动态修改Javascript setInterval函数中的速度
我有一个react应用程序,它需要以不同的句子间隔显示一些文本,一次显示一个 我所做的就是把所有的句子放在一个数组中,然后创建一个setInterval函数:动态修改Javascript setInterval函数中的速度,javascript,reactjs,Javascript,Reactjs,我有一个react应用程序,它需要以不同的句子间隔显示一些文本,一次显示一个 我所做的就是把所有的句子放在一个数组中,然后创建一个setInterval函数: startShowingText() { let i = 0 this.setState({ timer: window.setInterval(() => { this.setState({ sentence: SENTENCES[i] })
startShowingText() {
let i = 0
this.setState({
timer: window.setInterval(() => {
this.setState({
sentence: SENTENCES[i]
})
i += 1
}, this.state.startingDuration)
})
}
不幸的是,这种方法有许多缺点:
1) 它需要一张支票才能终止
2) 我不能动态地修改时间,所以一旦设置了this.state.startingDuration
,这将是所有句子的速度
3) 由于某些原因,如果我将window.setInterval
函数指定给状态之外的变量,则不会执行该代码:
startShowingText() {
let i = 0
console.log('here')
const timer = window.setInterval(() => {
this.setState({
sentence: SENTENCES[i]
})
i += 1
}, this.state.startingDuration)
console.log('there')
}
此代码正在打印:
这里
那里
不触发实际计时器
如何改进代码并使间隔可动态调整?您可以使用从游戏开发世界借用的一种方法,在游戏开发世界中,他们创建以特定间隔运行的“游戏循环”。在循环中,您可以根据当前循环迭代确定是否是输出句子的时间 一个粗略的例子:
const语句={
“我的第一句话。”:1,
“我的第二句话。”:20,
“我的第三句话。”:25,
“我的第四句话。”:40
};
常数ticks=100;
常数maxLoops=100;
常数i=设置间隔(写操作,滴答声);
设loopCounter=0;
函数writeLoop(){
如果(loopCounter>maxLoops){
间隔时间(i);
}
for(句子中的句子){
让targetLoop=句子[句子];
if(loopCounter==targetLoop){
文件。书写(“”+句子+“”);
}
}
loopCounter=loopCounter+1;
}
您可以使用设置超时
和递归函数,如下所示
类应用程序扩展了React.Component{
句子=[“第1句”、“第2句”、“第3句];
延迟时间=[10005003000];
建造师(道具){
超级(道具);
此.state={
已选择:0,
}
}
componentDidMount(){
这个。show句子();
}
show句子(){
const{selected}=this.state;
设置超时(()=>{
这个.setState({selected:(selected+1)%3});
这个。show句子();
},此.delayTime[所选])
}
render(){
返回(
{this.states[this.state.selected]}
);
}
}
ReactDOM.render(,document.getElementById('app'))
您可以递归调用
设置超时
并根据当前对话框更新速度
每个对话框的速度是每秒键入的字母数
var对话框=[{
正文:“知识产权是一种权利,是一种权利,是一种权利,是一种权利,是一种权利。”,
速度:120
}, {
正文:“我们必须尽可能少地进行实验,以确保我们的实验室能够满足我们的需求。”,
速度:60
}, {
课文:“两人或两人在婚姻中的相互尊重是不平等的。”,
速度:90
}, {
正文:“不可因疏忽大意而导致死亡的例外情况,不得因疏忽而导致动物死亡。”,
速度:30
}];
让estimatedTime=dialog.reduce((d,e)=>d+((1000/e.speed)*e.text.length)/1000,0);
log(`estimatedTime:${estimatedTime.toFixed(3)}秒`);
var startTime=new Date().getTime();
typeDialog(dialog,document.getElementById('lorem'),()=>{
让endTime=newdate().getTime();
让持续时间=(endTime-startTime)/1000;
让延迟=持续时间-估计时间;
log(`Task take:${duration.toFixed(3)}秒`);
log(`Latency:${Latency.toFixed(3)}秒`);
});
函数类型对话框(对话框、目标、完成){
如果(dialog.length>0){
让索引=0,速度=1000/对话框[index]。速度,
Current段落=document.createElement('p');
targetEl.appendChild(当前段落);
类型字符(索引,0,速度);
函数类型字符(索引、字母、速度){
如果(字母>对话框[索引].text.length){
索引++;字母=0;
如果(索引<对话框长度){
速度=1000/对话框[索引]。速度;
Current段落=document.createElement('p');
targetEl.appendChild(当前段落);
}
}
如果(索引<对话框长度){
设置超时(()=>{
Current段落.textContent+=对话框[索引].text.charAt(字母);
字体字符(索引,字母+1,速度)
},速度);
}否则{
if(completeFn!=null){
completeFn.call();
}
}
}
}
}
。作为控制台包装。作为控制台行代码,
.作为控制台包装。作为控制台行::之后,
#洛雷姆p{
字体大小:较小;
}
最好使用setTimeout
解决您的问题。您必须递归调用setTimeout
。