- Home /
how to move an UI image just in the surface of the canvas???
i have an ui image draggable , but I want to move it just inside the canvas. the code i have allows me to move the image but not within the limits of canvas. i use unity 4.6 This is my code:
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections;
public class DragUI : MonoBehaviour, IPointerDownHandler, IPointerUpHandler {
public Vector2 Canvas_Size;
public Vector2 a;
//public float b;
public RectTransform Rt; /***/
public GameObject bot; /****/
private bool mouseDown = false;
private Vector3 startMousePos;
private Vector3 startPos;
public void OnPointerDown(PointerEventData ped)
{
//BoxCollider2D.widht =
//Canvas.
mouseDown = true;
startPos = transform.position;
startMousePos = Input.mousePosition;
}
/*******************************************/
void Get()
{
Rt = bot.GetComponent<RectTransform>();
a.x = Rt.rect.height;
a.y = Rt.rect.width;
//Rt.rect.center = a;
}
/***********************************************/
public void OnPointerUp(PointerEventData ped)
{
mouseDown = false;
}
void Update ()
{
if (mouseDown) {
Vector3 currentPos = Input.mousePosition;
Vector3 diff = currentPos - startMousePos;
Vector3 pos = startPos + diff;
transform.position = pos;
}
//it is the test on the canvas limits
if(transform.position.x <= -(Rt.rect.width/2 ))
{
transform.position = new Vector2(-(Rt.rect.width/2), transform.position.y);
}
else if (transform.position.x >= (Rt.rect.width/2))
{
transform.position = new Vector2((Rt.rect.width/2), transform.position.y);
//transform.position.x = b; //Rt.rect.width;
}
if(transform.position.y <= -(Rt.rect.width /2))
{
transform.position = new Vector2(transform.position.x, -(Rt.rect.width/2 ));
}
else if(transform.position.y >= (Rt.rect.width/2 ))
{
transform.position = new Vector2(transform.position.x, (Rt.rect.width/2));
}
//a = new Vector2(0, 0);
}
}
help me please
Thank you
Answer by Mmmpies · Feb 01, 2015 at 12:21 PM
Hey @LAFI that code I updated in the last question works perfectly well for canvases as well as panels, in fact it'll work with any two objects that have a RectTransform in the new UI.
I'll post the updated code here as well just make the Canvas the ParentRT and the image MyRect.
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System.Collections;
public class DragUI : MonoBehaviour, IPointerDownHandler, IPointerUpHandler {
private bool mouseDown = false;
private Vector3 startMousePos;
private Vector3 startPos;
private bool restrictX;
private bool restrictY;
private float fakeX;
private float fakeY;
private float myWidth;
private float myHeight;
public RectTransform ParentRT;
public RectTransform MyRect;
void Start()
{
myWidth = (MyRect.rect.width + 5) / 2;
myHeight = (MyRect.rect.height + 5) / 2;
}
public void OnPointerDown(PointerEventData ped)
{
mouseDown = true;
startPos = transform.position;
startMousePos = Input.mousePosition;
}
public void OnPointerUp(PointerEventData ped)
{
mouseDown = false;
}
void Update ()
{
if (mouseDown) {
Vector3 currentPos = Input.mousePosition;
Vector3 diff = currentPos - startMousePos;
Vector3 pos = startPos + diff;
transform.position = pos;
if(transform.localPosition.x < 0 - ((ParentRT.rect.width / 2) - myWidth) || transform.localPosition.x > ((ParentRT.rect.width / 2) - myWidth))
restrictX = true;
else
restrictX = false;
if(transform.localPosition.y < 0 - ((ParentRT.rect.height / 2) - myHeight) || transform.localPosition.y > ((ParentRT.rect.height / 2) - myHeight))
restrictY = true;
else
restrictY = false;
if(restrictX)
{
if(transform.localPosition.x < 0)
fakeX = 0 - (ParentRT.rect.width / 2) + myWidth;
else
fakeX = (ParentRT.rect.width / 2) - myWidth;
Vector3 xpos = new Vector3 (fakeX, transform.localPosition.y, 0.0f);
transform.localPosition = xpos;
}
if(restrictY)
{
if(transform.localPosition.y < 0)
fakeY = 0 - (ParentRT.rect.height / 2) + myHeight;
else
fakeY = (ParentRT.rect.height / 2) - myHeight;
Vector3 ypos = new Vector3 (transform.localPosition.x, fakeY, 0.0f);
transform.localPosition = ypos;
}
}
}
}
Really you need to tick questions that have been answered correctly. It benefits you as well because some people won't help if someone gets a reputation for not marking correct answers.
To make this a bit more dynamic I added the following lines into Start
this.ParentRT = this.transform.parent.GetComponent<RectTransform>();
this.$$anonymous$$yRect = this.GetComponent<RectTransform>();
This will make it so you don't have to drag the RectTransforms into the editor.
Answer by troien · Feb 01, 2015 at 01:10 PM
This is a piece of code I made using the example Unity provides. (Forum post and asset store)
using UnityEngine;
using UnityEngine.EventSystems;
public class DragableUI : UIBehaviour, IBeginDragHandler, IDragHandler
{
/// <summary>
/// The RectTransform that we are able to drag around.
/// if null: the transform this Component is attatched to is used.
/// </summary>
public RectTransform dragObject;
/// <summary>
/// The area in which we are able to move the dragObject around.
/// if null: canvas is used
/// </summary>
public RectTransform dragArea;
private Vector2 originalLocalPointerPosition;
private Vector3 originalPanelLocalPosition;
private RectTransform dragObjectInternal
{
get
{
if (dragObject == null)
return (transform as RectTransform);
else
return dragObject;
}
}
private RectTransform dragAreaInternal
{
get
{
if (dragArea == null)
{
RectTransform canvas = transform as RectTransform;
while (canvas.parent != null && canvas.parent is RectTransform)
{
canvas = canvas.parent as RectTransform;
}
return canvas;
}
else
return dragArea;
}
}
public void OnBeginDrag(PointerEventData data)
{
originalPanelLocalPosition = dragObjectInternal.localPosition;
RectTransformUtility.ScreenPointToLocalPointInRectangle(dragAreaInternal, data.position, data.pressEventCamera, out originalLocalPointerPosition);
}
public void OnDrag(PointerEventData data)
{
Vector2 localPointerPosition;
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(dragAreaInternal, data.position, data.pressEventCamera, out localPointerPosition))
{
Vector3 offsetToOriginal = localPointerPosition - originalLocalPointerPosition;
dragObjectInternal.localPosition = originalPanelLocalPosition + offsetToOriginal;
}
ClampToArea();
}
// Clamp panel to dragArea
private void ClampToArea()
{
Vector3 pos = dragObjectInternal.localPosition;
Vector3 minPosition = dragAreaInternal.rect.min - dragObjectInternal.rect.min;
Vector3 maxPosition = dragAreaInternal.rect.max - dragObjectInternal.rect.max;
pos.x = Mathf.Clamp(dragObjectInternal.localPosition.x, minPosition.x, maxPosition.x);
pos.y = Mathf.Clamp(dragObjectInternal.localPosition.y, minPosition.y, maxPosition.y);
dragObjectInternal.localPosition = pos;
}
}
The reason why I post this is because even though @Mmmpies his answer does work in some cases, this code works better when you change the pivot or when you change the Render Mode of the Canvas to 'Screen Space - Camera' or 'World Space'.
ps. I did make it in a way that it uses default values when you leave dragObject or dragArea empty/null, though it is better for performance when you set those values in the inspector ;)
@troien Thank you for your answer you helped me more than you think ;) :)
Thanks @troien. This is exactly what i am looking for. it helped me a lot.
Thanks so much for this. Anybody would know how to make it react to right mouse clicks?
Your answer
Follow this Question
Related Questions
Drag object by Touch quickly 1 Answer
2d image does not scale/stretch correctly 2 Answers
Looking for picture in picture effect using Canvas Elements and Cinemachine follow target 0 Answers
How do I make UI elements go behind my 2D game objects? 1 Answer
Should UI Canvas be used for games similar to 2048? 1 Answer