首先,和3D轮转图一样根据生成对象的个数计算出周长、半径、每个图片之间的弧度。
再计算出每个物体的具体坐标位置(x),因为是2D物体在同一平面,所以没有z轴的变化,只能按近大远小的效果来模拟远近效果,根据z的数值来计算出缩放的倍率 p=(z+r)÷(2*r),z的取值范围是0≤z≤半径(r),再求出缩放的大小(最近时显示的大小-最小时显示大小)*p+最小时显示大小。再给每个图片的位置赋值,由于同一平面只有x轴的坐标变化,所以只给物体的x坐标赋值就可以。
再根据物体的大小使用Sort方法来排序,让缩放倍率最大的显示在前面。拖拽图片移动先取得拖拽的距离,再根据距离求出移动的弧度,调用物体旋转的方法让所有图片旋转实现旋转的效果,代码如下
private void Move()
{
for (int i = 0; i < n; i++)
{
if (list.Count<=i)
{
list.Add(Instantiate(prefab, transform));
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.lossyScale.x<b.lossyScale.x)
{
return -1;
}
else if (a.lossyScale.x > b.lossyScale.x)
{
return 1;
}
else
{
return 0;
}
});
for (int i = 0; i < sortlist.Count; i++)
{
sortlist[i].SetSiblingIndex(i);
}
}
public void OnDrag(PointerEventData eventData)
{
float x = eventData.delta.x;
float dis = x / r;
moveAng += dis;
Move();
}
使用DoTween模拟出惯性的效果,取得鼠标结束拖拽时的距离,根据速度来求出减速需要的时间。
获取停止时转到的图片的下标、求出需要回正的距离和弧度,再根据距离求出需要的时间,使用DoTween旋转求出的弧度回正位置。代码如下
public void OnEndDrag(PointerEventData eventData)
{
float speed= eventData.delta.x;
float time = Mathf.Abs(speed) / cut;
DT.To((a) =>
{
float dis = a / r;
moveAng += dis;
Move();
}, speed, 0, time).OnComplete(() =>
{
//print("index" + list.IndexOf(sortlist[n - 1].GetComponent<Image>()));
Align(list.IndexOf(sortlist[n - 1].GetComponent<Image>()));
});
}
private void Align(int index)
{
int id = list.IndexOf(sortlist[n - 1].GetComponent<Image>());
//print("id" + id);
int sp = id - index;
float spang = sp * ang;
print("id" + spang);
float alignang = Mathf.Asin(sortlist[n - 1].GetComponent<RectTransform>().anchoredPosition.x / r + spang);
float aligndis = alignang * r;
float time = Mathf.Abs(aligndis) / cut;
DT.To((a) =>
{
moveAng = a;
Move();
},moveAng, moveAng-alignang,time);
}