簡體   English   中英

使用 Unity 5 UI 進行雙指縮放

[英]Pinch-To-Zoom with Unity 5 UI

我正在嘗試在基於 Unity UI 的應用程序中重新實現雙指縮放系統。 大約六個月前,我能夠通過使 UI 畫布成為常規 GameObject 的子項並操縱該對象的變換來一起破解一個,但自從更新到 Unity 5.5+ 后,我發現這不起作用。 我能得到的最接近的允許捏手勢改變畫布的比例因子,這 a) 可以根據它們的對齊方式使圖像、面板等不正確地調整大小,b) 一旦縮放就不允許我平移。

到目前為止,我所擁有的是:

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;
                }
            }
    }
}

正如我所說,這在一定程度上有效,但不能給我一個很好的統一縮放,也不能讓我平移畫布。 在此先感謝您的幫助。

將此腳本附加到要放大和縮小的畫布對象中

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;
            }
    }
}

提醒:此腳本僅適用於畫布對象

您可以使用此函數(只需將負 deltaMagnitudeDiff 傳遞給它)此外,最好以 ( 0.05 ) 之類的比率多重播放 deltaMagnitudeDiff

float currentScale = 1f;
void Zoom (float increment)
{
    currentScale += increment;
    if (currentScale >= maxScale)
    {
        currentScale = maxScale;
    }
    else if (currentScale <= minScale)
    {
        currentScale = minScale;
    }
    rectTransform.localScale = new Vector3 (currentScale, currentScale, 1);

    pan.ValidatePosition ();
}

對於平移,您可以使用以下內容:

public class Pan : MonoBehaviour
{
    public float Speed;

    Vector3 startDragPosition;

    public void BeginDrag ()
    {
        startDragPosition = Input.mousePosition;
    }

    public void Drag ()
    {
        transform.localPosition += (Input.mousePosition - startDragPosition) * Speed;
        startDragPosition = Input.mousePosition;

        ValidatePosition ();
    }

    public void ValidatePosition ()
    {
        var temp = transform.localPosition;

        var width = ((RectTransform)transform).sizeDelta.x;
        var height = ((RectTransform)transform).sizeDelta.y;

        var MaxX = 0.5f * width * Mathf.Max (0, transform.localScale.x - 1);
        var MaxY = 0.5f * height * Mathf.Max (0, transform.localScale.y - 1);

        var offsetX = transform.localScale.x * width * (((RectTransform)transform).pivot.x - 0.5f);
        var offsetY = transform.localScale.y * width * (((RectTransform)transform).pivot.y - 0.5f);

        if (temp.x < -MaxX + offsetX)
            temp.x = -MaxX + offsetX;
        else if (temp.x > MaxX + offsetX)
            temp.x = MaxX + offsetX;

        if (temp.y < -MaxY + offsetY)
            temp.y = -MaxY + offsetY;
        else if (temp.y > MaxY + offsetY)
            temp.y = MaxY + offsetY;

        transform.localPosition = temp;
}

只需從事件觸發器組件調用函數 ( BeginDrag & Drag )。

我使用捏縮放對象的操作是這樣的,當對象位於屏幕中間時,它可以在任何觸摸屏上工作:

if (Input.touchCount == 2)
        {
            //The distance between the 2 touches is checked and subsequently used to scale the
            //object by moving the 2 fingers further, or closer form eachother.
            Touch touch0 = Input.GetTouch(0);
            Touch touch1 = Input.GetTouch(1);
            if (isScaling)//this will only be done if scaling is true
            {
                float currentTouchDistance = getTouchDistance();
                float deltaTouchDistance = currentTouchDistance - touchDistanceOrigin;
                float scalePercentage = (deltaTouchDistance / 1200f) + 1f;

                Vector3 scaleTemp = transform.localScale;
                scaleTemp.x = scalePercentage * originalScale.x;
                scaleTemp.y = scalePercentage * originalScale.y;
                scaleTemp.z = scalePercentage * originalScale.z;

                //to make the object snap to 100% a check is being done to see if the object scale is close to 100%,
                //if it is the scale will be put back to 100% so it snaps to the normal scale.
                //this is a quality of life feature, so its easy to get the original size of the object.
                if (scaleTemp.x * 100 < 102 && scaleTemp.x * 100 > 98)
                {
                    scaleTemp.x = 1;
                    scaleTemp.y = 1;
                    scaleTemp.z = 1;
                }
                //here we apply the calculation done above to actually make the object bigger/smaller.
                transform.localScale = scaleTemp;


            }
            else
            {
                //if 2 fingers are touching the screen but isScaling is not true we are going to see if
                //the middle of the screen is looking at the object and if it is set isScalinf to true;
                Ray ray;
                RaycastHit hitTouch;
                ray = cam.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0));
                if (Physics.Raycast(ray, out hitTouch, 100f))
                {
                    if (hitTouch.transform == transform)
                    {
                        isScaling = true;
                        //make sure that the distance between the fingers on initial contact is used as the original distance
                        touchDistanceOrigin = getTouchDistance();
                        originalScale = transform.localScale;
                    }
                }
            }
        }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM