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);
}
}