zoukankan      html  css  js  c++  java
  • 循环滚动

    using System;
    using System.Collections.Generic;
    using UnityEngine.EventSystems;
    
    namespace UnityEngine.UI
    {
        public class LoopScroll : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
        {
            enum DragMode
            {
                None,
                Horizontal,
                Vertical,
            }
    
            public Action<int> callBack;
            [SerializeField]
            private DragMode mode;
            [SerializeField]
            public Transform content;
            [SerializeField, Tooltip("拖拽速度"), Range(1, 100f)]
            private float speed = 1;
            [SerializeField, Tooltip("居中速度"), Range(1, 20f)]
            private float ratio = 1;
            [SerializeField, Tooltip("滑动力度"), Range(10, 1000)]
            private float spring = 30;
            [SerializeField, Tooltip("显示间隔(s)"), Range(1, 60)]
            private float interval = 3;
            [SerializeField, Tooltip("自动显示")]
            private bool auto;
            [SerializeField]
            private Vector2 center;
    
            private Vector2 space;
    
            private Vector2 cell;
    
            private Vector2 vector;
    
            private float offset;
    
            private Vector2 position;
    
            private Vector2 point_begin;
    
            private Vector2 point_end;
    
            private int index_pre;
    
            private int index_target;
    
            private float spring_value;
    
            private int spring_offset;
    
            private bool center_state;
    
            private float center_ratio;
    
            private Vector2 center_vector;
    
            private Vector2 center_position;
    
            private float auto_timer;
    
            private bool m_drag;
    
            private readonly List<RectTransform> m_childs = new List<RectTransform>();
    
            private void Awake()
            {
                FormatPosition();
            }
    
            private void Update()
            {
                if (!m_drag && center_state)
                {
                    center_ratio += Time.deltaTime * ratio;
                    center_position = Vector2.Lerp(m_childs[index_target].localPosition, center, center_ratio);
                    center_vector = center_position - (Vector2)m_childs[index_target].localPosition;
    
                    Drag(center_vector);
    
                    if (center_ratio > 1)
                    {
                        center_state = false;
                    }
                }
    
                if (auto)
                {
                    if (m_drag)
                        auto_timer = 0;
                    else
                        auto_timer += Time.deltaTime;
    
                    if (auto_timer >= interval)
                    {
                        auto_timer = 0;
    
                        Next();
                    }
                }
            }
    
            public void OnBeginDrag(PointerEventData eventData)
            {
                if (Lock) return;
    
                point_begin = Input.mousePosition;
    
                m_drag = true;
            }
    
            public void OnDrag(PointerEventData eventData)
            {
                if (m_drag)
                {
                    Drag(eventData.delta * speed * Time.deltaTime);
                }
            }
    
            public void OnEndDrag(PointerEventData eventData)
            {
                if (Lock) return;
    
                point_end = Input.mousePosition;
    
                m_drag = false;
    
                index_target = -1;
    
                for (int i = 0; i < m_childs.Count; i++)
                {
                    if (Center(m_childs[i].localPosition))
                    {
                        index_target = i;
                        break;
                    }
                }
    
                if (index_target != -1)
                {
                    if (index_target == index_pre)
                    {
                        switch (mode)
                        {
                            case DragMode.Horizontal:
                                spring_value = point_end.x - point_begin.x;
                                break;
                            case DragMode.Vertical:
                                spring_value = point_end.y - point_begin.y;
                                break;
                        }
    
                        if (Math.Abs(spring_value) > spring)
                        {
                            spring_offset = spring_value > 0 ? -1 : 1;
    
                            index_target += spring_offset;
    
                            if (index_target < 0)
                            {
                                index_target += m_childs.Count;
                            }
                            else if (index_target >= m_childs.Count)
                            {
                                index_target %= m_childs.Count;
                            }
                        }
                    }
    
                    index_pre = index_target;
    
                    callBack?.Invoke(index_target);
                }
    
                center_ratio = 0;
                center_state = index_target != -1;
            }
    
            public void FormatPosition()
            {
                m_childs.Clear();
    
                Content _content = content.GetComponent<Content>();
    
                cell.x = _content.Horizontal;
                cell.y = _content.Vertical;
    
                for (int i = 0; i < content.childCount; i++)
                {
                    if (content.GetChild(i).gameObject.activeSelf)
                    {
                        m_childs.Add(content.GetChild(i) as RectTransform);
                    }
                }
    
                Vector2 _position = center;
    
                for (int i = 0; i < m_childs.Count; i++)
                {
                    m_childs[i].anchorMin = Vector2.one * 0.5f;
                    m_childs[i].anchorMax = Vector2.one * 0.5f;
                    m_childs[i].pivot = Vector2.one * 0.5f;
                    m_childs[i].anchoredPosition = _position;
    
                    _content.Adapt(m_childs[i]);
    
                    switch (mode)
                    {
                        case DragMode.Horizontal:
                            _position.x += cell.x;
                            break;
                        case DragMode.Vertical:
                            _position.y -= cell.y;
                            break;
                        default:
                            _position += cell;
                            break;
                    }
                }
    
                int preview_index = 2;
    
                if (m_childs.Count > 0)
                {
                    switch (mode)
                    {
                        case DragMode.Horizontal:
                            space.x = m_childs[0].localPosition.x - preview_index * cell.x;
                            space.y = m_childs[m_childs.Count - preview_index].localPosition.x;
                            break;
                        case DragMode.Vertical:
                            space.x = m_childs[m_childs.Count - preview_index].localPosition.y;
                            space.y = m_childs[0].localPosition.y + preview_index * cell.y;
                            break;
                    }
                }
                else
                {
                    space = Vector2.zero;
                }
            }
    
            public void Jump(int index)
            {
                if (index < 0 || index >= m_childs.Count)
                    return;
    
                index_pre = index_target = index;
    
                Drag(Vector2.one * -1);
    
                if (index_target != -1)
                {
                    callBack?.Invoke(index_target);
                }
    
                center_ratio = 0;
                center_state = index_target != -1;
            }
    
            public bool Lock { get; set; }
    
            private void Next()
            {
                if (m_childs.Count == 0) return;
    
                index_target++;
    
                if (index_target >= m_childs.Count)
                {
                    index_target %= m_childs.Count;
                }
                index_pre = index_target;
    
                Drag(Vector2.one * -1);
    
                if (index_target != -1)
                {
                    callBack?.Invoke(index_target);
                }
    
                center_ratio = 0;
                center_state = index_target != -1;
            }
    
            private void Drag(Vector2 delta)
            {
                switch (mode)
                {
                    case DragMode.Horizontal:
                        vector.x = delta.x;
                        vector.y = 0;
                        break;
                    case DragMode.Vertical:
                        vector.x = 0;
                        vector.y = delta.y;
                        break;
                    default:
                        vector = delta;
                        break;
                }
    
                for (int i = 0; i < m_childs.Count; i++)
                {
                    position = m_childs[i].localPosition;
                    position += vector;
    
                    switch (mode)
                    {
                        case DragMode.Horizontal:
                            if (position.x > space.y)
                            {
                                offset = position.x - space.y;
                                position.x = space.x + offset;
                            }
                            else if (position.x < space.x)
                            {
                                offset = position.x - space.x;
                                position.x = space.y + offset;
                            }
                            break;
                        case DragMode.Vertical:
                            if (position.y > space.y)
                            {
                                offset = position.y - space.y;
                                position.y = space.x + offset;
                            }
                            else if (position.y < space.x)
                            {
                                offset = position.y - space.x;
                                position.y = space.y + offset;
                            }
                            break;
                        default:
                            break;
                    }
    
                    m_childs[i].localPosition = position;
                }
            }
    
            private bool Center(Vector2 position)
            {
                bool result = false;
    
                switch (mode)
                {
                    case DragMode.Horizontal:
                        result = Math.Abs(position.x - center.x) < cell.x / 2;
                        break;
                    case DragMode.Vertical:
                        result = Math.Abs(position.y - center.y) < cell.y / 2;
                        break;
                }
    
                return result;
            }
        }
    }
    LoopScroll
    using System.Collections.Generic;
    
    namespace UnityEngine.UI
    {
        [ExecuteInEditMode]
        public class Content : MonoBehaviour
        {
            private enum Axis
            {
                Horiaontal,
                Vertical,
            }
    
            private enum Stretch
            {
                None,
                Horiaontal,
                Vertical,
                Full,
            }
    
            [SerializeField] private Axis axis = Axis.Horiaontal;
            [SerializeField] private Stretch stretch = Stretch.None;
            [SerializeField] private RectTransform anchor = null;
            [SerializeField] private Vector2 size = new Vector2(100, 100);
            [SerializeField] private Vector2 spacing = Vector2.zero;
            [SerializeField] private bool adapt = false;
    
            private RectTransform m_target;
    
            private Vector2 m_position;
    
            private readonly List<RectTransform> m_childs = new List<RectTransform>();
    
            private void Awake()
            {
                m_target = GetComponent<RectTransform>();
    
                UpdateStretch();
            }
    
    #if UNITY_EDITOR
            private void OnValidate()
            {
                if (m_target == null) return;
    
                UpdateStretch();
    
                m_childs.Clear();
    
                for (int i = 0; i < m_target.childCount; i++)
                {
                    if (m_target.GetChild(i).gameObject.activeSelf)
                    {
                        m_childs.Add(m_target.GetChild(i) as RectTransform);
                    }
                }
    
                RefreshUI();
            }
    #endif
    
            private void RefreshUI()
            {
                m_position = Vector2.zero;
    
                for (int i = 0; i < m_childs.Count; i++)
                {
                    m_childs[i].anchoredPosition = m_position;
    
                    Adapt(m_childs[i]);
    
                    switch (axis)
                    {
                        case Axis.Horiaontal:
                            m_position.x += Horizontal;
                            break;
                        case Axis.Vertical:
                            m_position.y -= Vertical;
                            break;
                    }
                }
            }
    
            public void UpdateStretch()
            {
                switch (stretch)
                {
                    case Stretch.Horiaontal:
                        size.x = anchor != null ? anchor.rect.width : m_target.rect.width;
                        break;
                    case Stretch.Vertical:
                        size.y = anchor != null ? anchor.rect.height : m_target.rect.height;
                        break;
                    case Stretch.Full:
                        size.x = anchor != null ? anchor.rect.width : m_target.rect.width;
                        size.y = anchor != null ? anchor.rect.height : m_target.rect.height;
                        break;
                }
            }
    
            public void Adapt(RectTransform rect)
            {
                if (adapt)
                {
                    rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, Horizontal);
                    rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, Vertical);
                }
            }
    
            public float Horizontal { get { return size.x + spacing.x; } }
    
            public float Vertical { get { return size.y + spacing.y; } }
        }
    }
    Content

    注册:scroll.callBack = (index)=>{...};

    使用:scroll.Jump(index);

    需要展示的子节点物体需>=3,结构类似Scroll Rect,不需要加Fitter

  • 相关阅读:
    JS学习之旅2
    JS学习之旅1
    Stack 栈
    Linked List 链表
    Array 数组
    时间/空间复杂度
    What/Why/How
    Https 握手过程
    JS跨域解决方案
    JS 的内存管理-GC
  • 原文地址:https://www.cnblogs.com/Joke-crazy/p/12582059.html
Copyright © 2011-2022 走看看