Thursday, April 25, 2024
 Popular · Latest · Hot · Upcoming
rated 0 times [  1] [ 6]  / answers: 1 / hits: 31929  / 10 Years ago, mon, march 24, 2014, 12:00:00

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 ='#container')
.attr('height', 600)
.attr('width', 800);

var line = d3.svg.line()
.x(function(d) { return d[0]; })
.y(function(d) { return d[1]; })

function render() {
.attr('d', line(shapeCoords) + 'Z')
.style('stroke-width', 1)
.style('stroke', 'steelblue');

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];


And the html:

<!DOCTYPE html>
<title>D3 mousemove</title>
<script type=text/javascript
<script type=text/javascript
<script type=text/javascript src=script.js></script>
#container {
width: 800px;
height: 600px;
border: 1px solid silver; }
path, line {
stroke: steelblue;
stroke-width: 1;
fill: none;
<div id=container></div>

More From » svg


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 of render() produced the expected behavior. More on selections here.

function render() {
path = svg.selectAll('path').data([shapeCoords])
path.attr('d', function(d){return line(d) + 'Z'})
.style('stroke-width', 1)
.style('stroke', 'steelblue');
path.enter().append('svg:path').attr('d', function(d){return line(d) + 'Z'})
.style('stroke-width', 1)
.style('stroke', 'steelblue');

Once you run the data join on path via .data(), operations performed on path will only apply to the update selection. Meaning, only those existing elements that still have corresponding data elements under the new join. When you call enter().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 after path.enter() apply only to new elements. It's not featured in the snippet above, but enter() adds the enter selection to the update selection: any operations on path after calling enter() would apply to both existing and new elements.

[#71801] Sunday, March 23, 2014, 10 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.

Total Points: 278
Total Questions: 101
Total Answers: 103

Location: Botswana
Member since Sat, Jan 7, 2023
1 Year ago