C#2D轮转图
using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; using DG.Tweening; public class RotationChart2D : MonoBehaviour,IDragHandler,IEndDragHandler { public Image prefab;//预制体 public float max = 1;//缩放最大值 public float min = 0.5f;//缩放最小值 public int n = 10;//个数 public float spacing = 100;//UI间距的单位是像素 public float cut = 10;//减速度 float c;//周长 float r;//半径 float ang;//弧度 List<Image> list = new List<Image>(); List<Transform> sortlist = new List<Transform>(); float moveAng = 0;//拖动的弧度 // Start is called before the first frame update void Start() { c = (prefab.rectTransform.rect.width + spacing) * n; r = c / (2 * Mathf.PI); ang = 2 * Mathf.PI / n; Move(); } public void Move() { for (int i = 0; i < n; i++) { if (list.Count <= i) { list.Add(Instantiate(prefab, transform)); list[i].transform.GetComponent<Image>().sprite = Resources.Load<Sprite>("Image/image_" + i); sortlist.Add(list[i].transform); } float x = Mathf.Sin(i * ang + moveAng) * r; float z = Mathf.Cos(i * ang + moveAng) * r; float p = (z + r) / (2 * r); float scale = (max - min) * p + min; list[i].rectTransform.anchoredPosition = new Vector2(x, 0); list[i].transform.localScale = Vector3.one * scale; } sortlist.Sort((a, b) => { if (a.localScale.x<b.localScale.x) { return -1; } else if (a.localScale.x == b.localScale.x) { return 0; } else { return 1; } }); for (int i = 0; i < sortlist.Count; i++) { sortlist[i].SetSiblingIndex(i); } } // Update is called once per frame void Update() { } public void OnDrag(PointerEventData eventData) { float dis = eventData.delta.x; float dragAng = dis / r; moveAng += dragAng; Move(); } public void OnEndDrag(PointerEventData eventData) { float speed = eventData.delta.x; float time = Mathf.Abs(speed) / cut; DOTween.To((a) => { //通过距离计算弧度 float dragAng = a / r; moveAng += dragAng; Move(); },speed,0,time).OnComplete(()=> { Align(list.IndexOf(sortlist[n - 1].GetComponent<Image>())); }); } public void Align(int id) { //当前下标 int index = list.IndexOf(sortlist[n - 1].GetComponent<Image>()); //指定下标与当前下标的间隔 int sp = id - index; //计算另一个旋转方向需要的间隔 int sp0 = n - Mathf.Abs(sp); //一个方向是顺时针另一个一定是逆时针 所以一个是正另一个一定是负 sp0 = sp > 0 ? -sp0 : sp0; //选择两个方向中间隔娇小的一方旋转 int end = Mathf.Abs(sp) < Mathf.Abs(sp0) ? sp : sp0; //计算间隔的弧度 float spAng = end * ang; //需要旋转的弧度 = 中间偏差的弧度 + 间隔的弧度 float AlignAng = Mathf.Asin(sortlist[n - 1].GetComponent<RectTransform>().anchoredPosition.x / r) + spAng; //通过需要旋转的弧度计算需要旋转的距离 float Aligndis = AlignAng * r; //通过需要旋转的距离计算旋转的时间 float time = Mathf.Abs(Aligndis) / cut; DOTween.To((a) => { moveAng = a; Move(); },moveAng,moveAng - AlignAng,time); } }