bazi

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

 

posted on 2023-02-25 08:39  芭梓  阅读(27)  评论(0编辑  收藏  举报

导航