I'd like to apply the "general update pattern" from official documentation to update an svg path on the mouse event (but could be a button or whatever).
But the the path is only added and not updated. I think it's why I'm not properly using the enter
and exit
property but after some various trial, I cannot manage to let it work.
Here is a jsfiddle.
My js code is here:
var shapeCoords = [
[10, 10], [100, 10], [100, 100], [10, 100]
];
$(function() {
var container = $('#container');
// D3
console.log("D3: ", d3);
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');
function render() {
svg.data(shapeCoords)
.append('svg:path')
.attr('d', line(shapeCoords) + 'Z')
.style('stroke-width', 1)
.style('stroke', 'steelblue');
}
render();
var mouseIsDown = false;
container.on('mousedown mouseup mousemove', function(e) {
if (e.type == 'mousedown') {
mouseIsDown = true;
shapeCoords[3] = [e.offsetX, e.offsetY];
} else if (e.type == 'mouseup' ){
mouseIsDown = false;
shapeCoords[3] = [e.offsetX, e.offsetY];
} else if (e.type == 'mousemove') {
if (mouseIsDown) {
shapeCoords[3] = [e.offsetX, e.offsetY];
render();
}
}
});
});
And the html:
<!DOCTYPE html>
<html>
<head>
<title>D3 mousemove</title>
<script type="text/javascript"
src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js">
</script>
<script type="text/javascript"
src="http://mbostock.github.com/d3/d3.js">
</script>
<script type="text/javascript" src="script.js"></script>
<style>
#container {
width: 800px;
height: 600px;
border: 1px solid silver; }
path, line {
stroke: steelblue;
stroke-width: 1;
fill: none;
}
</style>
</head>
<body>
<div id="container"></div>
</body>
</html>
Your code isn't selecting an existing element, so instead of updating the "d" attribute of an existing path via the
update
selection, it's appending a new path each time. This version ofrender()
produced the expected behavior. More on selections here.Once you run the data join on
path
via.data()
, operations performed onpath
will only apply to the update selection. Meaning, only those existing elements that still have corresponding data elements under the new join. When you callenter().append()
it will append a new element for every data element without a pre-existing element, and then apply the following operations only to those elements.In the above, the first
path.attr()
above operates only on existing elements; those applied afterpath.enter()
apply only to new elements. It's not featured in the snippet above, butenter()
adds the enter selection to the update selection: any operations onpath
after callingenter()
would apply to both existing and new elements.Please try the following code, I think it's what you want. The problem is caused because you should distinguish enter, update and exit when you want to update elements, otherwise it will add data again and again.