Unity实现仿3D轮转图效果

这篇文章主要为大家详细介绍了Unity实现仿3D轮转图,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了Unity实现仿3D轮转图效果的具体代码,供大家参考,具体内容如下

一、效果演示

二、实现思路

——获取位置:可以将每个item的运行轨迹看作一个椭圆,分为四段进行观察,四个黑点视为四个item,观察四个黑点的位置,比例值为0.125和0.375的位置相同,比例值为0.625和0.875的位置相同,比例值为0.375和0.625的位置相反,可得结论
[0,0.25]:轨迹总长度*当前比例值
(0.25,0.5]:轨迹总长度 * (0.5 - 当前比例值)
(0.5,0.75]:轨迹总长度 * (0.5 - 当前比例值)
(0.75,1]:轨迹总长度 * (当前比例值 - 1)

——获取缩放值:可以将每个item的运行轨迹看作一个椭圆,分为四段进行观察,四个黑点视为四个item,观察四个黑点的位置,比例值为0时缩放值应为最大,比例值为0.5时缩放值应为最小,可得结论
[0-0.5]:缩放最大值 - 比例值 * (缩放最大值 - 缩放最小值) * 2
(0.5-1]:缩放最大值 - (1 - 比例值) * (缩放最大值 - 缩放最小值) * 2

——获取层级:使用UGUI的自然层级进行排序(越靠下越后渲染),拷贝一份列表item数据列表按照缩放值从小到大的顺序排序,再通过SetSiblingIndex依次设置层级

三、使用

——常规使用
SetData:传入item预制体和列表中item个数
OnSetItem:绑定设置item的方法
SetList:设置列表的显示

using UnityEngine; using UnityEngine.UI;   public class Test : MonoBehaviour {     public GameObject prefab;       public Rotary3DList rotary3DList;       private void Start()     {         rotary3DList.SetData(prefab, 5);         rotary3DList.OnSetItem = SetItem;         rotary3DList.SetList();     }       void SetItem(Rotary3DList.ListItemData listItemData)     {         listItemData.go.GetComponent().txt = listItemData.index.ToString();     } }

——MoveToIndex:移动到某一个下标位置,isScroll表示是否滑动到指定位置
——GetListItemData:获取到某个下标的item数据
——CenterIndex:当前中心点item下标

四、代码实现

using System.Collections.Generic; using UnityEngine; using System; using UnityEngine.UI; using UnityEngine.EventSystems; using System.Linq;   ///  /// 仿3D轮转图组件 ///  [AddComponentMenu("LFramework/UI/Rotary3DList", 50)] [RequireComponent(typeof(Image))] public class Rotary3DList : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler {     ///      /// 列表item数据     ///      public class ListItemData     {         public int index;         public GameObject go;         public float targetValue;//目标位置长度值         public float tempValue;//临时位置长度值(每次拖拽结束后才更新数值)     }       ///      /// 轮转类型     ///      public enum RotaryType     {         Horizontal,         Vertical,     }       public RotaryType rotaryType;//轮转类型     public float spacing;//间隔     public float maxScale = 1;//最大缩放值     public float minScale = 0.5f;//最小缩放值     public float t = 0.1f;//缓动插值     public Action OnSetItem;//设置item     public Action OnDragBegin;//拖拽开始     public Action OnDragging;//拖拽中     public Action OnDragEnd;//拖拽结束       //中心item下标     public int CenterIndex     {         get { return GetCenterItemIndex(); }     }       int m_ItemCount;//列表item总数量     float m_TotalValue;//总长度值     float m_DeltaValue;//长度值增量     GameObject m_Prefab;     RectTransform m_ItemContainer;     List m_ListItemDataList = new List();       bool m_InDrag;     float m_BeginPos;     List m_InitValueList = new List();//初始每个item的位置长度值       ///      /// 设置数据     ///      public void SetData(GameObject prefab, int itemCount)     {         m_ItemContainer = GetComponent();         m_ItemCount = itemCount;         m_Prefab = prefab;         m_DeltaValue = rotaryType == RotaryType.Horizontal             ? (spacing + m_Prefab.GetComponent().rect.width)             : (spacing + m_Prefab.GetComponent().rect.height);         m_TotalValue = m_DeltaValue * m_ItemCount;           InitData();     }       ///      /// 初始化数据     ///      void InitData()     {         float tempValue = 0;         for (int i = 0; i      /// 设置列表     ///      public void SetList()     {         foreach (var data in m_ListItemDataList)         {             OnSetItem?.Invoke(data);         }           UpdateItem(true);     }       ///      /// 移动到某个下标位置     ///      public void MoveToIndex(int index, bool isScroll = true)     {         if (index <0   || index>= m_ItemCount)         {             Debug.LogError("下标超出范围,index : " + index);             return;         }           int indexOffset = CenterIndex - index;         foreach (var data in m_ListItemDataList)         {             float tempValue = data.tempValue + m_DeltaValue * indexOffset <0   ? data.tempvalue + m_deltavalue * indexoffset m_totalvalue : indexoffset; float targetvalue=tempValue % m_totalvalue; data.targetvalue=targetValue; targetvalue; } updateitem(!isscroll); public void onbegindrag(pointereventdata eventdata) { m_indrag=true; m_beginpos=rotaryType> 0)         {             foreach (var data in m_ListItemDataList)             {                 float tempValue = (data.tempValue + offset) % m_TotalValue;                 data.targetValue = tempValue;             }         }         else if (offset <0)         {             foreach (var data in m_ListItemDataList)             {                 float tempValue = data.tempValue + offset <0   ? m_totalvalue - mathf.abs(data.tempvalue + offset) % : (data.tempvalue m_totalvalue; data.targetvalue=tempValue; } public void onenddrag(pointereventdata eventdata) { m_indrag=false; ondragend?.invoke(eventdata); foreach (var data in m_listitemdatalist) float nearlyvalue=GetNearlyValue(data.targetValue); nearlyvalue; data.tempvalue=nearlyValue; private update() updateitem(false);>     /// 更新item     ///      void UpdateItem(bool isForce)     {         //拖拽中-实时更新         if (m_InDrag)         {             foreach (var data in m_ListItemDataList)             {                 float ratio = data.targetValue / m_TotalValue;                   //更新位置                 float pos = GetPos(ratio);                 Vector2 targetPos = rotaryType == RotaryType.Horizontal                     ? new Vector2(pos, 0)                     : new Vector2(0, pos);                 data.go.transform.localPosition = targetPos;                   //更新缩放值                 float scale = GetScale(ratio);                 Vector2 targetScale = Vector3.one * scale;                 data.go.transform.localScale = targetScale;             }         }         //非拖拽中-缓动更新         else         {             foreach (var data in m_ListItemDataList)             {                 float ratio = data.targetValue / m_TotalValue;                   //更新位置                 float pos = GetPos(ratio);                 Vector2 targetPos = rotaryType == RotaryType.Horizontal                     ? new Vector2(pos, 0)                     : new Vector2(0, pos);                 float targetPosOffset = rotaryType == RotaryType.Horizontal                     ? data.go.transform.localPosition.x - targetPos.x                     : data.go.transform.localPosition.y - targetPos.y;                 data.go.transform.localPosition = Vector2.Lerp(data.go.transform.localPosition, targetPos, isForce ? 1 : t);                 if (Mathf.Abs(targetPosOffset) <= 0.01f)                 {                     data.go.transform.localPosition = targetPos;                 }                   //更新缩放值                 float scale = GetScale(ratio);                 Vector2 targetScale = Vector3.one * scale;                 float targetScaleOffset = data.go.transform.localScale.x - targetScale.x;                 data.go.transform.localScale = Vector2.Lerp(data.go.transform.localScale, targetScale, isForce ? 1 : t);                 if (Mathf.Abs(targetScaleOffset) <= 0.01f)                 {                     data.go.transform.localScale = targetScale;                 }             }         }           //更新层级         var listItemDataList = m_ListItemDataList.OrderBy(data => GetScale(data.targetValue / m_TotalValue)).ToList();         for (int i = 0; i      /// 得到位置     ///      float GetPos(float ratio)     {         if (ratio <0   && ratio> 1)         {             Debug.LogError("比例值错误,比例值必须为[0-1],ratio : " + ratio);             return 0;         }           if (ratio >= 0 && ratio <= 0.25f)         {             return m_TotalValue * ratio;         }         else if (ratio > 0.25f && ratio <= 0.75f)         {             return m_TotalValue * (0.5f - ratio);         }         else         {             return m_TotalValue * (ratio - 1);         }     }       ///      /// 得到缩放值     ///      float GetScale(float ratio)     {         if (ratio <0    && ratio> 1)         {             Debug.LogError("比例值错误,比例值必须为[0-1],ratio : " + ratio);             return 0;         }           float v = (maxScale - minScale) * 2;         if (ratio >= 0 && ratio <= 0.5f)         {             return maxScale - ratio * v;         }         else         {             return maxScale - (1 - ratio) * v;         }     }       ///      /// 得到距离最近的位置长度值     ///      float GetNearlyValue(float curValue)     {         float minDis = Mathf.Abs(curValue - m_InitValueList.First());         float nearlyValue = m_InitValueList.First();         foreach (var value in m_InitValueList)         {             float tempDis = Mathf.Abs(curValue - value);             if (tempDis      /// 得到中心item的下标     ///      int GetCenterItemIndex()     {         int index = 0;         float minDis = Mathf.Min(Mathf.Abs(m_ListItemDataList[0].targetValue - m_InitValueList.First()), Mathf.Abs(m_ListItemDataList[0].targetValue - m_InitValueList.Last()));         foreach (var data in m_ListItemDataList)         {             float tempDis = Mathf.Min(Mathf.Abs(data.targetValue - m_InitValueList.First()), Mathf.Abs(data.targetValue - m_InitValueList.Last()));             if (tempDis      /// 得到列表item数据     ///      public ListItemData GetListItemData(int index)     {         if (index <0    || index>= m_ItemCount)         {             Debug.LogError("下标超出范围,index : " + index);             return null;         }           return m_ListItemDataList[index];     } }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持0133技术站。

以上就是Unity实现仿3D轮转图效果的详细内容,更多请关注0133技术站其它相关文章!

赞(0) 打赏
未经允许不得转载:0133技术站首页 » 其他教程