我有一个遗留代码,其中视频时间线是使用Canvas渲染的(据我所知,它比DOM渲染快)。
因此,作者使用fillRect()
方法编写了代码,但后来将其重写为组合moveTo(), lineTo(), stroke()
。
时间轴看起来像8 * 1000px矩形,可以包含数百个矩形。
我不能问他为什么要进行此更改,并且我认为使用fillRect()
会更好。
fillRect()
的渲染速度与线条(内部填充)一样快吗?
答案 0 :(得分:0)
第二种方法几乎总是更快。
直到它实际上必须 paint 为止,所有上下文API所做的只是简单的算术运算,全部在CPU上完成,这非常快。
所有复杂的绘画部分+合成需要很长时间。
通常,为了使此较慢的部分更快,浏览器会将其移至GPU。但是它仍然必须将所有数据从RAM移到GPU内存,这需要一些时间。
因此,使用路径操作方法并仅调用一次fill()
或stroke()
在CPU上构建一个复杂的形状肯定比在调用这些fill()
时创建相同的复杂路径要快。和stroke()
像fillRect
或strokeRect
这样的几次必定会这样做。
const rects = Array.from({ length: 300 }, (_) => ({
x: Math.random() * 1000,
y: Math.random() * 1000,
s: Math.random() * 200 + 50
}));
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
// Benchmark.js playground borrowed from
// https://jsfiddle.net/533hc71h/
var test1_name = 'fillRect';
function test1() {
rects.forEach(({ x, y, s }) => ctx.fillRect(x, y, s, s));
}
var test2_name = 'path + fill()';
function test2() {
ctx.beginPath();
rects.forEach(({ x, y, s }) => ctx.rect(x, y, s, s));
ctx.fill();
}
function teardown() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
var cycleResults = document.getElementById('cycleResults');
var result = document.getElementById('result');
var btn = document.getElementById('btn');
// BENCHMARK ====================
btn.onclick = function runTests() {
btn.setAttribute('disable', true);
cycleResults.innerHTML = '';
result.textContent = 'Tests running...';
var suite = new Benchmark.Suite;
// add tests
suite
.add(test1_name || 'test1', test1)
.add(test2_name || 'test2', test2)
// add listeners
.on('cycle', function(event) {
var result = document.createElement('li');
result.textContent = String(event.target);
document.getElementById('cycleResults')
.appendChild(result);
})
.on('complete', function() {
result.textContent = 'Fastest is ' + this.filter('fastest').pluck('name');
btn.setAttribute('disable', false);
teardown();
test2();
})
.run({
async: true
});
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/benchmark/1.0.0/benchmark.min.js"></script>
<ul id='cycleResults'>
</ul>
<div id="result">
</div>
<br>
<button id="btn">
Run Tests
</button><br>
<canvas id="canvas" width="1000" height="1000"></canvas>