我有一个迷宫,我想要的是在每个单元格上创建一个圆圈,然后将这些圆圈移动到迷宫的右侧作为树。我使用d3过渡和html5画布。我的问题是,如果有任何优化,我可以做。我不知道画布表现,所以我不知道我能期待多少。
对于1600个元素(600 px x 600 px和15px cellSize),动画很流畅。对于3600个元素,它不是。
mazeSelection.selectAll('cell')
.data(root.descendants())
.enter()
.append('cell')
.attr('radius', 0)
.attr('cx', d => d.data.ix * cellSize + 0.5 * cellSize,)
.attr('cy', d => d.data.iy * cellSize + 0.5 * cellSize)
.transition().duration(2000)
.attr('radius', cellSize/2)
.transition().duration(3000)
.attr('radius', cellSize/4)
.tween('position', function(d) {
const i = d3.interpolate([this.getAttribute('cx'), this.getAttribute('cy')], [width + d.x, cellSize * 0.5 + d.y]);
return (t) => {
[d.cx, d.cy] = i(t);
this.setAttribute('cx', d.cx);
this.setAttribute('cy', d.cy);
};
});
context.fillStyle = "white";
let timer = d3.timer(function redraw() {
// clear maze
context.beginPath();
context.fillRect(0, 0, width * 2, height);
//drawMaze(grid, context, width, height, cellSize);
context.beginPath();
// here we must use a function to have access to "this"
mazeSelection.selectAll('cell')
.each(function (d) {
const radius = this.getAttribute('radius'),
x = this.getAttribute('cx'),
y = this.getAttribute('cy');
context.moveTo(x, y);
context.arc(x, y, radius * 0.5, 0, 2 * Math.PI);
(d.children || []).forEach(child => {
context.moveTo(x, y);
context.lineTo(child.cx, child.cy);
});
});
context.stroke();
context.fill();
});
答案 0 :(得分:0)
你必须上学才能获得最佳表现。
我会忽略上半场因为我不确定你在做什么。我猜测.each
迭代
您在下面的代码中评论的性能方面的错误
// why use a let in global scope????
let timer = d3.timer(function redraw() {
context.beginPath();
context.fillRect(0, 0, width * 2, height);
context.beginPath();
// You wrote "here we must use a function to have access to "this""
// What 'this'? I assume it is the iterated cell `this`. Just use the
// cell referance, you dont have to use `this`
mazeSelection.selectAll('cell')
.each(function (d) { // dont use callbacks to iterate. For loops are much quicker
// on chrome const and let are half the speed of var
const radius = this.getAttribute('radius'), // why use getAttribute, a pointless and very CPU expensive way to get an object's property
x = this.getAttribute('cx'),
y = this.getAttribute('cy');
// why even assign the above properties to a const when you can use them directly
context.moveTo(x, y);
context.arc(x, y, radius * 0.5, 0, 2 * Math.PI);
// use a for loop and don't test for the existence of children
// by creating a new Array if they don't exist and then calling
// the array method forEach, a complete waste of CPU time
(d.children || []).forEach(child => {
context.moveTo(x, y);
context.lineTo(child.cx, child.cy);
});
});
context.stroke();
context.fill();
});
如果您尝试以下方法来迭代对象,您将获得一些额外的性能。然而,3000+可能仍然遥不可及。
var timer = d3.timer(function redraw() {
context.beginPath();
context.fillRect(0, 0, width * 2, height);
context.beginPath();
var cells = mazeSelection.selectAll('cell')
for(var i = 0; i < cells.length; i ++){
var d = cell[i];
var x = d.x; // create a local referance as x & y may be used many times
var y = d.y;
context.moveTo(x, y);
context.arc(x, y, d.radius * 0.5, 0, 2 * Math.PI);
if(d.children){
var c = d.children;
for(var j = 0; j < c.length; j++){
context.moveTo(x, y);
context.lineTo(c[j].cx, c[j].cy);
}
}
context.stroke();
context.fill();
};
如果您渲染的弧大小相同,则可以通过将弧渲染到屏幕外画布(精灵表)然后使用drawImage(spriteSheet,...
绘制弧来获得性能提升,具体取决于硬件/浏览器这可能是次要的或显着的性能提升