Unity多指触摸UI跟随和缩放(缩放点在两指中间)

坑不是很多,直接放代码了。有问题联系QQ412484723,直接挂到UI上就可以用
思路就是ui的坐标位置始终跟第一次按下去的位置的x距离和y距离保持一致,单指的时候直接是第一次按下去的坐标,双指的时候是当前帧的两个点位置中心。之所以用前一帧和当前帧的touch数量判断是为了避免更多点触摸造成位置不准确的问题
在两指中间的缩放,我的思路是先按比例缩放,上一帧两手指的距离/上一帧的scale等于当前帧的两手指距离/scale,这样可以求出scale,记录上一帧两手指中心位置在要缩放的ui下的坐标和ui父物体下的坐标,然后计算当前两手指中心位置在ui下的坐标和父物体下的坐标,用ui的pos加上这两个值就行了。还有一种方法,按下去的时候记录两个手指在ui中坐标,下一帧的时候两个手指在屏幕的坐标换算到ui本地坐标也是上两个值,根据前后四个点反推坐标轴的旋转位移和缩放,这里给出第一种的实现。(canvas用的camera模式,这里直接用的maincamera,具体的应该getcomponentinparent().worldcamera这样获取camera)

链接: https://pan.baidu.com/s/1iS_0CltNGaY3z7bSYIOwGA 提取码: hz9g 复制这段内容后打开百度网盘手机App,操作更方便哦

using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.UI;

public class PinchZoom : MonoBehaviour
{
    private bool _isMousePressed;
    public float MaxScale = 6.0f;
    public float MinScale = 0.6f;

private Vector2 _midPoint = new Vector2(0, 0);

private Vector2 _start1;
private Vector2 _start2;

private Vector2 _startMid;
private Vector2 _touchScale;
private Vector2 _touchPos;
private Vector2 _startMouse;
private Vector2 pp3;
private Vector2 pp4;
private float _touchLength;

Vector2 aPos1 = new Vector2();
Vector2 aPos2 = new Vector2();

private float _x;
private float _y;
private float _pressTime;
//上一帧touch数量
private int _priorInputCount;

private RectTransform _t;

void Start()
{
    _t = (RectTransform)transform;
    var c = GetComponentInParent();
    Application.targetFrameRate = 60;
    Debug.Log(c.worldCamera.name);
}
void Update()
{
    //CheckZoomForMobile();
    CheckMovingForMobile();
}

private void CheckMovingForMobile()
{

#if UNITY_EDITOR_WIN
        if (Input.GetMouseButtonDown(0))
            _isMousePressed = true;
        else if (Input.GetMouseButtonUp(0))
            _isMousePressed = false;

    if (_isMousePressed)
        _pressTime += Time.deltaTime;
    else
        _pressTime = 0;

    //Zoom out
    if (Input.GetAxis("Mouse ScrollWheel") > 0)
    {
        var pos1 = ScreenToAnchorPosition(Input.mousePosition, _t);

        if (_t.localScale.x < MaxScale)
            _t.localScale *= 1.1f;

        var pos2 = ScreenToAnchorPosition(Input.mousePosition, _t);
        Debug.Log(pos1 + "/" + pos2);
        _t.anchoredPosition += (pos2 - pos1) * _t.localScale.x;
    }
    //Zoom in  
    if (Input.GetAxis("Mouse ScrollWheel") < 0)
    {
        var pos1 = ScreenToAnchorPosition(Input.mousePosition, _t);

        if (_t.localScale.x > MinScale)
            _t.localScale *= 0.9f;

        var pos2 = ScreenToAnchorPosition(Input.mousePosition, _t);
        _t.anchoredPosition += (pos2 - pos1) * _t.localScale.x;
    }

    if (_pressTime > 0.05f)
    {
        var x = Input.mousePosition.x;
        var y = Input.mousePosition.y;
        _t.anchoredPosition += new Vector2(x - _x, y - _y);
    }

    _x = Input.mousePosition.x;
    _y = Input.mousePosition.y;
#endif

    //text1.text=_midPoint.ToString();
    if (Input.touchCount == 1)
    {
        var aPos = ScreenToAnchorPosition(Input.GetTouch(0).position, transform.parent.transform as RectTransform);
        //第一个点按下或者其余点离开的时候
        if (_priorInputCount != 1)
        {
            _x = aPos.x - _t.anchoredPosition.x;
            _y = aPos.y - _t.anchoredPosition.y;
        }
        _midPoint = aPos;
        _t.anchoredPosition = new Vector2(_midPoint.x - _x, _midPoint.y - _y);
    }

    if (Input.touchCount == 2)
    {
        //第二个点按下或者其余点离开的时候
        var iPos1 = Input.GetTouch(0).position;
        var iPos2 = Input.GetTouch(1).position;

        _start1 = ScreenToAnchorPosition(iPos1, _t);
        _start2 = ScreenToAnchorPosition(iPos2, _t);

        if (_priorInputCount != 2)
        {
            _touchScale = _t.localScale;
            _touchPos = _t.anchoredPosition;
            _touchLength = Vector2.Distance(iPos1, iPos2);
        }

        var pos1 = new Vector2((_start1.x + _start2.x) / 2, (_start1.y + _start2.y) / 2);

        var curLength = Vector2.Distance(iPos1, iPos2);

        var scale = curLength * _touchScale.x / _touchLength;
        scale = Mathf.Clamp(scale, MinScale, MaxScale);
        _t.localScale = new Vector3(scale, scale, 1);

        var p1 = ScreenToAnchorPosition(Input.GetTouch(0).position, _t);
        var p2 = ScreenToAnchorPosition(Input.GetTouch(1).position, _t);

        var pos2 = new Vector2((p1.x + p2.x) / 2, (p1.y + p2.y) / 2);

        _t.anchoredPosition += (pos2 - pos1) * scale;

        if(_priorInputCount==2)
        {
            var pp1 = ScreenToAnchorPosition(iPos1, _t.parent.transform as RectTransform);
            var pp2 = ScreenToAnchorPosition(iPos2, _t.parent.transform as RectTransform);

            var curMid = new Vector2((pp1.x + pp2.x) / 2, (pp1.y + pp2.y) / 2);
            var priorMid=new Vector2((pp3.x + pp4.x) / 2, (pp3.y + pp4.y) / 2);
            _t.anchoredPosition += curMid - priorMid;
        }

        pp3 = ScreenToAnchorPosition(iPos1, _t.parent.transform as RectTransform);
        pp4 = ScreenToAnchorPosition(iPos2, _t.parent.transform as RectTransform);
    }

    _priorInputCount = Input.touchCount;
}


Vector2 ScreenToAnchorPosition(Vector2 pos, RectTransform rT)
{
    Vector2 position;
    RectTransformUtility.ScreenPointToLocalPointInRectangle(rT, pos, Camera.main, out position);
    return position;
}

}

你可能感兴趣的:(Unity)