PC&Android通用移动、放大、缩小

1.PC&Android适用同样的移动代码

首先PC端的点击事件在Android端也同样适用,所以我们可以不用再写一次移动的代码。然后因为Android端是通过手指位置和数量进行判断的,如果直接使用PC端的移动代码会有些小bug。所以我们在结合两者使用的时候需要对移动操作的代码加以限制,让只用一根手指触碰的时候才会触发移动的代码,如果出现两根或多根手指则肯定是在Android设备上运行,此时放大缩小就只能使用Android特定的代码了。

2.通用代码如下

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;

public class MapControl : MonoBehaviour, IPointerEnterHandler, IPointerDownHandler, IDragHandler, IPointerUpHandler
{
    private Vector3 targetScreen;// 目标物体的屏幕空间坐标  
    private Vector3 targetWorld;// 目标物体的世界空间坐标  
    private Transform target;// 目标物体的空间变换组件  
    private Vector3 mouseScreen;// 鼠标的屏幕空间坐标  
    private Vector3 start;//初始位置
    private Vector3 dragStartPos;//拖拽前位置

    private RectTransform canvas;//得到canvas的ugui坐标
    private RectTransform imgRect;//得到图片的ugui坐标
    Vector2 offset = new Vector3();//用来得到鼠标和图片的差值

    float maxX, maxY, minX, minY;

    public static bool isExitMap=true;

    private Vector2 oldPosition1;
    private Vector2 oldPosition2;

    void Awake()
    {
        target = transform;
        start = transform.localPosition;

        canvas = GameObject.Find("Canvas").GetComponent<RectTransform>();
        imgRect = GetComponent<RectTransform>();
        dragStartPos = transform.localPosition;
    }

    private void Update()
    {
        ScrollWheelControl();
        AndroidScrollWheelControl();
    }
    void ScrollWheelControl()//鼠标滑轮滚动控制物体大小
    {
        if (isExitMap) return;
        float scaleOffset = Input.GetAxis("Mouse ScrollWheel");
        if ((transform.localScale.x + scaleOffset) <= 3 && (transform.localScale.x + scaleOffset) >= 1)
        {
            transform.localScale = new Vector3(transform.localScale.x + scaleOffset, transform.localScale.y + scaleOffset, transform.localScale.z + scaleOffset);

            maxX = 950 * (transform.localScale.x - 1);
            maxY = 500 * (transform.localScale.x - 1);
            minX = -950 * (transform.localScale.x - 1);
            minY = -500 * (transform.localScale.x - 1);

            if ((transform.localScale.x - 1) == 0)
            {
                maxX =20;
                maxY =20;
                minX =-20;
                minY =-20;
            }

            if (scaleOffset < 0)//缩放的时候逐渐返回原点(防止缩放后视界停留在最大视界外)
            {
                transform.localPosition = Vector3.MoveTowards(transform.localPosition, start, 100f);
            }
        }
    }

    void AndroidScrollWheelControl()
    {
        if (Input.anyKey)
        {
            if (Input.touchCount >1)
            {
                if (Input.GetTouch(0).phase == TouchPhase.Moved && Input.GetTouch(1).phase == TouchPhase.Moved)
                {
                    Vector2 tempPosition1 = Input.GetTouch(0).position;
                    Vector2 tempPosition2 = Input.GetTouch(1).position;
                    if (isEnlarge(oldPosition1, oldPosition2, tempPosition1, tempPosition2))
                    {
                        float oldScale = transform.localScale.x;
                        float newScale = oldScale +0.1f;
                        transform.localScale = new Vector3(newScale, newScale, newScale);
                    }
                    else
                    {
                        float oldScale = transform.localScale.x;
                        float newScale = oldScale -0.1f;
                        transform.localScale = new Vector3(newScale, newScale, newScale);
                        transform.localPosition = Vector3.MoveTowards(transform.localPosition, start, 100f);
                    }
                    //备份上一次触摸点的位置,用于对比   
                    oldPosition1 = tempPosition1;
                    oldPosition2 = tempPosition2;
                }
                if (transform.localScale.x >= 3)
                    transform.localScale = new Vector3(3, 3, 3);
                if (transform.localScale.x <= 1)
                    transform.localScale = new Vector3(1, 1, 1);
            }
        }
    }
    bool isEnlarge(Vector2 oP1, Vector2 oP2, Vector2 nP1, Vector2 nP2)
    {
        //函数传入上一次触摸两点的位置与本次触摸两点的位置计算出用户的手势   
        var leng1 = Mathf.Sqrt((oP1.x - oP2.x) * (oP1.x - oP2.x) + (oP1.y - oP2.y) * (oP1.y - oP2.y));
        var leng2 = Mathf.Sqrt((nP1.x - nP2.x) * (nP1.x - nP2.x) + (nP1.y - nP2.y) * (nP1.y - nP2.y));
        if (leng1 < leng2)
            return true;//放大手势
        else
            return false;//缩小手势
    }

    public void OnPointerEnter(PointerEventData eventData)
    {
        if (Input.anyKey && Input.touchCount > 1)
            return;
        isExitMap = false;
    }
    void IPointerDownHandler.OnPointerDown(PointerEventData eventData)
    {
        if (Input.anyKey && Input.touchCount > 1)
            return;
        Vector2 mouseDown = eventData.position;    //记录鼠标按下时的屏幕坐标
        Vector2 mouseUguiPos = new Vector2();   //定义一个接收返回的ugui坐标
        bool isRect = RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas, mouseDown, eventData.enterEventCamera, out mouseUguiPos);
        if (isRect)   //如果在
        {
            //计算图片中心和鼠标点的差值
            offset = imgRect.anchoredPosition - mouseUguiPos;
        }
    }

    void IDragHandler.OnDrag(PointerEventData eventData)
    {
        if (Input.anyKey && Input.touchCount > 1)
            return;
        dragStartPos = transform.localPosition;
        Vector2 mouseDrag = eventData.position;   //当鼠标拖动时的屏幕坐标
        Vector2 uguiPos = new Vector2();   //用来接收转换后的拖动坐标
                                           //和上面类似
        bool isRect = RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas, mouseDrag, eventData.enterEventCamera, out uguiPos);
        if (isRect)
        {
            //设置图片的ugui坐标与鼠标的ugui坐标保持不变
            imgRect.anchoredPosition = offset + uguiPos;
            LimitArea();
        }
    }

    void IPointerUpHandler.OnPointerUp(PointerEventData eventData)
    {
        if (Input.anyKey && Input.touchCount > 1)
            return;
        offset = Vector2.zero;
        if(transform.localScale.x==1)
            imgRect.localPosition = new Vector3(0, 0, imgRect.localPosition.z);
    }

    void LimitPos()//根据ui顶点的屏幕坐标限制拖动范围,不受pivot影响(严格限制)
    {
        //左下,左上,右上,右下——以屏幕左下为原点
        gameObject.GetComponent<RectTransform>().GetWorldCorners(corners);
        if (corners[0].x > (Screen.width / 2))
            transform.localPosition = dragStartPos;
        if (corners[0].y > (Screen.height / 2))
            transform.localPosition = dragStartPos;
        if (corners[2].x < (Screen.width / 2))
            transform.localPosition = dragStartPos;
        if (corners[2].y < (Screen.height / 2))
            transform.localPosition = dragStartPos;
    }

    void LimitPos1()//根据ui顶点的屏幕坐标限制拖动范围,不受pivot影响(果冻效果,放在updata里运行)
    {
        if (isDraging)
            return;
        //左下,左上,右上,右下——以屏幕左下为原点
        gameObject.GetComponent<RectTransform>().GetWorldCorners(corners);
        if (corners[0].x > (Screen.width / 2))
            transform.localPosition = new Vector2(transform.localPosition.x - (corners[0].x - (Screen.width/2)), transform.localPosition.y);
        if (corners[0].y > (Screen.height / 2))
            transform.localPosition = new Vector2(transform.localPosition.x, transform.localPosition.y-(corners[0].y - (Screen.height / 2)));
        if (corners[2].x < (Screen.width / 2))
            transform.localPosition = new Vector2(transform.localPosition.x - (corners[2].x - (Screen.width / 2)), transform.localPosition.y);
        if (corners[2].y < (Screen.height / 2))
            transform.localPosition = new Vector2(transform.localPosition.x, transform.localPosition.y-(corners[2].y - (Screen.height / 2)));
    }
}


版权声明:本文为HAL2020原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。