React v16-d3 v4,使用从d3-selection中选择鼠标时会得到TypeError:无法读取null的属性'sourceEvent'吗?

Ali*_*eza 3 javascript event-handling javascript-events d3.js reactjs

d3React结合使用,并从d3选择中导入鼠标

import { selectAll, select, mouse } from 'd3-selection';
Run Code Online (Sandbox Code Playgroud)

尝试mouse(e.target) or mouse(select('.element'))在组件中使用:时,出现以下错误:

TypeError: Cannot read property 'sourceEvent' of null
./node_modules/d3-selection/src/sourceEvent.js.__webpack_exports__.a
node_modules/d3-selection/src/sourceEvent.js:5
  2 | 
  3 | export default function() {
  4 |   var current = event, source;
> 5 |   while (source = current.sourceEvent) current = source;
  6 |   return current;
  7 | }
  8 | 
Run Code Online (Sandbox Code Playgroud)

使用react-create-app创建的项目,似乎无法访问源事件?...

Ali*_*eza 5

经过研究后的最佳解决方案是,因为我没有使用d3-events,我们应该通过调用传递事件以解决问题...

var mouse = function(node) {
  var event = sourceEvent();
  if (event.changedTouches) event = event.changedTouches[0];
  return point(node, event);
};
Run Code Online (Sandbox Code Playgroud)

d3.mouse不接受event作为参数,但是如果您阅读源代码,则可以找到另一个通过mouse()调用的函数,以返回值并将其接受event作为参数,该函数称为clientPoint()

因此,不要使用mouse(),而是使用clientPoint()

就我而言,这可行:

import { selectAll, select, clientPoint } from 'd3-selection';
Run Code Online (Sandbox Code Playgroud)

和:

myFunction(e){
  console.log(clientPoint(e.target, e));
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,我同时将element和event传递为clientPoint(在代码中称为point,但导出为clientPoint)将接受(节点,事件),如您在源代码中看到的那样:

var point = function(node, event) {
  var svg = node.ownerSVGElement || node;

  if (svg.createSVGPoint) {
    var point = svg.createSVGPoint();
    point.x = event.clientX, point.y = event.clientY;
    point = point.matrixTransform(node.getScreenCTM().inverse());
    return [point.x, point.y];
  }

  var rect = node.getBoundingClientRect();
  return [event.clientX - rect.left - node.clientLeft, event.clientY - rect.top - node.clientTop];
};
Run Code Online (Sandbox Code Playgroud)

希望这对使用React v16和D3 v4的人有所帮助...