zoukankan      html  css  js  c++  java
  • Unity 滚轮实现UGUI ScrollView的缩放

    本文原创,转载请注明出处http://www.cnblogs.com/AdvancePikachu/p/7908754.html

    前段时间在做一个类似AnimationCurve的可视化编辑器,其中在做内部缩放的时候略有所感,把利用滚轮+焦点的缩放分享一下。

    其中一个脚本处理内部逻辑

    public class ResizeScrollEvent : UnityEvent<float> { }
    
    public class UIScroll : MonoBehaviour, IScrollHandler
    {
        public float minFactor = 1;
        public float maxFactor = 3;
        public bool wholeSizeFactor = true;
    
        private ResizeScrollEvent _onResize = new ResizeScrollEvent();
        private float _sizeFactor = 1f;
    
        public ResizeScrollEvent OnResize { get { return _onResize; } }
        public float SizeFactor
        {
            get
            {
                if (wholeSizeFactor)
                    return Mathf.Round(_sizeFactor);
                return _sizeFactor;
            }
            set
            {
                SetFactor(value);
            }
        }
    
        [SerializeField]
        RectTransform content;
        [SerializeField]
        RectTransform viewport;
    
        Rect _rect;
        Vector2 _focusPos;
    
        void Start()
        {
            _rect = GetWorldRect(viewport);
            _focusPos = _rect.center;
        }
    
        public static Rect GetWorldRect(RectTransform rt)
        {
            Vector3[] cors_ = new Vector3[4];
            rt.GetWorldCorners(cors_);
            Vector2 center = cors_[0];
            float width = Mathf.Abs(cors_[0].x - cors_[2].x);
            float height = Mathf.Abs(cors_[0].y - cors_[2].y);
            Rect rect_ = new Rect(center.x, center.y, width, height);
            return rect_;
        }
    
        private void SetFactor(float value)
        {
            value = ClampFactorValue(value);
    
            if (value != _sizeFactor)
            {
                _sizeFactor = value;
                ChangeSizeFactor(_sizeFactor);
                _onResize.Invoke(_sizeFactor);
            }
        }
    
        private void ChangeSizeFactor(float v)
        {
         Vector2 viewportSize_ = _rect.size; //缩放过程中的焦点位置(此处为中心位置) //_focusPos = _rect.center; Rect contentRect_ = GetWorldRect(content); Vector2 contentSize_ = contentRect_.size; Vector2 contentCenter_ = contentRect_.center; Vector2 contentCenter2ViewportCenter_ = _focusPos - contentCenter_; float centerPosPercentX_ = contentCenter2ViewportCenter_.x / contentSize_.x; float centerPosPercentY_ = contentCenter2ViewportCenter_.y / contentSize_.y; Vector2 scorllSize_ = viewportSize_ + (v - 1) * viewportSize_ / 5; content.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, scorllSize_.x); content.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, scorllSize_.y); Vector2 sizeDelta_ = scorllSize_ - contentSize_; Vector2 posOffset_ = new Vector2(sizeDelta_.x * -centerPosPercentX_, sizeDelta_.y * -centerPosPercentY_); content.anchoredPosition += posOffset_; Vector3[] viewCorner_ = new Vector3[4]; Vector3[] contentCorner_ = new Vector3[4]; viewport.GetWorldCorners(viewCorner_); content.GetWorldCorners(contentCorner_); float xFixDelta_ = 0; float yFixDelta_ = 0; if (viewCorner_[0].x < contentCorner_[0].x) xFixDelta_ = viewCorner_[0].x - contentCorner_[0].x; if (viewCorner_[0].y < contentCorner_[0].y) yFixDelta_ = viewCorner_[0].y - contentCorner_[0].y; if (viewCorner_[2].x > contentCorner_[2].x) xFixDelta_ = viewCorner_[2].x - contentCorner_[2].x; if (viewCorner_[2].y > contentCorner_[2].y) yFixDelta_ = viewCorner_[2].y - contentCorner_[2].y; content.anchoredPosition += new Vector2(xFixDelta_, yFixDelta_); } private float ClampFactorValue(float value) { float factor_ = Mathf.Clamp(value, minFactor, maxFactor); if (wholeSizeFactor) factor_ = Mathf.Round(factor_); return factor_; } public void OnScroll(PointerEventData eventData) { if (!isActiveAndEnabled) return;         _focusPos = eventData.position;//焦点为鼠标所在位置 float delta_ = 0; if (Mathf.Abs(eventData.scrollDelta.x) > Mathf.Abs(eventData.scrollDelta.y)) delta_ = eventData.scrollDelta.x; else delta_ = eventData.scrollDelta.y; SetFactor(_sizeFactor + delta_); } }

      另一个脚本做触发

    public class NewBehaviourScript : MonoBehaviour
    {
        [SerializeField]
        Slider scaleSlider;
        [SerializeField]
        Text sliderValue;
        [SerializeField]
        UIScroll scrollView;
    
    	void Start ()
        {
            scaleSlider.wholeNumbers = true;
            scaleSlider.minValue = 1;
            scaleSlider.maxValue = 10;
            scaleSlider.onValueChanged.AddListener(OnSliderValueChange);
    
            scrollView.minFactor = scaleSlider.minValue;
            scrollView.maxFactor = scaleSlider.maxValue;
            scrollView.wholeSizeFactor = true;
            scrollView.OnResize.AddListener(OnScrollResized);
            scrollView.SizeFactor = 1;
    	}
    
        private void OnScrollResized(float value)
        {
            scaleSlider.value = value;
        }
    
        private void OnSliderValueChange(float value)
        {
            scrollView.SizeFactor = value;
            sliderValue.text = value.ToString();
        }
    }
    

     

    PS:刚开始以为是版本问题,后来发现是我的Cavans设置有问题,修改后问题解决!

    附5.6.4f1项目文件https://files.cnblogs.com/files/AdvancePikachu/scroll.rar

  • 相关阅读:
    【Linux】Vim编辑器-批量注释与反注释
    java_部署jar
    linux_UBUNTU 12.04 上使用 SQUID 架设HTTP正向代理服务器
    crawler_java应用集锦9:httpclient4.2.2的几个常用方法,登录之后访问页面问题,下载文件_设置代理
    linux_coom _ Linux文件比较,文本文件的交集、差集与求差
    linux_之sed用法
    算法-跑道与马-百度面试题
    《Python》常用内置模块
    《Python》内置方法进阶和常用模块
    《Python》反射、内置方法(__str__,__repr__)
  • 原文地址:https://www.cnblogs.com/AdvancePikachu/p/7908754.html
Copyright © 2011-2022 走看看