Unity对Content的拖动,缩放,简化ScrollView 的功能

// <summary>
    /// content拖动
    /// </summary>
    public class LandMapContentDragControl : MonoBehaviour, IPointerUpHandler, IPointerDownHandler, IBeginDragHandler, IDragHandler
    {
        public LandMap_WindowManager manager;
        public RectTransform leftMask;
        public RectTransform rightMask;
        public RectTransform topMask;
        public RectTransform downMask;
        private RectTransform rect;

        private float screenWidthRadiu;
        private float screenHeightRadiu;

        public bool bOpen;
        private bool bTwoTouchDown;
        private bool bDrag;

        /// <summary>
        /// 改变大小时的边界
        /// </summary>
        private float leftMinValue;
        private float rightMinValue;
        private float topMinValue;
        private float downMinVlaue;
     

        private Touch m_OldTouch1;
        private Touch m_OldTouch2;

        private Vector2 dragStartPos;
        private Vector2 concentStartPos;

        public float curScale;
        private float maxScale;
        private float minScale;
        private int oneSize;

        /// <summary>
        /// 拖动中心坐标
        /// </summary>
        public Vector2Int touchCenterLandPos;
        public Vector2 touchCenterPos;

        /// <summary>
        /// 遮罩默认值
        /// </summary>
        private float leftMaskDefaultValue;
        private float rightMaskDefaultValue;
        private float topMaskDefaultValue;
        private float downMaskDefaultValue;

        private float widthRatio;

        public void Init(LandMap_WindowManager manager)
        {
            this.manager = manager;
            rect = this.transform as RectTransform;
            InitWidth();
        }
        private void InitWidth()
        {
            if (Screen.width < Screen.height)
            {
                screenWidthRadiu = GameTools.DesignWidth / 2;
                screenHeightRadiu = (float)GameTools.DesignWidth / (float)GameTools.Width * (float)GameTools.Height / 2 - 90f;
            }
            else
            {
                screenWidthRadiu = (float)GameTools.DesignWidth / (float)GameTools.Width * (float)GameTools.Height / 2;
                screenHeightRadiu = GameTools.DesignWidth / 2 - 90f;
            }
            widthRatio = (float)GameTools.DesignWidth / (float)GameTools.Width;
            //Debug.Log("屏幕的宽度半径:" + screenWidthRadiu + ":  高度半径:" + screenHeightRadiu);
        }
        /// <summary>
        /// 计算遮罩的默认值
        /// </summary>
        private void CalculateMaskDefaultValue(int curType)
        {
            int minArean = 99;
            int maxArean = 0;
            foreach (var item in LocalData.Instance._openLandAreanDataDic)
            {
                if(item.Key > maxArean)
                {
                    maxArean = item.Key;
                }
                if(item.Key < minArean)
                {
                    minArean = item.Key;
                }
            }
            MapClassifyData data = MapClassifyDataDic.dataDic[curType];
            int mul = 96 / data.oneCount;
            leftMaskDefaultValue = (minArean % 10 - 1) * data.textureSize  * mul;
            rightMaskDefaultValue = (10 - maxArean % 10) * data.textureSize * mul;
            topMaskDefaultValue = (minArean / 10 ) * data.textureSize * mul;
            downMaskDefaultValue = ( 9 - maxArean / 10) * data.textureSize * mul;
            SetMaskHeight(leftMaskDefaultValue, rightMaskDefaultValue, topMaskDefaultValue, downMaskDefaultValue);
        }

        private void SetMaskHeight(float leftValue,float rightValue,float topValue,float downValue)
        {
            float defalutValue = rect.rect.width;
            leftMask.sizeDelta = new Vector2(leftValue, 0);
            rightMask.sizeDelta = new Vector2(rightValue, 0);
            topMask.sizeDelta = new Vector2(0, topValue);
            downMask.sizeDelta = new Vector2(0, downValue);
        }

        private float rollSpeed;
        public void CutTypeScaleRange(float minScale,float maxScale,float curScale,int curType,Vector2Int centerPos,int oneSize,float speed,bool bOnce)
        {
            this.minScale = minScale;
            this.maxScale = maxScale;
            this.curScale = curScale;
            this.oneSize = oneSize;
            this.touchCenterLandPos = centerPos;
            this.rollSpeed = speed;
            ChangeScale(bOnce);
            //CalculateMaskDefaultValue(curType);
        }


        public void OnPointerDown(PointerEventData eventData)
        {
#if UNITY_EDITOR
            CalculateMousePos(eventData.position);
#endif
            manager.OnPointerDown();
            dragStartPos = eventData.position;
            concentStartPos = rect.anchoredPosition;
        }

        public void OnPointerUp(PointerEventData eventData)
        {
            if (!bDrag)
            {
                manager.OnPointerUp(eventData.position);
            }
            if (Input.touchCount < 2)
            {
                bTwoTouchDown = false;
                bDrag = false;
            }
            //Debug.Log("屏幕触碰点的数量:" + Input.touchCount);
        }
        public void OnBeginDrag(PointerEventData eventData)
        {
            bDrag = true;
            manager.OnBeginDrag();
        }

        public void OnDrag(PointerEventData eventData)
        {
            if (Input.touchCount < 2 && !bTwoTouchDown)
            {
                Vector2 d_value = eventData.position - dragStartPos;

                Vector2 pos = concentStartPos + d_value;

                //判断是否超出边界,超出计算当前中心的坐标,x < 0 y < 0
                JudgeConcentPosOverstepBoundary(ref pos);

                rect.anchoredPosition = pos;
                touchCenterLandPos = manager.CalculateCurPos();
                touchCenterPos = eventData.position;
                //Debug.Log("判断是否超出边界,超出计算当前中心的坐标:" + pos + "  拖动中:" + eventData.position + " 拖动方向:" + d_value);
            }
        }
        /// <summary>
        /// 判断坐标是否超出边界
        /// </summary>
        /// <returns></returns>
        private void JudgeConcentPosOverstepBoundary(ref Vector2 pos)
        {
            if (pos.x > leftMinValue)//是判断超出边界
            {
                pos.x = leftMinValue;
            }
            if (pos.x < rightMinValue)
            {
                pos.x = rightMinValue;
            }

            if (pos.y < topMinValue)
            {
                pos.y = topMinValue;
            }
            if (pos.y > downMinVlaue)
            {
                pos.y = downMinVlaue;
            }
        }

        private void Update()
        {
            if (bOpen)
            {
#if UNITY_EDITOR
                MouseInput();
#endif
#if UNITY_ANDROID || UNITY_IOS
                TouchInput();
#endif
            }
        }
        /// <summary>
        /// 鼠标输入
        /// </summary>
        private void MouseInput()
        {
            float value = Input.GetAxis("Mouse ScrollWheel") * 0.1f;
            if (value != 0)
            {
                if(touchCenterLandPos == Vector2.zero)
                {
                    CalculateMousePos(Input.mousePosition);
                }
                ChangeConcentScale(value);
            }
        }
        /// <summary>
        /// 触屏输入
        /// </summary>
        private void TouchInput()
        {
            if (Input.touchCount == 2)
            {
                bTwoTouchDown = true;
                Touch newtouch1 = Input.GetTouch(0);
                Touch newtouch2 = Input.GetTouch(1);
                if (newtouch2.phase == TouchPhase.Began)
                {
                    m_OldTouch1 = newtouch1;
                    m_OldTouch2 = newtouch2;
                    CalculateTouchCenterPos(m_OldTouch1.position, m_OldTouch2.position);
                    return;
                }
                if (newtouch2.phase == TouchPhase.Ended)
                {
                    return;
                }
                float olddistance = Vector2.Distance(m_OldTouch1.position, m_OldTouch2.position);
                float newdistance = Vector2.Distance(newtouch1.position, newtouch2.position);
                float changScale = newdistance - olddistance;
                m_OldTouch1 = newtouch1;
                m_OldTouch2 = newtouch2;
                float d_v = 0.01f * rollSpeed;
                if (changScale > 0)
                {
                    changScale = d_v;
                }
                else if (changScale < 0)
                {
                    changScale = -d_v;
                }

                //Debug.Log("拖动改变的大小:" + changScale + "  当前大小:" + (olddistance - newdistance));
                ChangeConcentScale(changScale);
            }
            else if (bTwoTouchDown && Input.touchCount == 0)
            {
                bTwoTouchDown = false;
            }
        }
        /// <summary>
        /// 改变Concent显示的大小
        /// </summary>
        /// <param name="addValue"></param>
        public void ChangeConcentScale(float addValue)
        {
            curScale += addValue;
            if (curScale > maxScale)
            {
                curScale = maxScale;
                manager.AddCurType();
                return;
            }
            if (curScale < minScale)
            {
                curScale = minScale;
                manager.SubCurType();
                return;
            }
            //Debug.Log("改变Camera显示的大小:" + addValue + "  改之后的大小:" + curScale);

            ChangeScale(false);
        }
        /// <summary>
        /// 改变content大小,必须先确定sizeData
        /// </summary>
        public void ChangeScale(bool bOnce)
        {
            rect.localScale = Vector3.one * curScale;
            manager.CalculateImageBoundary();
            Vector2 sizeDalte = rect.rect.size * curScale;
            if(screenWidthRadiu == 0)
            {
                InitWidth();
            }
            leftMinValue = screenWidthRadiu;
            downMinVlaue = 180f;
            rightMinValue = -(sizeDalte.x - screenWidthRadiu);
            topMinValue = -(sizeDalte.y - screenHeightRadiu * 2 + 180f);

            Vector2 pos = GetTouchCenterAnchoredPos(bOnce);
            JudgeConcentPosOverstepBoundary(ref pos);
            rect.anchoredPosition = pos;
            //Debug.Log(string.Format("计算边界值,左边界值:{0},右边界值:{1},上边界值:{2},下边界值:{3},anchordPos;{4}", leftMinValue, rightMinValue, topMinValue, downMinVlaue, pos));
            //计算中心坐标
            manager.CalculateCurPos(touchCenterLandPos);
            manager.RefreshSelfLandItem();
        }

        /// <summary>
        ///  获取拖动过程中的中心坐标
        /// </summary>
        /// <param name="bOnce">是否是切换档位</param>
        /// <param name="bFroceZoom">是否是强制切换</param>
        /// <returns></returns>
        private Vector2 GetTouchCenterAnchoredPos(bool bOnce)
        {
            Vector2 pos = rect.anchoredPosition;
            if (touchCenterLandPos != Vector2Int.zero)
            {
                Vector2 landPos = new Vector2(touchCenterLandPos.x, touchCenterLandPos.y) * oneSize * curScale;//土地坐标对应的center坐标
                if (bOnce)
                {
                    if (screenWidthRadiu == 0)
                    {
                        InitWidth();
                    }
                    landPos -= new Vector2(screenWidthRadiu, screenHeightRadiu);
                }
                //Vector2 centerDis = new Vector2(screenWidthRadiu, screenHeightRadiu);
                pos = touchCenterPos - landPos;
                //Debug.Log("获取拖动过程中的中心坐标,TouchCenter坐标:" + touchCenterLandPos + "  屏幕距离:" + touchCenterPos + "  锚点坐标:" + pos + "  是否是第一次:" + bOnce);
            }
            return pos;
        }

        /// <summary>
        /// 计算拖动的中心坐标
        /// </summary>
        /// <param name="startPos"></param>
        /// <param name="endPos"></param>
        private void CalculateTouchCenterPos(Vector2 startPos,Vector2 endPos)
        {
            Vector2 dir = (endPos - startPos).normalized;
            float dis = Vector2.Distance(startPos, endPos) / 2f;
            Vector2 screenPos = startPos + dir * dis;
            //Debug.Log("计算拖动中心坐标,起点坐标:" + startPos + "  终点坐标:" + endPos + "  距离:" + dis + "  方向:" + dir + "  中心坐标:" + screenPos);
            CalculateMousePos(screenPos);
        }


        /// <summary>
        /// 计算鼠标停住的位置
        /// </summary>
        /// <param name="pos"></param>
        private void CalculateMousePos(Vector2 pos)
        {
            touchCenterPos = pos * widthRatio;
            touchCenterPos.y -= 180f;
            touchCenterLandPos = manager.AnchoredPosition2LandPos(rect.anchoredPosition, pos);
            //Debug.Log("屏幕拖动中心的位置:" + touchCenterLandPos + "  拖动的中心坐标:" + touchCenterPos + "  屏幕中心坐标:" + pos);
        }
      
    }

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity是一款专业的游戏开发引擎,但也可以用来实现窗口拖拽缩放功能。在Unity中,可以使用RectTransform组件来控制界面元素的位置和大小。接下来,我将介绍一种简单的方法来实现窗口的拖拽和缩放功能。 首先,在Unity中创建一个UI界面,并添加一个Image组件作为窗口的背景。然后,给窗口的Image组件添加一个拖拽脚本和一个缩放脚本。 拖拽脚本的作用是控制窗口的拖拽功能。在脚本中,我们可以通过监听鼠标按下、鼠标拖动和鼠标放开的事件来实现窗口的拖拽。具体步骤如下: 1. 在脚本中定义一个bool类型的变量,用于判断是否可以进行拖拽操作。 2. 在Update函数中,通过Input.GetMouseButtonDown和Input.GetMouseButtonUp函数判断鼠标是否按下或放开。如果鼠标按下,将上述bool变量设置为true,如果鼠标放开,将bool变量设置为false。 3. 还需要判断鼠标是否在窗口的范围内。可以使用RectTransform组件的rect属性获取窗口的矩形区域,然后使用RectTransformUtility类的ScreenPointToLocalPointInRectangle函数判断鼠标的位置是否在窗口的范围内。 4. 如果鼠标在窗口范围内并且bool变量为true,可以通过RectTransform组件的anchoredPosition属性来设置窗口的位置。 缩放脚本的作用是实现窗口的缩放功能。在脚本中,我们可以通过鼠标滚轮的输入来控制窗口的缩放。具体步骤如下: 1. 在脚本中定义一个float类型的变量,用于控制窗口的缩放比例。 2. 在Update函数中,通过Input.GetAxis函数来获取鼠标滚轮的输入值。 3. 根据鼠标滚轮的输入值来增加或减少窗口的缩放比例。可以使用RectTransform组件的sizeDelta属性来设置窗口的大小。 通过上述步骤,我们可以实现Unity中窗口的拖拽和缩放功能。这样用户就可以通过鼠标来拖动窗口并调整窗口的大小,提升用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值