我正在研究乌龟图形的d3.js实现。基本上,当我们给出绘制或移动的龟指令时,它会将这些指令转换为svg路径对象可接受的形式,以便它的" d"属性。
我希望用户能够提供乌龟指令(在javascript控制台或最终使用按钮),并让svg画布上的路径动态更新。现在我可以做到这一点,但transition()
还没有成功。即无论我为转换设置duration()
,它都会立即更新。也许这与我没有将指令作为数据绑定到路径元素这一事实有关?
我有一个Turtle构造函数和一个Vector2D构造函数,定义如下:
<body>
<script src="path_to_D3"></script>
<script>
var svg = d3.select("body").append("svg").attr("width", 800).attr("height", 800);
var xScale = d3.scale.linear().domain(-1000, 1000).range(0, 800)
var yScale = d3.scale.linear().domain(-1000, 1000).range(0, 800)
// Here's where I am having an issue with binding data.
var path = svg.append("path").attr("stroke", "red").attr("fill", "none");
// Proposed alternative: var path = d3.select(".turtlePath").data("");
// path.enter().append("path").attr("class", "turtlePath")
// .attr("d", function(d) { return d; });
//
function Vector2D(x, y) {
this.x = x
this.y = y
this.add = function(other) {
return new Vector2D(x + other.x, y + other.y)
}
this.scaleBy(factor) {
return new Vector2D(x * factor, y * factor)
}
}
functionTurtle() {
var position = new Vector2D(0, 0)
var angle = 0;
var pathInstruct = “M” + x(0) + “, “ + y(0) + “ “;
var moveDist = 100;
this.penDown = false;
this.goForward = function() {
var xAdd = Math.cos(angle);
var yAdd = Math.sin(angle);
position = position.add(new Vector2D(xAdd, yAdd).scaleBy(moveDist));
// Here is the crucial bit.
var newInstruct = "";
if (penDown) {
newInstruct = "L" + x(position.x) + ", " + y(position.y) + " ";
} else {
newInstruct = "m" + x(position.x) + ", " + y(position.y) + " ";
}
pathInstruct += newInstruct;
// Here's where I'd like the transition to occur.
path.attr("d", pathInstruct);
// Proposed: path.data(pathInstruct).transition().duration(500)
// .attr("d", function(d) { return d; });
}
}
</script>
</body>
然后我可以给出海龟命令并将它们显示在画布上:
var t = new Turtle()
t.penDown = true;
t.goForward();
t.goForward();
t.penDown = false;
乌龟的这些命令产生一条简单的水平线。但我喜欢动态更新的路径,而不是像Mike Bostock的post那样即时更新。我是否需要将路径指令作为数据绑定到路径元素?
答案 0 :(得分:0)
错误与转换无关 - 它是由初始化和更新步骤中.data()
调用引起的。
传递给.data()
的参数必须是一个数据值数组,即使您只有一个元素,因此只有一个数据值。 / p>
要解决此问题,您有两种选择:
通过在调用方法时将数据值包装在括号中来创建一个ad-hoc数组:
path.data([pathInstruct]).transition().duration(500)
.attr("d", function(d) { return d; });
使用.datum()
方法,该方法接受单个数据值并将其附加到选择中的每个元素:
path.datum(pathInstruct).transition().duration(500)
.attr("d", function(d) { return d; });
请注意,.datum()
方法不会创建enter()
或exit()
选项;在使用.datum()
设置数据之前,您必须先创建路径元素。