javascript - 加速改变 div 元素颜色的 JavaScript 函数构造 'led display'

标签 javascript html css performance optimization

背景信息

对于我正在从事的元素,我需要模拟一行可以显示不同二进制数字的 LED。使用大量带有 border-radius: 50% 的 div 元素,我可以制作成行的“LED”。然后,JavaScript 函数可以应用不同的 css 类来更改每个元素的颜色,以模拟其打开或关闭。我拥有的另一个功能是工具提示,当您将鼠标悬停在 LED 上时,它会显示 LED 显示的数值。

问题

我遇到的问题是这种方法的性能。这是因为我的网页将使用许多这样的行,并且每行的值都会在每次屏幕刷新时通过 requestAnimationFrame() 更新。目前,在我的笔记本电脑上更新我页面上 LED 行的每个实例大约需要 5 毫秒。这绝对低于我们在 60Hz 下每帧的 16.6 毫秒 - 但是对于我的元素,每帧还需要完成许多其他事情,而这确实留给这些事情的时间很少。

一个例子

我当前实现的一个例子可以在 js fiddle 上找到:https://jsfiddle.net/dL6jq7or/25/ .单击“基准”文本并检查控制台以查看将 LED 行更新 50,000 次需要多长时间。您可以使用它来快速评估您提出的任何想法的表现。

注意:我每次都将显示设置为不同的值,以避免浏览器在检测到没有发生实际更改时可能执行的任何巧妙技巧。这些 LED 行的实际应用每次几乎总是会赋予它们不同的值,因此这使得基准测试更加真实。

我已经尝试加快速度

我在 led_strips 对象中缓存了对 LED 的引用,这给了一个小的性能提升,因为浏览器不必每次都执行 document.getElementById()更多。

我听说在元素中添加/删除 css 类比直接使用 JavaScript 更改其 css 属性更快。这就是代码添加或删除 on 类以更改 LED 状态的原因。

我发现,在尝试删除 led div 之前先检查它是否有 on 类(反之亦然),可以小幅提升性能。

注意事项

LED 灯带没有固定尺寸 - 它们中的 LED 数量应仅由其中包含的 led 类 div 的数量决定。

并非所有的 LED 灯带都有工具提示 - 如果它们应该有一个,则容器 div 将具有 tooltip-enabled 类并包含一个 tooltip-content div。

您会看到我注释掉了 display_number_on_leds 函数的一部分,它只在工具提示可见时更新它。此检查可显着提高性能,但意味着如果您在更改后将鼠标悬停在 strip 上,工具提示可能会显示错误的值。这是 Not Acceptable 。

浏览器更改显示数字的大部分时间似乎都花在重新计算页面的布局/样式上。避免这种情况肯定会提高性能,但我不确定该怎么做。

总结

谁能找到一种方法来加速 display_number_on_leds 函数,同时保留我目前拥有的功能?如果这种方法不可能更快地工作,是否有任何替代方法可以更快(也许是 Canvas ?)。

最佳答案

由于您没有在工具提示中设置任何 HTML,只有文本,您可以使用 nodeValuetextContentinnertext 之一来代替。 nodeValue尽管我在 Chrome 66 上的速度提高了 50% 以上,但这里似乎给出了最好的结果。

运行你的原始代码(使用 innerHTML)10 次给我:

50,000 iterations: 483.121826171875ms
50,000 iterations: 430.60400390625ms
50,000 iterations: 431.64599609375ms
50,000 iterations: 454.813232421875ms
50,000 iterations: 428.945068359375ms
50,000 iterations: 451.15673828125ms
50,000 iterations: 436.782958984375ms
50,000 iterations: 432.094970703125ms
50,000 iterations: 551.495849609375ms
50,000 iterations: 442.85400390625ms

使用 tooltip.childNodes[0].nodeValue = text;

50,000 iterations: 212.26611328125ms
50,000 iterations: 198.85595703125ms
50,000 iterations: 206.324951171875ms
50,000 iterations: 201.528076171875ms
50,000 iterations: 202.0048828125ms
50,000 iterations: 195.52685546875ms
50,000 iterations: 207.598876953125ms
50,000 iterations: 202.48291015625ms
50,000 iterations: 207.677001953125ms
50,000 iterations: 197.98583984375ms

使用tooltip.textContent = text;

50,000 iterations: 259.39892578125ms
50,000 iterations: 221.156005859375ms
50,000 iterations: 238.042236328125ms
50,000 iterations: 212.44189453125ms
50,000 iterations: 221.1201171875ms
50,000 iterations: 225.68212890625ms
50,000 iterations: 226.552001953125ms
50,000 iterations: 209.56494140625ms
50,000 iterations: 215.00439453125ms
50,000 iterations: 222.412109375ms

使用tooltip.innerText = text;

50,000 iterations: 208.27099609375ms
50,000 iterations: 196.996826171875ms
50,000 iterations: 204.372802734375ms
50,000 iterations: 208.3291015625ms
50,000 iterations: 266.80810546875ms
50,000 iterations: 203.071044921875ms
50,000 iterations: 208.48876953125ms
50,000 iterations: 206.7939453125ms
50,000 iterations: 203.4111328125ms
50,000 iterations: 214.489013671875ms

编辑

除了上述内容之外,您还可以执行一些其他操作来稍微提高性能。

1.

num_dec_digitsnum_hex_digits 不会在迭代之间更改值,因为它们只依赖于 LED 的数量,所以可以在 get_led_references() 改为:

function get_led_references(id) {
  var ref = document.getElementById(id);
  var has_tooltip = ref.children[0].className == "tooltip_content";
  var leds = Array.prototype.slice.call(ref.children);
  var references = {
    leds: leds,
    tooltip: has_tooltip ? leds.shift() : null
  };

  var log10_pow2 = Math.log10(Math.pow(2, leds.length));
  references.num_dec_digits = Math.ceil(log10_pow2);
  references.num_hex_digits = Math.ceil(log10_pow2 / Math.log10(16));

  return references;
}

当然,如果这样做,则 display_number_on_leds() 将必须相应更改。

2.

get_padded_num() 函数中,您当前分配的新字符串比您需要的要长。至少对于您提供的示例数据,一个在填充字符前面的 while 循环似乎执行速度提高了 10-20%:

function get_padded_num(number, length, base) {
  var str = number.toString(base);
  while (length > str.length) {
    str = '0' + str;
  }

  return str;
}

因此,通过添加修改,现在执行时间为:

50,000 iterations: 165.459716796875ms
50,000 iterations: 169.538818359375ms
50,000 iterations: 176.2109375ms
50,000 iterations: 170.885986328125ms
50,000 iterations: 167.305908203125ms
50,000 iterations: 169.608154296875ms
50,000 iterations: 168.797119140625ms
50,000 iterations: 175.070068359375ms
50,000 iterations: 165.182861328125ms
50,000 iterations: 169.580810546875ms

关于javascript - 加速改变 div 元素颜色的 JavaScript 函数构造 'led display',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51441551/

相关文章:

javascript - jQuery - 找到一个类存在并返回真/假

javascript - Socket.io 不使用 socket.on 添加消息

javascript - 使用 controllerAs 语法从 "this"访问指令的隔离范围

java - 使用带有 Java 的 Google Appengine 删除 .html 扩展名

html - 奇怪的边框在视频标签上留下黑色

android - 在 Android Opera Mini 浏览器上无法正确查看网站

javascript - 为什么我无法访问父窗口的变量?

javascript - 如何从无序列表中删除列表元素?

HTML CSS 在元素前放置一个未知的标签

css - li 项之间的空间