I’m just digging into d3 and learning a lot, but I’m sure I’m missing/misunderstanding some fundamentals here and would love some guidance.
Basically, I’d like to utilize d3 to draw a line segment that follows the mouse from the mousedown event (x1, y1) update the (x2, y2) coordinates as the mousemove event fires and finally finish/stop drawing the line once mouseup fires (finalizing the (x2, y2) coordinates).
Take a look at this jsFiddle I’ve setup to illustrate what I’m trying to do: http://jsfiddle.net/555Cv/
Obviously the issue is that the line isn’t updating as the mouse moves. It’s likely I’m going about this completely wrong, so any sort of guidance would be appreciated. Thanks!
UPDATE
I see there is d3.behavior.drag extensions, but I’m not sure if that’s exactly the type of thing I’d need or not (since the user isn’t exactly interacting with any objects, rather creating a new one on the fly (line object))
UPDATE 2
Okay, I’m trying to go about it a bit differently here, and it’s almost there I think. Although I’m sure there’s a much better way to do this. What’s below is close (but it doesn’t draw the lines).
var shapeCoords = [
[10, 10], [200, 10], [200, 200], [10, 200], [5, 100]
];
$(function() {
var container = $('#container');
// D3
console.log("D3: ", d3);
// Draw Shape
var svg = d3.select('#container').append('svg:svg').attr('height', 600).attr('width', 800);
var line = d3.svg.line()
.x(function(d) { return d[0]; })
.y(function(d) { return d[1]; })
.interpolate('linear');
svg
.data(shapeCoords)
.append('svg:path')
.attr('d', line(shapeCoords) + 'Z')
.style('stroke-width', 1)
.style('stroke', 'steelblue')
.style('fill', 'rgba(120, 220, 54, 0.2)');
// Draw Lines
var lineData = [];
var line = d3.svg.line()
.x(function(d) { return d.x; })
.y(function(d) { return d.y; })
.interpolate("linear");
var redrawLine = function() {
var svgLines = svg.selectAll('path')
.data(lineData);
svgLines.enter()
.append('path')
.attr('d', line(lineData))
.attr('class', 'my-lines');
svgLines.exit()
.remove();
console.debug("lineData", lineData);
};
var mouseIsDown = false;
container.on('mousedown mouseup mousemove', function(e) {
if (e.type == 'mousedown') {
mouseIsDown = true;
lineData[0] = {x:e.offsetX, y:e.offsetY};
redrawLine();
} else if (e.type == 'mouseup' ){
mouseIsDown = false;
lineData[1] = {x:e.offsetX, y:e.offsetY};
redrawLine();
} else if (e.type == 'mousemove') {
if (mouseIsDown) {
lineData[1] = {x:e.offsetX, y:e.offsetY};
redrawLine();
}
}
});
});
I’ve updated the jsFiddle here: http://jsfiddle.net/555Cv/1/
Ok, I think I’ve solved it, see jsFiddle: http://jsfiddle.net/555Cv/2/
But surely there must be a more elegant/proper way to do this…