代码之家  ›  专栏  ›  技术社区  ›  Adam Zerner

如何避免“跳跃式”UI更新?

  •  0
  • Adam Zerner  · 技术社区  · 7 年前

    我想运行模拟并更新进度条,但进度条会以“跳跃”的方式更新。从21%到34%再到76%。我想一个接一个地从21%到22%再到23%等等。

    将此视为 SSCCE :

    http://embed.plnkr.co/XIKxpV6oWyWiwklFBSLh/

    HTML

    <button>Simulate</button>
    

    JS公司

    $(document).ready(function () {
      var $button = $('button');
    
      var worker = new Worker("worker.js");
      worker.addEventListener("message", function(e) {
        if (e.data) {
          switch (e.data.cmd) {
            case "progress":
              $button.text((e.data.value / 250).toFixed(0) + "%");
              break;
            case "complete":
              $button.text("Simulate");
              break;
          }
        }
      });
      $button.on("click", function() {
        worker.postMessage("start");
      });
    });
    

    工人

    this.addEventListener("message", function(e) {
      if (e.data === "start") {
        for (var n = 0; n < 250000000; ++n) {
          if (n % 10000 === 1) {
            this.postMessage({cmd: "progress", value: n / 10000});
          }
        }
        this.postMessage({cmd: "complete"});
      }
    });
    

    如何才能使其顺利更新?为什么一开始更新不顺畅?

    1 回复  |  直到 7 年前
        1
  •  0
  •   BrunoLM    7 年前

    你可以改变 progress 提供填充值。

    它之所以不平滑,是因为它没有为所有值发布进度值,只有每个 10000 (如果您尝试发布每个值,您的浏览器很可能会冻结)

    if (n % 10000 === 1) {
      this.postMessage({cmd: "progress", value: n / 10000});
    }
    

    所以你不能得到所有可能的%值,你需要填充。

    像这样的

    $(document).ready(function () {
      var $button = $('button');
    
      var last = 0
      var worker = new Worker("worker.js");
      worker.addEventListener("message", function process(e) {
        if (e.data) {
          switch (e.data.cmd) {
            case "progress":
              var next = (e.data.value / 250)
              var current = last
    
              // fill values
              // from last % to new %
              for (; current < next; ++current) {
                $button.text(current + "%")
              }
    
              last = current
    
              $button.text(next.toFixed(0) + "%");
    
              break;
            case "complete":
              $button.text("Simulate");
              break;
          }
        }
      });
    
      $button.on("click", function() {
        worker.postMessage("start");
      });
    });