Cannot read 'sourceEvent' property from null in event listeners

I just started to learn the d3.js. library I need to make an SVG editor, and I taught that it is a good idea to use this. I have a problem, I wrote several functions and want these functions to be launched with one click.

The functions create a line from point A to point B, so I need to call these functions only when the Line button is pressed.

Here is the code block:

var line; var container = d3.select("body").append("svg") .on('mousedown',mousedown) .on('mouseup',mouseup); function mousedown() { 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]); container.on("mousemove", mousemove); }; function mousemove(){ var coordinates = d3.mouse(this); line.attr("x2", coordinates[0]) .attr("y2", coordinates[1]); }; function mouseup(){ container.on("mousemove", null); }; 

HTML

 <button id="lineBtn">Line</button> 

CSS

 line { stroke: black; stroke-width: 3px; } svg{ border:1px solid black; width:500px; height:500px; margin-left: 40%; margin-right:40%; } 
+6
source share
1 answer

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> 
0
source

Source: https://habr.com/ru/post/1209549/


All Articles