对于我正在从事的项目,我需要模拟一行可以以二进制形式显示不同数字的LED。通过在border-radius: 50%
中使用许多div元素,我可以制作成行的“ LED”。然后,JavaScript函数可以应用不同的CSS类来更改每个元素的颜色,以模拟它的打开或关闭状态。我的另一个功能是工具提示,当您将鼠标悬停在LED上时,它们会显示LED所显示的数值。
我遇到的问题是这种方法的性能。这是因为我的网页将使用许多这样的行,并且每行通过requestAnimationFrame()
进行的屏幕刷新都会更新其值。目前,在笔记本电脑上更新页面上LED行的每个实例大约需要5毫秒。对于60Hz的每帧,这肯定低于我们的16.6ms-但是,对于我的项目,每帧还需要做很多其他事情,这确实为这些时间留了很少的时间。
在js提琴上可以找到我目前的实现示例:https://jsfiddle.net/dL6jq7or/25/。单击“基准”文本,然后检查控制台以查看更新50,000行LED所花费的时间。您可以使用它来快速评估您提出的任何想法的效果。
注意:我每次都会将显示设置为不同的值,以避免浏览器在未检测到实际变化的情况下进行任何巧妙的欺骗。这些LED行的实际应用几乎总是每次都为它们提供不同的值,从而使基准更加逼真。
我将对LED的引用缓存在led_strips
对象中,这对性能带来了很小的提升,因为浏览器不再需要每次都document.getElementById()
。
我听说在元素中添加css类和从中移除css类比直接用JavaScript更改其css属性要快。这就是为什么代码添加或删除on
类以更改led的状态的原因。
我发现,先检查led div是否具有on
类,然后再尝试将其删除(反之亦然),可以提高性能。
LED灯条没有固定的尺寸-LED灯条的数量只能由其中包含的led
类div的数量来确定。
不是所有的LED灯条都具有工具提示-如果它们应该有一个工具提示,则容器div将具有tooltip-enabled
类并包含tooltip-content
div。
您将看到我注释了display_number_on_leds
函数的一部分,该部分仅在工具提示可见时进行了更新。此检查可以显着提高性能,但是这意味着如果在更改条之后将鼠标悬停在条上,则工具提示可能显示错误的值。这是不可接受的。
浏览器更改显示数字所花费的大部分时间似乎是在重新计算页面的布局/样式。避免这种情况肯定会提高性能,但是我不确定该怎么做。
有人能看到一种加快display_number_on_leds
功能的方法,该方法可以保留我目前拥有的功能吗?如果这种方法不可能更快地工作,那么有没有其他替代方法可能会更快一些(也许是画布?)。
答案 0 :(得分:1)
由于您没有在工具提示中设置任何HTML,只能设置文本,因此可以使用nodeValue
,textContent
或innertext
中的一种。 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_digits
和num_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