UGUI图片跑马灯的实现

今天用UGUI做多个图片自动滚动展示的功能,具体如下

1.从特定文件夹中读取所有图片

2.排列展示所有图片,如果超出屏幕范围了,就循环滚动

3.点击其中的图片,暂停滚动,该图片放大展示在屏幕中间。再点击就缩小回去,并继续滚动。

首先,要遍历文件夹,读取所有的图片

// 在特定路径中获取所有图片
    Dictionary<string, Texture2D> GetAllImgInPath( string fullPath)
    {
        Dictionary<string, Texture2D> retDict = new Dictionary<string, Texture2D>();
        // 先判断是不是存在该路径
        if( Directory.Exists( fullPath) == false)
        {
            return retDict;
        }
        // 遍历路径中所有的文件
        string [] filePathArr = Directory.GetFiles( fullPath);
        string ext = string.Empty;
        string []imgExtArr = new string[]{".jpg", ".png", ".bmp"};
        foreach( string fullName in filePathArr)
        {
            // 根据后缀判断是不是图片
            ext = Path.GetExtension( fullName);
            if( ((IList)imgExtArr).Contains(ext))
            {
                // 读取图像
                byte[] imgBytes = File.ReadAllBytes( fullName);
                Texture2D t2d = new Texture2D(1,1);
                t2d.LoadImage( imgBytes);
                retDict.Add( Path.GetFileName( fullName), t2d);
            }
        }
        return retDict;
    }

然后针对每个图像创建一个RawImage对象。我在ugui中没有找到直接创建ugui控件的函数,只能做了一个RawImage的预置物,然后使用预置物Instantiate出来新的。

// 初始化所有图像
    void InitAllImg( Dictionary<string, Texture2D> texDict)
    {
        if( m_imgCellPerfab == null || m_imgCellParent == null)
        {
            Debug.LogError( "InitAllImg ERR!! 预置物或者父节点是空值!");
            return;
        }
        m_allImgs.Clear();
        foreach( KeyValuePair<string, Texture2D> pair in texDict)
        {   
            // 新建rawImage
            Texture2D t2d = pair.Value;
            RawImage imgCell = Instantiate( m_imgCellPerfab);
            imgCell.texture = t2d;
            imgCell.GetComponent<Transform>().SetParent( m_imgCellParent, false);
            // 给图片添加点击事件
            EventTriggerListener.Get(imgCell.gameObject).onDown += OnClickImg;
            m_allImgs.Add( imgCell);
        }

        InitImgPos();
    }

现在这些图片都可以显示了,现在该处理这些图片的位置了。设定一个间距距离,然后根据图像的宽度就可以算出下个图像的初始位置

// 初始化位置
    void InitImgPos()
    {
        // 先算出总的宽度
        float totalW = m_spacing;
        foreach( RawImage img in m_allImgs)
        {
            // 图片的宽度+间隔
            RectTransform rectTran = img.GetComponent<RectTransform>();
            totalW = totalW + rectTran.rect.width + m_spacing;
        }
        // 如果总宽度比父节点宽度小,居中。如果总宽度比父节点的宽度大,从最左边起
        Vector2 parentSize = m_imgCellParent.GetComponent<RectTransform>().sizeDelta;
        float startX = 0;
        if( totalW < parentSize.x)
        {
            // 居中
            startX = -totalW/2;
        }
        else
        {
            // 从最左边起
            startX = -parentSize.x/2;
        }
        float x = startX + m_spacing;
        // 初始化每个图片的位置
        foreach( RawImage img in m_allImgs)
        {
            // 图片的宽度+间隔
            RectTransform rectTran = img.GetComponent<RectTransform>();
            // 因为是中心对齐,所以偏移宽度的一半
            x = x + rectTran.sizeDelta.x/2; 
            rectTran.localPosition = new Vector3( x, 0, 0);
            // 下个图片的位置
            x = x + rectTran.sizeDelta.x/2 + m_spacing;
        }
    }

之后就是处理移动了,就是每帧根据速度算出来移动的距离,然后每个图片都移动这个距离就好了。如果移动超出父节点的范围了的话,就把这个位置重新设置在队列的最后面(也就是当前的位置加上总的宽度)

// 处理移动 useTime:使用的时间
    void DealMove( float useTime)
    {
        float dis = useTime * m_moveSp;
        float x = 0;
        Vector2 parentSize = m_imgCellParent.GetComponent<RectTransform>().sizeDelta;
        // 遍历完所有的图片计算新位置
        foreach( RawImage img in m_allImgs)
        {
            RectTransform rectTran = img.GetComponent<RectTransform>();
            x = rectTran.localPosition.x - dis;
            // 跑出范围了,就把它加到后面去
            if( x < -(parentSize.x/2 + rectTran.sizeDelta.x/2 + m_spacing))
            {
                x = x + m_totalWidth;
            }
            rectTran.localPosition = new Vector3( x, 0, 0);
        }
    }

到目前为止,循环滚动的跑马灯效果已经完成了。

下面要处理点击图片后放大/缩小,滚动的开始/停止。

       要实现放大/缩小效果,需要另外创建一个图片专门用于放大缩小。因为如果直接用原图来放大的话,如果它的层级不是最高的,那么放大后层级比它高的图片会盖在它上面。图片缩放的时候需要用到dotween插件。

// 开始弹出
    public void StartPop( RawImage srcImg, PopCB popCB)
    {
        m_srcImg = srcImg;
        m_popCB = popCB;
        // 
        m_popPlane.SetActive( true);
        // 根据源图片初始化要缩放的图片的大小,位置
        RectTransform rectTran = m_scaleImg.GetComponent<RectTransform>();
        RectTransform srcImgTran = srcImg.GetComponent<RectTransform>();
        rectTran.sizeDelta = srcImgTran.sizeDelta;
        rectTran.localPosition = srcImgTran.localPosition;
        m_scaleImg.texture = srcImg.texture;
        // 计算出需要缩放的倍数
        float scaleX = m_maxSize.x/srcImgTran.sizeDelta.x;
        float scaleY = m_maxSize.y/srcImgTran.sizeDelta.y;
        float scale = Mathf.Min( scaleX, scaleY);
        m_bWaiting = true;
        Sequence quence = DOTween.Sequence();
        quence.Append( rectTran.DOScale( new Vector3(scale, scale, 1), m_animTime));
        quence.Join( rectTran.DOLocalMove( new Vector3(0,0,0), m_animTime));
        quence.AppendCallback( ()=>{
            // 动画完成
            m_bWaiting = false;
        });  
    }

给图片添加点击事件的时候用到了

EventTriggerListener.Get(imgCell.gameObject).onDown += OnClickImg;

EventTriggerListener这个类是自己封装的事件的监听类,具体的代码可以看项目源文件。

unity版本:unity 2020.3

源码路径:

autoRollImg.unitypackage-网络游戏文档类资源-CSDN下载

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zpba

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值