圖片的輪播展現效果若是使用2D實現,須要將3D中存在的近大遠小效果使用圖片的縮放呈現,所以須要存儲和計算圖片的位置同時還要計算存儲圖片的縮放信息。將全部圖片的位置連線看做是一個橢圓,就能夠根據圖片的個數得到全部圖片在橢圓上的位置,從0-1均勻分佈,如4個圖片位置爲0、0.2五、0.五、0.75,5個圖片位置爲0、0.二、0.四、0.六、0.8。根據這個位置能夠分別計算圖片在2D平面上的實際位置(投影的位置)和圖片的縮放比例,而後根據這些信息生成圖片並實如今鼠標拖動過程當中圖片的改變,使用DOTWEEN能夠方便實現動畫效果。html
將RotationDiagram2D掛載到空物體上,以後生成的圖片都是這個物體的子物體,這個腳本是輪播圖的管理腳本。RotationDiagramItem是掛載在圖片上的腳本,在生成圖片時也會添加這個腳本,實現了圖片的運動等各類效果。ide
using System.Collections; using System.Collections.Generic; using System.Linq; using UnityEngine; using UnityEngine.UI; public class RotationDiagram2D : MonoBehaviour { public Vector2 ItemSize; //圖片的大小 public Sprite[] ItemSprites; //圖片精靈集合 public float ScaleMax; //圖片的最大scale public float ScaleMin; //圖片的最小scale public float Offset; //圖片的偏移量(相鄰圖片的間隔) private List<RotationDiagramItem> _items; //存儲全部圖片RotationDiagramItem組件的集合 private List<ItemPosData> _posData; //存儲全部圖片ItemPosData的集合 /// <summary> /// 調用相應的方法進行初始化 /// </summary> private void Start() { _items = new List<RotationDiagramItem>(); _posData = new List<ItemPosData>(); CreateItem(); CalculateData(); SetItemData(); } /// <summary> /// 生成臨時的空物體,在空物體上添加各類組件並返回 /// </summary> /// <returns></returns> private GameObject CreateTemplate() { GameObject item = new GameObject("Template"); item.AddComponent<RectTransform>().sizeDelta = ItemSize; item.AddComponent<Image>(); item.AddComponent<RotationDiagramItem>(); return item; } /// <summary> /// 生成全部物體,根據圖片精靈個數生成對應個數的物體,並設置好圖片精靈,將RotationDiagramItem組件添加到集合中,將組件的Change方法註冊到Action中 /// </summary> private void CreateItem() { GameObject template = CreateTemplate(); RotationDiagramItem itemTemp = null; foreach(Sprite sprite in ItemSprites) { itemTemp = Instantiate(template).GetComponent<RotationDiagramItem>(); itemTemp.SetParent(transform); itemTemp.SetSprite(sprite); itemTemp.AddMoveListener(Change); _items.Add(itemTemp); } Destroy(template); } /// <summary> /// 根據鼠標拖拽的方向獲得相應的信號,並調用Change方法 /// </summary> /// <param name="offsetX"></param> 鼠標拖拽的方向 private void Change(float offsetX) { int symbol = offsetX >= 0 ? 1 : -1; Change(symbol); } /// <summary> /// 根據信號改變全部圖片的id並更改物體的位置縮放等信息 /// </summary> /// <param name="symbol"></param> private void Change(int symbol) { foreach (RotationDiagramItem item in _items) { item.ChangeId(symbol, _items.Count); } for (int i = 0; i < _posData.Count; i++) { _items[i].SetPosData(_posData[_items[i].PosId]); } } /// <summary> /// 計算圖片的位置縮放等信息 /// </summary> private void CalculateData() { List<ItemData> itemDatas = new List<ItemData>(); float length = (ItemSize.x + Offset) * _items.Count; float radioOffset = 1 / (float)_items.Count; float radio = 0; for(int i = 0;i < _items.Count;i++) { ItemData itemData = new ItemData(); itemData.PosId = i; itemDatas.Add(itemData); _items[i].PosId = i; ItemPosData data = new ItemPosData(); data.x = GetX(radio, length); data.scaleTimes = GetScaleTimes(radio, ScaleMax, ScaleMin); radio += radioOffset; _posData.Add(data); } itemDatas = itemDatas.OrderBy(u => _posData[u.PosId].scaleTimes).ToList(); for (int i = 0; i < itemDatas.Count; i++) { _posData[itemDatas[i].PosId].order = i; } } /// <summary> /// 設置圖片的位置縮放等信息 /// </summary> private void SetItemData() { for (int i = 0; i < _posData.Count; i++) { _items[i].SetPosData(_posData[i]); } } /// <summary> /// 計算圖片對應的橫座標 /// </summary> /// <param name="radio"></param> 表明圖片在橢圓形圓圈上位置的數值,這個值在0-1之間 /// <param name="length"></param> 整個圖片展現牆的長度 /// <returns></returns> private float GetX(float radio,float length) { if(radio > 1 || radio < 0) { Debug.LogError("當前比例必須是0-1的值"); return 0; } if(radio >= 0 && radio < 0.25f) { return length * radio; } else if(radio >= 0.25f && radio < 0.75f) { return length * (0.5f - radio); } else { return length * (radio - 1); } } /// <summary> /// 計算圖片的縮放倍數 /// </summary> /// <param name="radio"></param> 圖片在橢圓上的位置 /// <param name="max"></param> 圖片的最大縮放比例 /// <param name="min"></param> 圖片的最小縮放比例 /// <returns></returns> private float GetScaleTimes(float radio,float max,float min) { if (radio > 1 || radio < 0) { Debug.LogError("當前比例必須是0-1的值"); return 0; } if (radio < 0.5f) return Mathf.Lerp(max, min, radio); else return Mathf.Lerp(min, max, radio - 0.5f); } } /// <summary> /// 記錄圖片的位置、縮放和層級信息的類 /// </summary> public class ItemPosData { public float x; public float scaleTimes; public int order; } /// <summary> /// 記錄圖片次序和層級信息的結構體 /// </summary> public struct ItemData { public int PosId; public int OrderId; }
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; using DG.Tweening; public class RotationDiagramItem : MonoBehaviour, IDragHandler,IEndDragHandler { public int PosId; private float _offsetX; public Action<float> _moveAction; public float _aniTime = 1; private Image _image; private Image Image { get { if (_image == null) _image = GetComponent<Image>(); return _image; } } private RectTransform _rect; private RectTransform Rect { get { if (_rect == null) _rect = GetComponent<RectTransform>(); return _rect; } } /// <summary> /// 設置父物體 /// </summary> /// <param name="parent"></param> 父物體 public void SetParent(Transform parent) { transform.SetParent(parent); } /// <summary> /// 設置圖片 /// </summary> /// <param name="sprite"></param> 圖片精靈 public void SetSprite(Sprite sprite) { Image.sprite = sprite; } /// <summary> /// 設置位置和大小 /// </summary> /// <param name="data"></param> 保存圖片位置和大小信息的對象 public void SetPosData(ItemPosData data) { Rect.DOAnchorPos(Vector2.right * data.x, _aniTime); //Rect.anchoredPosition3D = Vector2.right * data.x; Rect.DOScale(Vector3.one * data.scaleTimes, _aniTime); //Rect.localScale = Vector3.one * data.scaleTimes; StartCoroutine(Wait(data)); } /// <summary> /// 等待後設置圖片層級 /// </summary> /// <param name="data"></param> 保存圖片信息的對象 /// <returns></returns> private IEnumerator Wait(ItemPosData data) { yield return new WaitForSeconds(_aniTime * 0.5f); transform.SetSiblingIndex(data.order); } /// <summary> /// IDragHandler接口的實現方法 /// </summary> /// <param name="eventData"></param> public void OnDrag(PointerEventData eventData) { _offsetX += eventData.delta.x; } /// <summary> /// IEndDragHandler接口的實現方法 /// </summary> /// <param name="eventData"></param> public void OnEndDrag(PointerEventData eventData) { _moveAction(_offsetX); _offsetX = 0; } /// <summary> /// 添加監聽器,監聽鼠標的拖動 /// </summary> /// <param name="onMove"></param> public void AddMoveListener(Action<float> onMove) { _moveAction = onMove; } /// <summary> /// 根據信號改變圖片的id /// </summary> /// <param name="symbol"></param> 表明圖片拖動方向的信號值 /// <param name="totalItemNum"></param> 圖片的總數 public void ChangeId(int symbol,int totalItemNum) { int id = PosId; id += symbol; if(id < 0) { id += totalItemNum; } PosId = id % totalItemNum; } }