问题
I'm still learning to program and I'm currently trying out the d3 library.
So far I'm pretty happy with the result. fiddle
Q: If you check out the link (or part of the code under this question) you should try to plot a point. This is only possible on the x-axis ticks. You'll see it animates but it's not exactly what I want. I just want it to animate the newly added line. I have checked out .enter() and .append() but I was getting errors. I might be doing something wrong.
function lines(x, y) {
this.x = x;
this.y = y+h;
}
var lineArray = [{x: 0, y: h}, {x: 1, y: h}];
var lineArrayPrevious = lineArray[lineArray.length -1].x;
var d3line = d3.svg.line()
.x(function(d) { return d.x; })
.y(function(d) { return d.y; })
.interpolate("monotone");
var path = svg.append("path").attr("d", d3line(lineArray)).attr("class", "line");
canPlot = true;
function plot() {
var m = d3.mouse(this);
if (m[0]-20 > lineArray[lineArray.length - 1].x) {
var lineX = lineArray.push(new lines(m[0], m[1]));
svg.selectAll("path")
.data(lineArray)
.attr("d", d3line(lineArray));
var point = svg.append("circle")
.attr("cx", function(d, i) { return m[0]; })
.attr("cy", function(d, i) { return m[1]+h; })
.attr("r", 0).transition().delay(150).attr("r", 6);
var totalLength = path.node().getTotalLength();
console.log();
path.attr("stroke-dasharray", totalLength + " " + totalLength)
.attr("stroke-dashoffset", totalLength)
.transition().duration(700).ease("linear").attr("stroke-dashoffset", 0).delay(200);
canPlot = true;
} else { console.log("error"); canPlot = false; }
}
Excuse my bad code, I'm learning and will clean it up eventually.
Q2: How hard would it be to make a circle that follows the mouse's y-position and moves on the ticks when you get near one?
Q3: If we solve my first question, would it be easy to get the lines to animate/update automatically when we do question 2?
Thanks in advance.
回答1:
I've updated your jsfiddle here to include the points that you're asking for.
Regarding question 1, I've changed the way the line is drawn such that it can be interpolated from the previous to the current point in a transition. The relevant code is this.
svg.select("path.line")
.attr("d", d3line(lineArray))
.transition().duration(700)
.attrTween('d', pathTween)
.each("end", function() {
var lineX = lineArray.push(new lines(m[0], m[1]));
});
var last = lineArray[lineArray.length-1];
function pathTween() {
var xi = d3.interpolate(last.x, m[0]),
yi = d3.interpolate(last.y, m[1] + h);
return function(t) {
return d3line(lineArray.concat([{x: xi(t), y: yi(t)}]));
};
}
Note that the new data point is only added to the array of points once the transition finishes.
Regarding your second question, this is taken care of by attaching handlers to all tick marks and append a marker on mouse over:
d3.selectAll(".xaxis > .tick").on("mouseenter", mousein)
.on("mousemove", mousemove)
.on("mouseleave", mouseout);
function mousein() {
svg.append("circle").attr("class", "marker").attr("r", 3)
.attr("pointer-events", "none");
}
function mousemove() {
d3.select("circle.marker")
.attr("transform", d3.select(this).attr("transform"))
.attr("cy", d3.mouse(this)[1] + h);
}
function mouseout() {
d3.select("circle.marker").remove();
}
来源:https://stackoverflow.com/questions/20362343/animate-path-line-from-last-known-point-to-new-added-point-d3