greyBow
greyBow

Reputation: 1348

Image jumps to its center point when dragged with a mouse

Hoping someone has a quick answer for this one as I haven't been able to figure this out. Rather than have the image jumping to center itself on the mouse cursor, I'd like to be able to drag the image from any place on the image without the jump. I know it has something to do with referencing the mouse position against the image or reseting the origin point of the image to the mouse location, but I don't know how to code it. Has anyone done this already? Using C#.

Vector3 partsPanelScale;
public Vector3 buildPanelScale;

public Transform placeholderParent = null;
public Transform parentToReturnTo = null;

GameObject placeholder = null;

public GameObject animalPart;

public GameObject trashCan; 
public GameObject partsPanel;
public GameObject partsWindow;
GameObject buildBoard;
GameObject dragLayer;

private float _mX; // holds current eventData.position.x
private float _mY; // holds current eventData.position.y
private float _pmX;// holds previous eventData.position.x
private float _pmY;// holds previous eventData.position.y

void Start ()
{
    dragLayer = GameObject.FindGameObjectWithTag("DragLayer");
    buildBoard = GameObject.FindGameObjectWithTag("Board");
    partsPanel = GameObject.FindGameObjectWithTag("Parts");
    partsWindow = GameObject.FindGameObjectWithTag("PartsWindow");
    trashCan = GameObject.FindGameObjectWithTag("Trash");
}

#region IPointerClickHandler implementation

public void OnPointerClick (PointerEventData eventData)
{
    if(transform.parent.gameObject == buildBoard)
    {
        transform.SetAsLastSibling();
    }
}

#endregion

#region IBeginDragHandler implementation

public void OnBeginDrag (PointerEventData eventData)
{
    // each frame updates the current position of the mouse.
    _mX = eventData.position.x;
    _mY = eventData.position.y;

    // create placeholder gap and hold correct position in layout
    placeholder = new GameObject();
    placeholder.transform.SetParent(transform.parent);
    placeholder.transform.SetSiblingIndex(transform.GetSiblingIndex());

    if(transform.parent.gameObject == partsPanel)
    {
        partsPanelScale = transform.localScale;
    }

    parentToReturnTo = transform.parent;                                    // store current parent location
    placeholderParent = parentToReturnTo;                                   // set placeholder gameobject transform

    GetComponent<CanvasGroup>().blocksRaycasts = false;                     // turn off image raycasting when dragging image in order to see what's behind the image            
}

#endregion

#region IDragHandler implementation

float distance = 0;



public void OnDrag (PointerEventData eventData)
{

    // Divided the difference by 6 to reduce the speed of dragging.
    transform.position = new Vector3
        (
            (_pmX - _mX)/6 + transform.position.x,
            (_pmY - _mY)/6 + transform.position.y,
            distance
            );

    // Vector3 mousePosition = new Vector3(eventData.position.x, eventData.position.y, distance);
    // Vector3 objPosition = Camera.main.ViewportToScreenPoint(mousePosition);
    // transform.position = mousePosition;                                  // set object coordinates to mouse coordinates

    if(transform.parent.gameObject == partsPanel)
    {
        transform.SetParent(dragLayer.transform);                           // pop object to draglayer to move object out of partsPnael
    }

    if(transform.parent.gameObject == buildBoard)
    {
        // Constrain drag to boundaries of buildBoard Code
    }
}

#endregion

#region IEndDragHandler implementation

public void OnEndDrag (PointerEventData eventData)
{
    // end of the drag. set the previous position.
    _pmX = _mX;
    _pmY = _mY;

    transform.SetParent(parentToReturnTo);                                  // Snaps object back to orginal parent if dropped outside of a dropzone
    transform.SetSiblingIndex(placeholder.transform.GetSiblingIndex());     // Returns card back to placeholder location

    GetComponent<CanvasGroup>().blocksRaycasts = true;                      // turn Raycast back on
    Destroy(placeholder);                                                   // kill the placeholder if object hits a drop zone or returns to parts panel

    if(transform.parent.gameObject == buildBoard)
    {
        // Debug.Log ("Your sprite is now on the " + transform.parent.name);

        transform.localScale = buildPanelScale;
        transform.SetAsLastSibling();                                       // always place last piece on top
    }

    if(transform.parent.gameObject == partsPanel)
    {
        transform.localScale = partsPanelScale;
    }
}

#endregion

Upvotes: 0

Views: 917

Answers (1)

M.kazem Akhgary
M.kazem Akhgary

Reputation: 19179

To drag correctly you need both Previous and Current position of the mouse.

Because each time you move mouse the Image should Move a bit (at x and y coordinate) from its previous position.

If you just use the current position and directly set it to image the resault will be jump over the screen.

You have to Transform the transformation of image by getting differences of previous and current position (x2 - x1 , y2 - y1).Then set the Final transformation to the Image transform.

You also need MouseOver event to update the positions. (orMouseMove)

private double _mX; // holds current eventData.position.x
private double _mY; // holds current eventData.position.y
private double _pmX;// holds previous eventData.position.x
private double _pmY;// holds previous eventData.position.y

// each frame updates the current position of the mouse.
private void MouseOver(PointerEventData eventData)
{
    _mX = eventData.position.x;
    _mY = eventData.position.y;
}

public void OnDrag (PointerEventData eventData)
{
    transform.position = new Vector3D((_pmX - _mX)/6 + transform.position.x,
                                      (_pmY - _mY)/6 + transform.position.y, distance);
    // Divided the difference by 6 to reduce the speed of dragging.

    //...

    // end of the drag. set the previous position.
    _pmX = _mX;
    _pmY = _mY;
}

Note that class names and events i have used may differ from unity3d.

If you drag from right to left but image goes from left to right replace _pmX - mX with _mX - _pmX.

If you drag from up to down but image goes from down to up replace _pmY - mY with _mY - _pmY.

Upvotes: 1

Related Questions