UI轮转图
代码如下:(需要使用插件DoTween/也可不用)
using System.Collections;
using System.Collections.Generic;
using UnityEngine; using UnityEngine.UI;
using UnityEngine.EventSystems;
using DG.Tweening;
public class UIScreptRender : MonoBehaviour,IDragHandler,IEndDragHandler
{
public Image prefab;//对象
public int num;//个数
public float spacing;//间距
float c;//周长
float r;//半径
float ang;//每个角的弧度
float dis = 0;//拖动的距离
float max = 1;//缩放最大值
float min = 0.5f;//缩放最小值
float cutSpeed = 100;//速度
List<GameObject> list=new List<GameObject>();
List<Transform> sorts= new List<Transform>();
// Start is called before the first frame update
void Start()
{
c = (prefab.rectTransform.rect.width + spacing) * num;//计算周长
r = c / (2*Mathf.PI);
ang = (2 * Mathf.PI) / num;
Move();
}
public void Move()
{
float moveang = dis / r;
for (int i = 0; i < num; i++)
{
float x = Mathf.Sin(i*ang+moveang) * r;
float z=Mathf.Cos(i*ang+moveang) * r;
//计算缩放比
float p = (z + r) / (2*r);
//近大远小
p = 1 - p;
//用比值计算缩放
float scale = (max - min) * p + min;
if (list.Count<=i)
{
GameObject image = Instantiate(prefab.gameObject,transform);
image.name=i.ToString();
list.Add(image);
sorts.Add(image.transform);
}
list[i].transform.localPosition = Vector3.right * x;
list[i].transform.localScale=Vector3.one* scale;
}
sorts.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 < sorts.Count; i++)
{
sorts[i].SetSiblingIndex(i);
}
}
// Update is called once per frame
void Update()
{
}
public void OnDrag(PointerEventData eventData)
{
dis -= eventData.delta.x;
Move();
}
public void OnEndDrag(PointerEventData eventData)
{
float starspeed=eventData.delta.x;
float endspeed = 0;
float time=Mathf.Abs(starspeed)/cutSpeed;
DOTween.To((float a) =>
{
dis -= a;
Move();
}, starspeed, endspeed, time).OnComplete(() =>
{
}) ;
}
public void Align(int n)
{
int i = list.IndexOf(sorts[num-1].gameObject);
int s = i - n;
int s2=num-Mathf.Abs(s);
s2 = s > 0 ? -s2 : s2;
int s3=Mathf.Abs(s)<Mathf.Abs(s2)?s:s2;
float moveAng = Mathf.Asin(sorts[num-1].localPosition.x/r);
float moveDis = moveAng * r;
float time = Mathf.Abs(moveDis) / cutSpeed;
DOTween.To((float a) =>
{
dis = a;
Move();
}, dis, dis + moveDis, time).OnComplete(() =>
{
}) ;
}
}
----------------------------------------------------------说明-------------------
UI在空间中遵循近大远小的原则,以z轴为核心实现视觉效果
3d轮转图和2d主要区别在于是否有z轴,2d没有z,改为近大远小,由于没有z轴,所以还涉及遮挡排序的问题
(以下内容请结合代码观看,与代码部分对应)
物体场景状态
以一个父级物体为基础,在下面创建子集对象,打包成预制体之后,在场景中移除
在父物体对象上挂载脚本
代码书写
-------------------------------------------------------------------------
声明引入预制体对象
要生成对象的数量
每个预制体之间的间距
//接下来考虑轨道
周长
半径
弧度
移动的距离
缩放最大值=1
缩放最小值=0.5f
创建集合放对象:
List<GameObject> list
排序过后的:
List<Transfrom> sort
开始准备
总周长=(预制体对象宽+间距)*个数
半径=周长/(2*Π)
角弧度=(2*Π)/对象的数量(num)
进行计算(开始计算)//刷新计算数据
开始计算
移动的弧度=距离/半径;
循环计算(每个对象所在的位置)
{
x轴=Mathf.Sin(i (对象数量) * 每个角的弧度+移动的弧度) * 半径
z轴=Mathf.Cos(i (对象数量) *每个角的弧度+移动的距离) *半径
//计算缩放比值。半径是1,最近是-1,最远是1,所以要算直径的比值,将最近和最远都+1,得到0到2的值,用它来用直径2作比较
缩放比=(z轴+半径)/(2 * 半径);
//近大远小需要反过来,0是原来-1的位置,是近处
(实际缩放比,进一步处理)缩放比=1-(原来的)缩放比;(还原)
//用比值计算缩放 区间 *比例 +最小值
scale=(max(缩放最大值)-min(缩放最小值))* 缩放比 + min(缩放最小 值);
if( list.Count<=i )
{
GameObject image=Inatance(prefab.gameObject,transfrom);//创建对象
调整名称
//添加进集合
list.Add(image);
sort.Add(image.transfrom);
}
list[i].transfrom.localPostion=v3.right(x轴)*x;
list[i].transfrom.localScale=v3.one*scale(实际缩放比值);
}
//判断缩放,进行排序
sort(排序<表达式排序>)
比较x轴进行排序
//实时切换子父级进行详细的显示
切换子父级
拖拽中
拖动距离+=拖拽对象的x轴
进行计算(开始计算)//刷新计算数据
结束拖拽部分之后,使用DoTween插件做了一个减缓的效果