轮播图2D

效果

转动轮播图效果


代码

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


public class RotaryFigure2D : MonoBehaviour,IDragHandler,IEndDragHandler
{
    public GameObject prefab;
    public int num = 5;
    public float spacing = 1;//间距
    public float scaleMax = 1;//缩放最大值
    public float scaleMin = 0.5f;//缩放最小值
    Rect rect;//预制体的属性
    float L;//周长
    float r;//半径
    float ang;//每个角弧度
    float dragDistance = 0;//拖拽距离
    List<GameObject> temps = new List<GameObject>();
    List<Transform> sorts = new List<Transform>();

    private void Start()
    {
        rect = prefab.GetComponent<RectTransform>().rect;
        //计算周长
        L = (rect.width + spacing) * num;
        //计算半径
        r = L / (2 * Mathf.PI);
        //计算每个角的弧度
        ang = 2 * Mathf.PI / num;
        Move();
    }
    public void Move()
    {
        //计算拖动的弧度(周长与拖拽距离的比值乘2PI)
        float dragAng = (dragDistance / L) * (2 * Mathf.PI);

        for (int i = 0; i < num; i++)
        {
            if(temps.Count<=i)
            {
                GameObject temp = Instantiate(prefab, transform);
                temp.name = i.ToString();
                temp.GetComponent<Image>().color = Random.ColorHSV();
                temps.Add(temp);
                sorts.Add(temp.transform);
            }
            //计算位置
            float x = Mathf.Sin(ang * i+ dragAng) * r;
            float z= Mathf.Cos(ang * i+ dragAng) * r;
            //z+r求出此元素相对于整个直径的位置,再除以直径,获取它相对于这个直径的位置作为判断远近的根据
            //由于应该越小的数离得越近,根据近大远小,用1减去该值来取反
            //用该比值乘最大值与最小值之间的区间值,来算出实际缩放区间
            //用算出的实际缩放区间加上缩放最小值来算出实际缩放
            float scale=(1-(z+r)/ (2 * r)) * (scaleMax - scaleMin) + scaleMin;
            temps[i].transform.localPosition = new Vector3(x, 0, 0);
            temps[i].transform.localScale = new Vector3(scale, scale, scale);
            
        }
        //根据缩放排序
        sorts.Sort((a, b) =>
        {
            return a.localScale.x.CompareTo(b.localScale.x);
        });
        //根据缩放修改渲染层级
        for (int i = 0; i < sorts.Count; i++)
        {
            sorts[i].SetSiblingIndex(i);
        }
    }

    public void OnDrag(PointerEventData eventData)
    {
        dragDistance -= eventData.delta.x;
        Move();
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        //惯性
        //根据停止拖动时的速度,到速度归零前,使其继续转动一小段时间
        DOTween.To((float a) =>
        {
            dragDistance -= a;
            Move();
        }, eventData.delta.x, 0, Mathf.Abs(eventData.delta.x / 100)).OnComplete(() =>//惯性结束后调用
        {
            //指定转到最大的id
            MoveTo(int.Parse(sorts[sorts.Count - 1].name));
        });
    }
    //对齐(指定位置)
    public void MoveTo(int n)
    {
        //计算正常移动个数
        int a = int.Parse(sorts[sorts.Count - 1].name) - n;
        //计算反向移动个数
        int b = num - Mathf.Abs(a);
        //找到正反两个方向中个数少的方向
        int c = Mathf.Abs(a) < b ? Mathf.Abs(a) : b;
        //判断正常移动时是顺时针还是逆时针,a是顺时针b就是逆时针,a是逆时针b就是顺时针
        if ((a < 0 && c == Mathf.Abs(a)) || (a > 0 && c == b))  
        {
            c = -c;
        }

        //计算指定位置和最大的之间的弧度
        float cutAng = c* ang;
        //对齐最大的
        //通过最大的坐标求弧度
        float moveAng = Mathf.Asin(sorts[sorts.Count - 1].localPosition.x / r);
        //把差值弧度加到对齐最大弧度上,算出需要移动的弧度
        moveAng += cutAng;
        //因为咱们使用距离转动,所以要把弧度转换成移动距离
        //移动的距离 = 移动的弧度与2PI的比值乘周长
        float moveDistance = moveAng / (2 * Mathf.PI) * L;
        //让它自己缓慢转动过去
        DOTween.To((float a) =>
        {
            dragDistance = a;
            Move();
        }, dragDistance, dragDistance + moveDistance, Mathf.Abs(moveDistance / 100)).OnComplete(() =>
        {
            //在这获取最终选择的数据
            sorts[sorts.Count - 1].GetComponent<Image>();
        });
    }
}

操作

 创建一个Image,透明度调为0,做一个Image预制体,放入代码里


思路

1、移动效果

        封装一个移动方法

        通过需要移动的距离计算出需要移动的弧度

        遍历每个元素,通过Sin,Cos计算出元素当前弧度应该处于的位置

        根据算出的z轴值决定元素大小,近大远小

        改变元素的位置和大小

        把元素在一个集合里,进行从小到大排序,并按顺序设置层级,越大层级越大

2、拖动效果

        在拖动接口中,根据拖动距离计算需要移动的距离,再通过实时调用移动方法实现转动效果

3、惯性效果

        在拖动结束接口中,使用DOTween插件里的To方法,调用移动方法,实现惯性效果

        在惯性结束后,可调用对齐方法,实现居中效果

4、对齐指定元素效果

        根据需要对齐的元素编号,和目前处于最前方元素编号进行计算得出顺时针和逆时针需要移动的个数,比较出最少移动的个数

        用最少移动的个数算出对齐元素与最前方元素的差值弧度

        计算出最前方的弧度,与插值弧度相加,算出需要移动的距离

        使用DOTween插件的To方法使其慢慢转动到指定位置

        在对齐完成后可获取它的一些数据,进行其他操作

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是一种基本的Unity 2D图片轮播实现方法: 1. 创建一个空的GameObject,将其命名为“ImageSlider”或其他你喜欢的名称。 2. 在ImageSlider对象上添加一个RectTransform组件,调整它的大小和位置以适应你的需要。 3. 在ImageSlider对象上添加一个Image组件,作为默认显示的图片。你可以选择任何一个你喜欢的图片作为默认显示的图片。 4. 创建一个新的空的GameObject,将其命名为“ImageList”或其他你喜欢的名称。 5. 将ImageList对象作为ImageSlider对象的子对象。 6. 在ImageList对象上添加一个RectTransform组件,调整它的大小和位置以适应你的需要。 7. 在ImageList对象上添加一个HorizontalLayoutGroup组件,调整它的大小和位置以适应你的需要。HorizontalLayoutGroup会让子对象按照水平方向排列。 8. 在ImageList对象下创建多个新的GameObject,每个GameObject代表一个要显示的图片。 9. 在每个GameObject上添加一个Image组件,并将要显示的图片拖入到Image组件中。 10. 将每个GameObject作为ImageList对象的子对象,它们会按照顺序排列。 11. 创建一个新的C#脚本,将其命名为“ImageSliderController”或其他你喜欢的名称,将其添加到ImageSlider对象上。 12. 在ImageSliderController中声明一个public GameObject类型的变量“imageList”,用于引用ImageList对象。 13. 在ImageSliderController中声明一个public float类型的变量“slideInterval”,用于控制图片轮播的间隔时间。 14. 在ImageSliderController中声明一个private int类型的变量“currentIndex”,用于存储当前显示的图片的索引。 15. 在ImageSliderController的Start()方法中,将“currentIndex”初始化为0,并启动一个协程函数“SlideImages()”。 16. 在ImageSliderController中编写一个协程函数“SlideImages()”,控制图片轮播的逻辑。 17. 在“SlideImages()”函数中,使用while循环控制图片轮播的持续时间。 18. 在“SlideImages()”函数中,使用for循环遍历ImageList对象中的所有子对象,根据当前索引切换显示的图片。 19. 在“SlideImages()”函数中,使用yield return new WaitForSeconds(slideInterval)语句控制图片轮播的间隔时间。 20. 在ImageSliderController中编写一个public方法“NextImage()”,用于手动切换到下一张图片。 21. 在“NextImage()”方法中,将“currentIndex”加1,并调用“SlideImages()”函数。 22. 在ImageSliderController中编写一个public方法“PreviousImage()”,用于手动切换到上一张图片。 23. 在“PreviousImage()”方法中,将“currentIndex”减1,并调用“SlideImages()”函数。 24. 在ImageSliderController中编写一个public方法“GoToImage(int index)”,用于跳转到指定索引的图片。 25. 在“GoToImage(int index)”方法中,将“currentIndex”设置为指定的索引,并调用“SlideImages()”函数。 26. 在ImageSliderController中编写一个public方法“StopSlide()”,用于停止图片轮播。 27. 在“StopSlide()”方法中,停止协程函数“SlideImages()”。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值