一、需求
1、一条或者多条滚动文字,有序切换
2、循环滚动
二、原理
setInterval:控制循环
requestAnimationFrame:动画效果
三、实现
constructor() {
super();
this.state = {
sloganList: [
"横向滚动文字1横向滚动文字1横向滚动文字1横向滚动文字1",
"横向滚动文字2",
"横向滚动文字3",
],
sloganIndex: 0,//展示的文本下标
}
this.sign = true;//定时器判断是否要进行文字滚动动画
this.textWidth = 0;//文字的宽度
this.textLeft = 0;
this.offsetStep = 3;//每次移动的步长
}
constructor内部主要记录了滚动文字的基本信息,重要的两个参数是sloganIndex,sign。 sloganIndex控制目前需要展示的数据下标 sign则是判断是否调用文字滚动控制方法,值为true则调用,进入新一轮的滚动动画
componentDidMount() {
let sloganContainer = this.container.clientWidth;
this.text.style.left = sloganContainer + "px";
this.timer = setInterval(() => {
if (this.sign) {
if(Array.isArray(this.state.sloganList)&&this.state.sloganList.length) {
this.showSlogan();
} else {
clearInterval(this.timer);
}
} else {
this.timer = null;
}
}, 1000);
}
componentWillUnmount() {
clearInterval(this.timer);
}
在组建渲染完成后定时器启动,通过sign信号控制是否执行滚动方法;组件销毁、数据格式错误或是没有数据时清除定时器
showSlogan = () => {
this.textWidth = this.text.clientWidth;//文字宽度
this.textLeft = parseInt(this.text.style.left);//相对父元素偏移距离
if(this.textLeft >= -this.textWidth) this.sign = false;
if(this.textLeft > -this.textWidth) {
this.text.style.left = this.textLeft - this.offsetStep + "px";
requestAnimationFrame(this.showSlogan)
} else {
let nextIndex =
this.state.sloganIndex != this.state.sloganList.length - 1 ? ++this.state.sloganIndex : 0;
this.setState({
sloganIndex: nextIndex
}, () => {
this.text.style.left = this.container.clientWidth + "px";
this.textWidth = this.text.clientWidth;
this.sign = true;
})
}
}
1、开始滚动前,将sign设置为false,滚动期间不会重复调用 2、文字直到最后一个字消失本次任务才算结束,所以文字元素最后的left值为元素宽度的负值 3、本轮动画结束后判断下一个动画文字所在下标,改变sloganIndex 4、待新内容渲染结束后设置新文字元素在内容区的最右边,并获取新的滚动文字宽度 5、设置sign为true,定时器运行时检查到该值为true则调用showSlogan方法
四、完整代码
class Slogan extends Component {
constructor() {
super();
this.state = {
sloganList: [
"横向滚动文字1横向滚动文字1横向滚动文字1横向滚动文字1",
"横向滚动文字2",
"横向滚动文字3",
],
sloganIndex: 0,
}
this.sign = true;//判断是否进行文字滚动动画
this.textWidth = 0;//文字的宽度
this.textLeft = 0;
this.offsetStep = 3;//每次移动的步长
}
componentDidMount() {
let sloganContainer = this.container.clientWidth;
this.text.style.left = sloganContainer + "px";
this.timer = setInterval(() => {
if (this.sign) {
if(this.state.sloganList&&this.state.sloganList.length) {
this.showSlogan();
} else {
clearInterval(this.timer);
}
} else {
this.timer = null;
}
}, 1000);
}
componentWillUnmount() {
clearInterval(this.timer);
}
render() {
const { sloganList, sloganIndex } = this.state;
return (
<div ref={(ref) => this.container = ref} className="container"> <span ref={(ref) => this.text = ref} className="slogan"> {sloganList[sloganIndex]} </span> </div>
)
}
showSlogan = () => {
this.textWidth = this.text.clientWidth;//文字宽度
this.textLeft = parseInt(this.text.style.left);//相对父元素偏移距离
if(this.textLeft >= -this.textWidth) this.sign = false;
if(this.textLeft > -this.textWidth) {
this.text.style.left = this.textLeft - this.offsetStep + "px";
requestAnimationFrame(this.showSlogan)
} else {
let nextIndex = this.state.sloganIndex != this.state.sloganList.length - 1 ? ++this.state.sloganIndex : 0;
this.setState({
sloganIndex: nextIndex
}, () => {
this.text.style.left = this.container.clientWidth + "px";
this.textWidth = this.text.clientWidth;
this.sign = true;
})
}
}
}
.container {
width: 70%;
height: 35px;
line-height: 35px;
margin: 0 auto;
border: 1px solid #B0BEC5;
padding: 0 10px;
position: relative;
overflow: hidden;
}
.slogan {
position: relative;
display: inline-block;
}
五、总结
主要做个记录,也没用jQuery,原生js的getter/setter操作太麻烦了 希望互相学习,非常感谢。
今天的文章多条文字切换滚动实现(React、JS)分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/22955.html