为什么要自己写组件
html中的标签可实现文字跑马灯效果,但这个标签在H5标准中已经被废弃,未来可能不受支持。
自定义的组件调整动画效果、性能方面更灵活,可以实现更多需求。
组件说明
本组件是基于React+hooks开发的,也可以改成vue的,动画原理一样。
组件可实现模拟标签的效果,也可使用css3动画获得更流畅的体验
参数说明:
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>
1
2
3
4
5
6
7
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>
1
2
3
4
5
6
7
组件源码
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
)
}
————————————————
版权声明:本文为CSDN博主「daoke_li」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/daoke_li/article/details/117300799