【问题标题】:Cannot read property 'sourceEvent' of null in event listeners无法在事件侦听器中读取 null 的属性“sourceEvent”
【发布时间】:2015-02-18 11:39:21
【问题描述】:

我刚开始学习 d3.js 库。我需要制作一个 svg 编辑器,我教过使用这个编辑器是个好主意。我有一个问题,我写了一些函数,我希望这些函数在鼠标点击时运行。

这些函数创建了一条从 A 点到 B 点的线,所以我只需要在单击 Line 按钮时调用这些函数。

这是代码块:

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%; 
}

【问题讨论】:

  • 您何时/在何处看到标题中的错误?
  • 在按钮上绑定功能时。 document.getElementById("lineBtn").onclick = function drawLine(){ mousedown();鼠标移动();鼠标向上(); }
  • start those functions only when Line button is clicked 是什么意思?在 svg 上的鼠标功能起作用之前,您首先必须单击 line 按钮?你想用它来关闭/打开画线功能吗? 或者你的意思是点击那个按钮应该画一条线吗?
  • 我将有例如 3 个按钮,直线、圆​​形、矩形。当我单击线条按钮时,我希望能够用鼠标画一条线。当我单击圆形时,我希望能够用鼠标绘制圆形,也可以绘制矩形。
  • 我在使用 techanjs/d3 和 vue.js 时遇到了类似的问题——有人知道如何让它工作吗?

标签: javascript d3.js dom-events


【解决方案1】:

根据您的comment,问题在于您处理按钮的方式:

document.getElementById("lineBtn").onclick = function drawLine(){ 
    mousedown(); 
    mousemove(); 
    mouseup(); 
};

您不能像这样调用这些函数有几个原因,但主要是因为没有 this 被传递给 d3.mouse,因此没有源事件。

更好的方法是使用按钮设置正确的侦听器,如下所示:

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);
});

这是一个演示(使用 D3 v5,在此问题上与您的 v3 没有什么不同):

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>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-09
    • 2015-11-13
    • 1970-01-01
    • 2020-07-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多