绘制2D轮转图
首先,需要准备可以用于制作轮转图的图片/可以先摆放,将其制作成预制体。在接下来的开发过程中,我们会通过一个自己定义的预制体数组来管理这些预制体生成的轮转图的最基本单位。
然后,需要计算出轮转的圆心、半径和图片之间的夹角。将所有图片按照圆弧排列,同时通过计算每个图片的位置和比例实现轮转效果。通过列表管理每个图片,并按照缩放比例排序。
接下来,监听拖拽行为,计算拖拽的距离并移动图片。拖拽结束后,通过动画的方式实现轮转到指定位置的效果。可以通过计算需要旋转的图片数量,选择旋转的方向并计算出旋转的距离和时间,最终以动画的方式完成轮转效果。
在实现这个功能过程中,使用DOTween插件可以大大简化动画效果的处理,提高了开发效率。同时,通过简单的数学计算,实现了轮转效果。如果我们没法使用DOTween插件的话可以参考一下
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
using System;
using DG.Tweening;
public class ZhuanQuan : 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 = 300;
List<GameObject> list = new List<GameObject>();
List<Transform> sors = new List<Transform>();
void Start()
{
c = (prefab.rectTransform.rect.width+spacing)*num;
r = c /(2*Mathf.PI);
ang = (2*Mathf.PI)/num;
Move();
}
private 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.GetComponent<Image>().color = UnityEngine.Random.ColorHSV();
image.name = i.ToString();
list.Add(image);
sors.Add(image.transform);
}
list[i].transform.localPosition = Vector3.right * x;
list[i].transform.localScale = Vector3.one * scale;
}
sors.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 < sors.Count; i++)
{
sors[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 startspeed = eventData.delta.x;
float endspeed = 0;
float time = Mathf.Abs(startspeed) / cutSpeed;
DOTween.To((float a) => {
dis -= a;
Move();
},startspeed,endspeed,time).OnComplete(()=>
{
});
}
public void Align(int n)
{
int i = list.IndexOf(sors[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(sors[num - 1].localPosition.x / r) + s3*ang;
float moveDis = moveAng * r;
float time = Mathf.Abs(moveDis)/cutSpeed;
DOTween.To((float a) => {
dis = a;
Move();
}, dis, dis + moveDis, time).OnComplete(() =>
{
}
);
}
}