Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pinch-To-Zoom with Unity 5 UI

I'm trying to re-implement a pinch-to-zoom system in a Unity UI-based app. About six months ago I was able to hack one together by making the UI canvas a child of a regular GameObject, and manipulating that object's transform, but since updating to Unity 5.5+ I find this doesn't work. The closest I can get allows the pinch gesture to change the canvas' scaleFactor, which a) can make images, panels, etc resize improperly depending on their alignments, and b) won't allow me to pan once zoomed.

What I have so far is this:

public class PinchToZoomScaler : MonoBehaviour {

    public Canvas canvas; // The canvas
    public float zoomSpeed = 0.5f;        // The rate of change of the canvas scale factor

    public float _resetDuration = 3.0f;
    float _durationTimer = 0.0f;

    float _startScale = 0.0f;

    void Start() {
        _startScale = canvas.scaleFactor;
    }

    void Update()
    {
            // If there are two touches on the device...
            if (Input.touchCount == 2) {
                // Store both touches.
                Touch touchZero = Input.GetTouch (0);
                Touch touchOne = Input.GetTouch (1);

                // Find the position in the previous frame of each touch.
                Vector2 touchZeroPrevPos = touchZero.position - touchZero.deltaPosition;
                Vector2 touchOnePrevPos = touchOne.position - touchOne.deltaPosition;

                // Find the magnitude of the vector (the distance) between the touches in each frame.
                float prevTouchDeltaMag = (touchZeroPrevPos - touchOnePrevPos).magnitude;
                float touchDeltaMag = (touchZero.position - touchOne.position).magnitude;

                // Find the difference in the distances between each frame.
                float deltaMagnitudeDiff = prevTouchDeltaMag - touchDeltaMag;

                // ... change the canvas size based on the change in distance between the touches.
                canvas.scaleFactor -= deltaMagnitudeDiff * zoomSpeed;

                // Make sure the canvas size never drops below 0.1
                canvas.scaleFactor = Mathf.Max (canvas.scaleFactor, _startScale);
                canvas.scaleFactor = Mathf.Min (canvas.scaleFactor, _startScale * 3.0f);

                _durationTimer = 0.0f;
            } else {
                _durationTimer += Time.deltaTime;

                if (_durationTimer >= _resetDuration) {
                    canvas.scaleFactor = _startScale;
                }
            }
    }
}

As I said, this works to a degree, but doesn't give me a nice uniform zooming, not does it allow me to pan the canvas. Thanks in advance for any help.

like image 673
Vanguard3000 Avatar asked Nov 08 '22 02:11

Vanguard3000


1 Answers

Attach this script in canvas object which you want to zoom in and zoom out by pinch

using UnityEngine;
using UnityEngine.EventSystems;

public class ObjectScalling : MonoBehaviour, IPointerDownHandler, IPointerUpHandler 
{
    private bool _isDragging;
    private float _currentScale;
    public float minScale, maxScale;
    private float _temp = 0;
    private float _scalingRate = 2;

    private void Start() 
    {
        _currentScale = transform.localScale.x;
    }

    public void OnPointerDown(PointerEventData eventData) 
    {
        if (Input.touchCount == 1) 
        {
            _isDragging = true;
        }
    }


    public void OnPointerUp(PointerEventData eventData) 
    {
        _isDragging = false;
    }


    private void Update() 
    {
        if (_isDragging)
            if (Input.touchCount == 2) 
            {
                transform.localScale = new Vector2(_currentScale, _currentScale);
                float distance = Vector3.Distance(Input.GetTouch(0).position, Input.GetTouch(1).position);
                if (_temp > distance) 
                {
                    if (_currentScale < minScale)
                        return;
                    _currentScale -= (Time.deltaTime) * _scalingRate;
                }

                else if (_temp < distance) 
                {
                    if (_currentScale > maxScale)
                        return;
                    _currentScale += (Time.deltaTime) * _scalingRate;
                }

                _temp = distance;
            }
    }
}

Reminder: This script only works in canvas objects

like image 165
Shubham Pandit Avatar answered Nov 14 '22 21:11

Shubham Pandit