我每100毫秒获得一次位置并将它们应用到DOM中:
const div = d3.select(container).selectAll('div').data(positions)
div.enter()
.append('div')
div.transition()
.duration(100)
.style({
top: d => d.y,
left: d => d.x,
})
div.exit()
.remove()
因此,元素可以在100毫秒内获得平滑动画,以获得下一个位置所需的100毫秒。这很好。
但我在DOM中有不同的元素依赖于第一个元素的位置。它们使用相同的位置数据进行渲染,但是在软件的不同模块中进行渲染。
我的问题是,此转换会插入其他模块无法使用的数据。这些其他模块的元素似乎提供了光学错误"可视化,因为它们基于原始数据。
示例:一个点移动到一个正方形并且正方形被突出显示,但点的位置被插值,并且正方形用于检查是否应该突出显示的位置不是。因此,即使该点不在其中,方形也会突出显示。
我如何解决这个问题?我可以在某处获取那些插值吗?
答案 0 :(得分:3)
我能想到的最简单的方法是使用转换的attrTween,styleTween或tween方法(https://github.com/mbostock/d3/wiki/Transitions#attrTween)。它们采用必须返回函数的函数(插值器)。该插补器将被多次调用以执行转换,因此您可以继续调用回调(cb),以便通知其他模块有关更改。
selection.styleTween('top', function(){
var interpol = d3.interpolate(0,10); //interpolate from 0 to 10
return function(t) { // this guy will be called many times to calc transition
// t will be changing from 0 to 1
var val = interpol(t);
cb(val); // <-- callback that will notify other modules about the change in value
return val; // <-- you have to return val so d3 transitions element
}
});
答案 1 :(得分:3)
如果我正确理解您,您希望完全控制补间功能:
div
.transition()
.duration(1000)
.tween("postion", function(d) {
var div = d3.select(this),
startTop = parseInt(div.style('top')),
startLeft = parseInt(div.style('left')),
yInterp = d3.interpolateRound(startTop, d.y),
xInterp = d3.interpolateRound(startLeft, d.x);
return function(t) {
div.style("top", yInterp(t) + "px");
div.style("left", xInterp(t) + "px");
};
});
工作代码:
<!DOCTYPE html>
<html>
<head>
<script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
</head>
<body>
<div id="parent">
<div style="width: 20px; top: 20px; left: 30px; height: 20px; background-color: steelblue; position: absolute"></div>
<div style="width: 20px; top: 0px; left: 40px; height: 20px; background-color: orange; position: absolute"></div>
</div>
<script>
var positions = [
{x: 50, y: 50},
{x: 100, y: 100}
];
var div = d3.select('#parent')
.selectAll('div')
.data(positions);
div
.transition()
.duration(1000)
.tween("postion", function(d) {
var div = d3.select(this),
startTop = parseInt(div.style('top')),
startLeft = parseInt(div.style('left')),
yInterp = d3.interpolateRound(startTop, d.y),
xInterp = d3.interpolateRound(startLeft, d.x);
return function(t) {
div.style("top", yInterp(t) + "px");
div.style("left", xInterp(t) + "px");
};
});
</script>
</body>
</html>
&#13;