CSS3实现像marquee的文字走跑马灯(滚动字幕)组件

为什么要自己写组件

  1. html中的标签可实现文字跑马灯效果,但这个标签在H5标准中已经被废弃,未来可能不受支持。
    自定义的组件调整动画效果、性能方面更灵活,可以实现更多需求。

组件说明

  1. 本组件是基于React+hooks开发的,也可以改成vue的,动画原理一样。
  2. 组件可实现模拟标签的效果,也可使用css3动画获得更流畅的体验
  3. 参数说明:
    v - 速度,每秒移动多少个像素,默认100
    t - 刷新一次的时长(ms),默认50,只在frameWise为true时有效
    frameWise - 为true即表示使用逐帧动画效果,内容运动过程中有振动的感觉;
    为false则使用css3的过渡效果制作成动画,性能好,比较较流畅

使用举例

1. 模拟逐帧动画

 <CssMarquee v={80}>{
         list.map(item =>
              <div className={'item'} onClick={() => gotoDetail(item)}>
                  <span className={'point'}>·</span>{item.content}
              </div>
          )}
</CssMarquee>

2. css3动画

<CssMarquee frameWise v={80} t={36}>{
          list.map(item =>
                 <div className={'item'} onClick={() => gotoDetail(item)}>
                          <span className={'point'}>·</span>{item.content}
                 </div>
          )}
</CssMarquee>

组件源码

import { useState, useEffect, useRef } from 'react'

// children - 传入的内容,即调用组件时写在首位标签之间的内容
// v - 每秒移动多少个像素
// t - 刷新一次的时长(ms),只在frameWise为true时有效
// frameWise - 为true即表示使用逐帧动画效果,内容运动过程中有振动的感觉;
//             为false则使用css3的过渡效果制作成动画,性能好,比较较流畅
export default ({ children, frameWise, v = 100, t = 50 }) => {
    const wrapRef = useRef() // 动画容器
    const contentRef = useRef() // 动画内容
    const [offsetX, setOffsetX] = useState(0)
    const _offsetX = useRef()

    useEffect(() => {
        frameWise && (_offsetX.current = offsetX)
    })
    useEffect(() => {
        const wrapWidth = wrapRef.current.offsetWidth // 容器宽度
        const contentWidth = contentRef.current.scrollWidth // 内容宽度

        if (frameWise) {
            // 使用定时器来控制移动
            setOffsetX(wrapWidth)
            const timer = setInterval(() => {
                if (-_offsetX.current > contentWidth) {
                    setOffsetX(wrapWidth)
                } else {
                    setOffsetX(x => x - v * (t / 1000))
                }
            }, t)
            return () => {
                clearInterval(timer)
            }
        }

        // 使用css3的过渡实现
        const deltaX = contentWidth + wrapWidth // 移动距离
        const deltaT = deltaX / v + 's' // 周期
        contentRef.current.style.transitionTimingFunction = 'linear' // 线性动画

        const animation = () => {
            // 每个周期的开始,先让内容归位
            contentRef.current.style['transition-duration'] = '0s'
            contentRef.current.style.transform = `translateX(${wrapWidth}px)`
            // 设置过渡时间和目标
            setTimeout(() => {
                contentRef.current.style.transitionDuration = deltaT
                contentRef.current.style.transform = `translateX(${-contentWidth}px)`
            }, 100)
        }
        animation()

        const timer = setInterval(() => {
            animation()
        }, deltaX * 1000 / v + 100)

        return () => {
            clearInterval(timer)
        }
    }, [])

    return (children.length
        ? <div className={'m-cssMarquee'}>
            <div className={'wrap'} ref={wrapRef}>{
                frameWise
                    ? <div className={'content'} ref={contentRef} style={{ transform: `translateX(${offsetX}px)` }}>{children}</div>
                    : <div className={'content'} ref={contentRef}>{children}</div>
            }
            </div>
        </div>
        : null
    )
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值