d3.event在ReactJS + d3JS组件中为null

时间:2016-04-27 10:38:48

标签: d3.js reactjs system

我正在使用 ReactJS,d3JS和ES6 来创建组织结构图。我可以创建图表并查看它。但我想将缩放行为添加到图表中,因此我使用了 d3.behavior.zoom 。我可以看到调用缩放方法,但 d3.event 为空。

在我的ASP.NET项目中,我确保除了systemJS配置之外没有任何对 d3.js 的引用,许多stackoverflow答案提到了与相关的问题d3.event 为空。

这是我的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>

OrgChart组件:

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() {
        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;

        var zoom = d3.behavior.zoom()
            .scaleExtent([1, 10])
            .on("zoom", this.zoomed)
            .translate([rootX, rootY]);

        d3.select("#viewport")
            .call(zoom);
    }

    zoomed() {
        d3.select("#viewport").attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
    }

    render() {

        return (
            <svg id='fullTree' width='100%'>
                <g id='viewport'>
                    { this.state.persons }
                </g>
            </svg>
        );
    }
}

export default OrgChart;

5 个答案:

答案 0 :(得分:16)

如果您使用的是React,Babel或Webpack以及d3.js v4,您似乎需要从d3-selection导入event才能使用d3.event

import * as d3 from 'd3';
import {event as currentEvent} from 'd3-selection';

您现在可以像使用currentEvent一样使用d3.event。有关详细信息,请参阅https://github.com/d3/d3/issues/2733

答案 1 :(得分:5)

如果要导入多个d3包。 这些包有一个可访问的d3对象,可能会相互冲突。你必须用不同的名字导入它们。

import d3 from 'd3-selection'
import d3Zoom from 'd3-zoom'
import d3Scale from 'd3-scale'

并为您的回调设置了匿名函数

.on("zoom", () => d3.select("#viewport")
    .attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
)

答案 2 :(得分:3)

您是否尝试过这样导入d3: import d3 from 'd3';

当文档中存在两个d3时,似乎会出现此问题。

答案 3 :(得分:1)

快速拍摄,试试这个。

    var zoom = d3.behavior.zoom()
        .scaleExtent([1, 10])
        .on("zoom", () => d3.select("#viewport").attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");)
        .translate([rootX, rootY]);

如果这样做,则以下内容应解决您的问题,

var zoom = d3.behavior.zoom()
            .scaleExtent([1, 10])
            .on("zoom", this.zoomed.bind(this))
            .translate([rootX, rootY]);

答案 4 :(得分:1)

我不确定完全你正在做什么,但它闻起来就像你在思考它。从理论上讲,缩放行为会改变音阶范围。

所以你需要做的就是将你的可视化基于两个尺度 - 一个用于x坐标,一个用于y坐标。然后,您可以通过缩放来更改这些比例,并自动更改可视化效果。

基本上,放大只意味着xy更宽。在zoom-level = 1,概念坐标(0.1, 0.1)映射到(10, 10)。当缩放级别更改为2时,相同的映射将变为(20, 20)。这会产生放大的印象。

以下是我的一些旧代码,它使用此原则来创建缩放:https://github.com/Swizec/candidate-bucket-chart/blob/169779e110c8825f4545c71ae5845ff7bad4f1f4/src/BubbleChart.jsx

React本身有点过时,我没有时间推断缩放到一个更清洁的示例项目,但我希望它有所帮助。

请记住forceUpdate,因为React不知道您的比例已发生变化。