Estou usando ReactJS, d3JS e ES6 para criar um organograma. Posso criar o gráfico e vê-lo. Mas eu quero adicionar o zoom e o comportamento de arrastar ao gráfico, então usei d3.behavior.zoom . Posso ver que o método com zoom é chamado, mas o d3.event é nulo.
Tentei anexar o comportamento do zoom ao div, svg e g, mas nada ajudou. O comportamento ampliado é chamado, mas o evento é nulo.
Em meu projeto ASP.NET, certifiquei-me de não ter nenhuma referência a d3.js além da configuração systemJS, que muitas respostas de stackoverflow mencionaram como o problema relacionado ao motivo de d3.event ser nulo.
Meu código é muito semelhante ao que está em um exemplo como este https://github.com/Swizec/candidate-bucket-chart/blob/169779e110c8825f4545c71ae5845ff7bad4f1f4/src/BubbleChart.jsx que usa a versão antiga do ReactJS.
Esta é a minha configuração systemJS:
<script>
System.defaultJSExtensions = true;
System.config({
map: {
'rx': "https://cdnjs.cloudflare.com/ajax/libs/rxjs/4.0.7/rx.all.min.js",
'react': 'https://cdnjs.cloudflare.com/ajax/libs/react/15.0.1/react.js',
'react-dom': 'https://cdnjs.cloudflare.com/ajax/libs/react/15.0.1/react-dom.js',
'd3': 'https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.16/d3.js'
}
});
System.import('../app/app.js');
</script>
import React, { Component } from 'react';
import * as Rx from 'rx';
import * as d3 from 'd3';
import Person from './person';
class OrgChart extends Component {
constructor(props) {
super(props);
this.state = { persons: [] };
}
componentWillMount() {
// Just read a JSON file
var source = Rx.Observable.fromPromise($.getJSON("/js/org-persons.json"));
source.subscribe(
function(chart) {
var tree = d3.layout.tree()
.nodeSize([110, 50])
.separation(function() {
return 1;
});
var nodes = tree.nodes(chart[0]).reverse();
var links = tree.links(nodes);
var p = [];
nodes.forEach(function(node) {
fs.push((<Person x={node.x} y={node.y}></Person>));
}.bind(this));
this.setState({ person: p });
}.bind(this)
);
}
componentDidMount() {
var rootX = document.body.clientWidth / 4;
var rootY = 300;
// A standard setup with d3 to use it's zoom/drag behavior
var zoom = d3.behavior.zoom()
.scaleExtent([1, 10])
.on("zoom", this.zoomed)
.translate([rootX, rootY]);
// Attach zoom behavior to the first group in the svg.
d3.select("#viewport")
.call(zoom);
}
// When I drag the svg, this function gets called but the event is null. d3 is a global object.
zoomed() {
d3.select("#viewport").attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
}
// renders an org chart
render() {
return (
<div id='treeContainer'><svg id='fullTree' width='100%'>
<g id='viewport'>
{ this.state.persons }
</g>
</svg></div>
);
}
}
export default OrgChart;
O código ao qual você faz referência parece ser javascript d3 geral e o evento não passa pelo sistema de eventos do React. Parece uma questão d3, não relacionada ao React. Por esse motivo, encerrarei este problema.
Em outra nota, você deve usar um ref
para fazer referência a um nó DOM, NÃO selecionando por ID. Usar coisas como d3.select("#viewport")
pode causar problemas de interoperabilidade com outros componentes que escolhem o mesmo ID e evitar que um componente seja usado várias vezes na mesma página. Usar um ref
resolverá esses problemas.
Outros com esse problema certamente irão parar aqui, então aqui está uma abordagem que funcionou para mim:
> window.theD3versionHostingTheEvent = d3;
listener.apply(this, argumentz);
e, em seguida, escolha Avançar para a próxima chamada de função até chegar ao local que gerou o erro.window.theD3versionHostingTheEvent == d3
Se o resultado for false
, você definitivamente está executando duas instâncias de d3. No meu caso, descobri que uma das bibliotecas que eu estava usando tinha o d3 incluído.
É muito provável que você esteja usando o Babel, que tem problemas para importar um campo mutável do d3 usando a sintaxe de importação / exportação.
Veja isto: https://github.com/d3/d3/issues/2733#issuecomment -190743489
Você vai querer alterar a maneira como importa d3 com o seguinte:
import * as d3 from 'd3';
import {event as currentEvent} from 'd3';
E substitua todas as ocorrências de d3.event
por currentEvent
.
Isso corrige o problema com d3.js v3.
Comentários muito úteis
É muito provável que você esteja usando o Babel, que tem problemas para importar um campo mutável do d3 usando a sintaxe de importação / exportação.
Veja isto: https://github.com/d3/d3/issues/2733#issuecomment -190743489
Você vai querer alterar a maneira como importa d3 com o seguinte:
E substitua todas as ocorrências de
d3.event
porcurrentEvent
.Isso corrige o problema com d3.js v3.