gpt4 book ai didi

javascript - 使用 D3.js 是重新绘制对象还是 "move"对象更好?

转载 作者:行者123 更新时间:2023-12-03 11:23:26 25 4
gpt4 key购买 nike

我一直在尝试动画。

通过清除整个 Canvas 并在每帧(或“滴答”)的新位置重新绘制它来在 Canvas 上为对象设置动画非常简单:

// Inside requestAnimationFrame(...) callback

// Clear canvas
canvas.selectAll('*').remove();

// ... calculate position of x and y
// x, y = ...

// Add object in new position
canvas.append('circle')
.attr('cx', x)
.attr('cy', y)
.attr('r', 10)
.attr('fill', '#ffffff');

这是一种不好的做法还是我做得对?

例如,如果您正在制作一个充满四处移动的对象的屏幕,通过在每一帧中更新它们的属性(例如,x、y 坐标)来为它们设置动画是否更好?

或者,也许还有其他一些我完全不知道的方法,不是吗?

注意:我的动画可能一次包含 100-200 个对象。

最佳答案

最好移动它们,因为这是您制作动画而不会出错的唯一方法。

在 d3.js 中,对象是数据绑定(bind)的。清除并重新绘制“ Canvas ”不是正确的方法。首先,它不是 Canvas ,它是网页,任何清除和重绘都由浏览器本身处理。您的工作基本上是将数据绑定(bind)到 SVG。

您需要使用 d3 事件,enterexitupdate,它处理 SVG 在数据绑定(bind)基础数据时的行为方式被修改并让 d3 处理动画。

最简单的例子在这里:https://bost.ocks.org/mike/circles/

  1. 选择您的元素,并将选择存储在变量中

var svg= d3.select("svg");

var circles = svg.selectAll('circle');

  1. 现在我们需要将一些数据绑定(bind)到圆上。

var databoundCircles = circles.data([12,13,14,15,66]);

这个数据可以是任何东西。通常我会期望一个对象列表,但这些都是简单的数字。

  1. 处理数据出现时“制作”的方式

databoundCircles.enter().append('circle');;

  1. 处理数据被删除后发生在他们身上的事情

databoundCircles.exit().remove()

  1. 处理数据更新时发生的事情

databoundCircles.attr('r', function(d, i) { return d * 2; })

这将在数据更改时更改半径。

并回顾该教程:

  1. enter - 传入元素,进入舞台。

  2. 更新 - 持久元素,留在舞台上。

  3. exit - 传出元素,退出舞台。

总而言之:不要像现在这样。确保您专门使用这些事件来处理元素的生命周期。

专业提示:如果您使用的是对象列表,请确保通过 id 或某些唯一标识符绑定(bind)数据,否则动画可能会表现异常时间。请记住,您正在将数据绑定(bind)到 SVG,您不仅仅是在删除和重绘 Canvas !

d3.selectAll('circle').data([{id:1},{id:2}], function(d) { return d.id; });

记下可选的第二个参数,它告诉我们如何绑定(bind)数据!非常重要!

var svg = d3.select("svg");

//the data looks like this.
var data = [{
id: 1,
r: 3,
x: 35,
y: 30
}, {
id: 2,
r: 5,
x: 30,
y: 35
}];


//data generator makes the list above
function newList() {
//just make a simple array full of the number 1
var items = new Array(randoNum(1, 10)).fill(1)
//make the pieces of data. ID is important!
return items.map(function(val, i) {

var r = randoNum(1, 16)

return {
id: i,
r: r,
x: randoNum(1, 200) + r,
y: randoNum(1, 100) + r
}
});
}

//im just making rando numbers with this.
function randoNum(from, to) {
return Math.floor(Math.random() * (to - from) + from);
}

function update(data) {

//1. get circles (there are none in the first pass!)
var circles = svg.selectAll('circle');

//2. bind data
var databoundCircles = circles.data(data, function(d) {
return d.id;
});

//3. enter
var enter = databoundCircles.enter()
.append('circle')
.attr('r', 0)

//4. exit
databoundCircles.exit()
.transition()
.attr('r', 0)
.remove();

//5. update
//(everything after transition is tweened)
databoundCircles
.attr('fill', function(d, i){
var h = parseInt(i.toString(16));
return '#' + [h,h,h].join('');
})

.transition()
.duration(1000)
.attr('r', function(d, i) {
return d.r * 4
})
.attr('cx', function(d, i) {
return d.x * 2;
})
.attr('cy', function(d, i){
return d.y * 2
})
;
}

//first time I run, I use my example data above
update(data);

//now i update every few seconds
//watch how d3 'keeps track' of each circle
setInterval(function() {
update(newList());
}, 2000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<svg width="500" height="300">

</svg>

关于javascript - 使用 D3.js 是重新绘制对象还是 "move"对象更好?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41155505/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com