(Unity)UI上的轮转图(3D效果)

轮转图也叫做轮播图

 在UI上,我们只要掌握好近大远小以及角标层级的分配,就能模拟出3D的轮转效果了。

不管是横向、纵向、斜向都能有不错的表现。 

这里以纵向代码举例:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class Circle2D : MonoBehaviour,IDragHandler,IEndDragHandler
{
    public InputField inputf;
    public int num = 14;//Item数量
    public float offest = 10;//间距
    public Image prefab;//Item预制体
    public float max = 1;//Item最大比例
    public float min = 0.5f;//Item最小比例
    public float dec = 10;//减速度
    float c;//周长
    float r;//半径
    float ang;//每个角弧度
    float allang;//移动的总弧度
    public List<GameObject> list = new List<GameObject>();
    public List<Transform> sort = new List<Transform>();
    DT dt;
    DT dt0;
    void Start()
    {
        c = num * (prefab.rectTransform.sizeDelta.y+offest);
        r = c / (360 * Mathf.Deg2Rad);
        ang = 360 * Mathf.Deg2Rad / num;
        Move();
    }
    public void Move()
    {
        for(int i = 0; i < num; i++)
        {
            if (list.Count <= i)
            {
                list.Add(Instantiate(prefab.gameObject, transform));
                sort.Add(list[i].transform);
                list[i].transform.GetComponentInChildren<Text>().text = i.ToString();
            }
            float y = Mathf.Sin(i * ang+allang) * r;
            float z = Mathf.Cos(i * ang+allang) * r;
            float p = (z + r) / (r + r);
            float scale = max * (1 - p) + min * p;
            list[i].transform.localPosition = new Vector3(0, y, 0);
            list[i].transform.localScale = Vector3.one * scale;
        }
        //排序设置角标
        Sort();
    }
    public void OnDrag(PointerEventData eventData)
    {
        if (dt != null)
        {
            Destroy(dt.gameObject);
        }
        if (dt0 != null)
        {
            Destroy(dt0.gameObject);
        }
        allang-=eventData.delta.y/r;
        Move();
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        float dis = eventData.delta.y;
        float time = Mathf.Abs(dis / dec);
        dt=DT.To((a) =>
        {
            allang -= a / r;
            Move();
        }, dis, 0, time).OnComlate(() =>
        {
            float moveang = Mathf.Asin(sort[num - 1].localPosition.y / r);
            float movetime = Mathf.Abs(moveang * r / dec);
            dt0=DT.To((b) =>
            {
                allang = b;
                Move();
            }, allang, allang + moveang, movetime).OnComlate(() =>
            {

            });
        });
    }
    public void Sort()
    {
        sort.Sort((a, b) =>
        {
            if (a.localScale.z < b.localScale.z)
            {
                return -1;
            }
            else if (a.localScale.z == b.localScale.z)
            {
                return 0;
            }
            else
            {
                return 1;
            }
        });
        for (int i = 0; i < sort.Count; i++)
        {
            sort[i].SetSiblingIndex(i);
        }
    }
    public void OnButton()
    {
       
        int next = int.Parse(inputf.text);
        Sort();
        //当前位置
        int id = list.IndexOf(sort[^1].gameObject);
        int n0 = id - next;
        int n1 = num - Mathf.Abs(n0);
        int n2 = n0 > 0 ? -n1 : n1;
        int n3 = Mathf.Abs(n0) < Mathf.Abs(n2) ? n0 : n2;
        //预计位置
        float moveang = Mathf.Asin(sort[num - 1].localPosition.y / r) + n3 * ang;
        float movetime = Mathf.Abs(moveang * r / dec);
        dt0 = DT.To((b) =>
        {
            allang = b;
            Move();
        }, allang, allang + moveang, movetime).OnComlate(() =>
        {

        });

    }
    void Update()
    {

    }
}

这里用了一个简单的脚本代替DoTween:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DT : MonoBehaviour
{
    float starttime, nowtime, alltime;
    float now;
    Action<float> action;
    Action comlate;
    bool isplay = true;
    void Start()
    {
        
    }
    public static DT To(Action<float>action,float starttime,float nowtime,float alltime)
    {
        GameObject obj = new GameObject("Dt");
        DT self = obj.AddComponent<DT>();
        self.starttime = starttime;
        self.nowtime = nowtime;
        self.alltime = alltime;
        self.now = Time.time;
        self.action = action;
        return self;
    }
    public DT OnComlate(Action comlate)
    {
        this.comlate = comlate;
        return this.GetComponent<DT>();
    }
    void Update()
    {
        if (Time.time - now < alltime)
        {
            float p = (Time.time - now) / alltime;
            float c = (1 - p) * starttime + nowtime * p;
            if (action != null)
            {
                action(c);
            }
        }
        else if(isplay)
        {
            isplay = false;
            if (action != null)
            {
                action(nowtime);
            }
            if (comlate != null)
            {
                comlate();
            }
            Destroy(gameObject);
        }
    }
}

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值