Javascript/React:使用真实的变化的延迟调用setTimeout

gorkyyrv  于 2023-01-01  发布在  Java
关注(0)|答案(2)|浏览(124)

我正在编写一个程序,在react中可视化合并排序。我希望允许用户使用滑块来改变排序速度。我在for循环中使用setTimeout函数,以便将迭代安排为等间隔的时间间隔。我希望以某种方式将从滑块获得的值反映在setTimeout中,但是,由于循环立即执行,并且调度循环的迭代,所以当执行程序时立即计算延迟值。

const MergeSort = () => {
    let animations = sortingAlgorithms.mergeSort(array);
    console.log(animations.length);
    for (let i = 0; i < animations.length; i++) {
      //   speed++;
      //   console.log(i);

      setTimeout(() => {
        // setSpeed(tempSpeed);
        const topArrayBars = document.getElementsByClassName("array__bar");
        const bottomArrayBars =
          document.getElementsByClassName("array__baraux");
        if (animations[i].type === "look") {
          for (let j = 0; j < topArrayBars.length; j++) {
            topArrayBars[j].style.backgroundColor = "rgb(57, 200, 195)";
          }
          for (let j = animations[i].look[0]; j <= animations[i].look[1]; j++) {
            topArrayBars[j].style.backgroundColor = "rgb(255, 79, 120)";
          }
        } else if (animations[i].type === "join") {
          for (let j = 0; j < topArrayBars.length; j++) {
            topArrayBars[j].style.backgroundColor = "rgb(57, 200, 195)";
          }
          //   left color
          for (
            let j = animations[i].leftIndices[0];
            j <= animations[i].leftIndices[1];
            j++
          ) {
            topArrayBars[j].style.backgroundColor = "rgb(255, 77, 252)";
          }
          // right color
          for (
            let j = animations[i].rightIndices[0];
            j <= animations[i].rightIndices[1];
            j++
          ) {
            topArrayBars[j].style.backgroundColor = "rgb(255, 237, 77)";
          }
        } else if (animations[i].type === "place") {
          bottomArrayBars[animations[i].newIdx].style.height =
            topArrayBars[animations[i].oldIdx].style.height;
          bottomArrayBars[animations[i].newIdx].style.backgroundColor =
            topArrayBars[animations[i].oldIdx].style.backgroundColor;
          topArrayBars[animations[i].oldIdx].style.backgroundColor =
            "rgba(57, 200, 195, 0)";
        } else if (animations[i].type === "lift") {
          for (
            let j = animations[i].range[0];
            j <= animations[i].range[1];
            j++
          ) {
            topArrayBars[j].style.height =
              animations[i].newVals[j - animations[i].range[0]].toString() +
              "px";
            topArrayBars[j].style.backgroundColor = "rgb(57, 200, 195)";
          }
          for (let j = 0; j < topArrayBars.length; j++) {
            topArrayBars[j].style.backgroundColor = "rgb(57, 200, 195)";
          }
          for (let j = 0; j < bottomArrayBars.length; j++) {
            bottomArrayBars[j].style.backgroundColor = "rgba(57, 200, 195, 0)";
          }
        }
      }, i * getSpeed());
    }

上面的getSpeed函数试图从一个由滑块控制的名为speed的useState变量中提取速度。2然而,我不知道如何让程序等待滑块值是多少来改变动画的速度。
我想让循环迭代如下:执行一次检查速度值,并等待1/速度再次执行检查速度值,并等待1/速度...

plicqrtu

plicqrtu1#

下面的代码片段说明了您的方法和Bergi的方法之间的差异。

var speed = 100;
function action(i) {
    document.getElementById("counter").textContent = i;
}
function animation1() {
    for (var i = 0; i < 100; i++)
    setTimeout(action.bind(undefined, i), i * speed);
}
function animation2(steps) {
    action(steps);
  if (steps < 100)
    setTimeout(function() {
      animation2(steps + 1);
    }, speed);
}
<span id="counter"></span>
<input type="range" onchange="speed=this.value" value="100" min="0" max="1000"/>
<button onclick="animation1(0)">Fixed speed</button>
<button onclick="animation2(0)">Flexible speed</button>
igetnqfo

igetnqfo2#

实际上,我是通过ChatGPT解决这个问题的。关键是,我在代码中错误的部分设置了超时。超时应该在包含在promise中的循环的末尾。请参见下面的代码:

this.setState({ prevArray: this.state.array.slice() });
    let animations = sortingAlgorithms.mergeSort(this.state.array);
    for (let i = 0; i < animations.length; i++) {
      const topArrayBars = document.getElementsByClassName("array__bar");
      const bottomArrayBars = document.getElementsByClassName("array__baraux");
      if (animations[i].type === "look") {
        for (let j = 0; j < topArrayBars.length; j++) {
          topArrayBars[j].style.backgroundColor = "rgb(57, 200, 195)";
        }
        for (let j = animations[i].look[0]; j <= animations[i].look[1]; j++) {
          topArrayBars[j].style.backgroundColor = "rgb(255, 79, 120)";
        }
      } else if (animations[i].type === "join") {
        for (let j = 0; j < topArrayBars.length; j++) {
          topArrayBars[j].style.backgroundColor = "rgb(57, 200, 195)";
        }
        //   left color
        for (
          let j = animations[i].leftIndices[0];
          j <= animations[i].leftIndices[1];
          j++
        ) {
          topArrayBars[j].style.backgroundColor = "rgb(255, 77, 252)";
        }
        // right color
        for (
          let j = animations[i].rightIndices[0];
          j <= animations[i].rightIndices[1];
          j++
        ) {
          topArrayBars[j].style.backgroundColor = "rgb(255, 237, 77)";
        }
      } else if (animations[i].type === "place") {
        bottomArrayBars[animations[i].newIdx].style.height =
          topArrayBars[animations[i].oldIdx].style.height;
        bottomArrayBars[animations[i].newIdx].style.backgroundColor =
          topArrayBars[animations[i].oldIdx].style.backgroundColor;
        topArrayBars[animations[i].oldIdx].style.backgroundColor =
          "rgba(57, 200, 195, 0)";
      } else if (animations[i].type === "lift") {
        for (let j = animations[i].range[0]; j <= animations[i].range[1]; j++) {
          topArrayBars[j].style.height =
            animations[i].newVals[j - animations[i].range[0]].toString() + "px";
          topArrayBars[j].style.backgroundColor = "rgb(57, 200, 195)";
        }
        for (let j = 0; j < topArrayBars.length; j++) {
          topArrayBars[j].style.backgroundColor = "rgb(57, 200, 195)";
        }
        for (let j = 0; j < bottomArrayBars.length; j++) {
          bottomArrayBars[j].style.backgroundColor = "rgba(57, 200, 195, 0)";
        }
      }

      console.log(i);
      await new Promise((resolve) =>
        this.timeouts.push(setTimeout(resolve, this.state.delay))
      );
    }
  }

然后,您将有一个滑块设置延迟,它的工作!

相关问题