According to your comment , the problem is how you handle the buttons:
document.getElementById("lineBtn").onclick = function drawLine(){ mousedown(); mousemove(); mouseup(); };
You cannot call these functions like this for several reasons, but mainly because there is no in this passed to d3.mouse and, therefore, not a single event is the source.
The best approach is to use the buttons to set the correct listeners, for example like this:
d3.select("#lineBtn").on("click", function() { container.on('mousedown', mousedownLine) .on('mouseup', mouseupLine); }); d3.select("#circleBtn").on("click", function() { container.on('mousedown', mousedownCircle) .on('mouseup', mouseupCircle); });
Here is a demo (using D3 v5, which is no different from your v3 regarding this issue):
var line; var circle; var container = d3.select("body").append("svg"); d3.select("#lineBtn").on("click", function() { container.on('mousedown', mousedownLine) .on('mouseup', mouseupLine); }); d3.select("#circleBtn").on("click", function() { container.on('mousedown', mousedownCircle) .on('mouseup', mouseupCircle); }); function mousedownLine() { container.on("mousemove", mousemoveLine); var coordinates = d3.mouse(this); line = container.append("line") .attr("x1", coordinates[0]) .attr("y1", coordinates[1]) .attr("x2", coordinates[0]) .attr("y2", coordinates[1]); }; function mousemoveLine() { var coordinates = d3.mouse(this); line.attr("x2", coordinates[0]) .attr("y2", coordinates[1]); }; function mouseupLine() { container.on("mousemove", null); }; function mousedownCircle() { container.on("mousemove", mousemoveCircle); var coordinates = d3.mouse(this); circle = container.append("circle") .attr("cx", coordinates[0]) .attr("cy", coordinates[1]); }; function mousemoveCircle() { var coordinates = d3.mouse(this); circle.attr("r", Math.hypot(coordinates[0] - circle.attr("cx"), coordinates[1] - circle.attr("cy"))); }; function mouseupCircle() { container.on("mousemove", null); };
line { stroke: teal; stroke-width: 2px; } circle { stroke: tomato; fill: none; stroke-width: 2px; } svg { border: 1px solid black; width: 500px; height: 300px; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script> <button id="lineBtn">Line</button> <button id="circleBtn">Circle</button>
source share