- 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