D3.js V4 缩放在 React + faux 中不起作用

D3.js V4 zoom doesn't work in React + faux

我正在尝试按 x 轴缩放我的时间轴, 但它对缩放没有任何反应,我浏览了很多教程,尝试了单独的缩放功能,最终在这里得到了我所得到的(使用这个 https://coderwall.com/p/psogia/simplest-way-to-add-zoom-pan-on-d3-js 手册):

const { dataset } = this.props;
  var minDt = 0;
      var maxDt = 300;
      var intervalMinWidth = 1;
      var elementWidth = 1200; // TODO: make adoptable
      var elementHeight = 200;

      var width = 500;
      var height = 600;

      var groupHeight = 20;
      var xTickSize = 5;

      var x = d3.scaleLinear()
        .domain([minDt, maxDt])
        .range([0, width]);

      var xAxis = d3.axisBottom(x)
        .tickSize(xTickSize);

      var svg = d3.select(svgRoot)
        .append('svg')
        .attr('id', 'chart')
        .attr('class', 'timeline-chart')
        .attr("width", "100%")
        .attr("height", "100%")
        .call(d3.zoom().on("zoom", function () {
          svg.attr("transform", d3.event.transform)
        }))
      .append('g');

      var gX = svg.append("g")
          .attr("class", "axis axis--x")
          .call(xAxis);

      var groupExonItems = svg
        .selectAll('.group-interval-item')
        .data(dataset)
        .enter()
        .append('g')
        .attr('clip-path', 'url(#chart-content)')
        .attr('class', 'item')
        .attr('transform', function (d, i) {
          return 'translate(0, ' + groupHeight * i + ')';
          })
        .selectAll('.rect').data(function (d) {
            return d.data.filter(function (_) {
              return _.type === 'exon';
            });
        }).enter();

      var exonBarHeight = 0.8 * groupHeight;
      var exonBarMargin = 30;

      var exons = groupExonItems
        .append('rect')
        .attr('class', 'interval')
        .attr('width', function (d) {
            return Math.max(intervalMinWidth, x(d.to) - x(d.from));
          })
        .attr('height', exonBarHeight)
        .attr('y', exonBarMargin)
        .attr('x', function (d) {
            return x(d.from);
      });

我试过单独的功能,也没有任何进展:

  function zoomFunction(){
        var new_xScale = d3.event.transform.rescaleX(x)
        gX.call(xAxis.scale(new_xScale));
        svg.selectAll('rect.interval').attr('x', function (d) {
                return x(d.from);
        }).attr('width', function (d) {
                return Math.max(intervalMinWidth, x(d.to) - x(d.from));
        });
      };

如果我记录缩放功能 - 我可以看到它可以访问,并且缩放比例发生变化,但不是我的矩形。 可能是因为我正在使用 react + faux 来绘制 svg,我尝试过不使用 faux - 通过将 D3 代码放入 componentDidMount 函数 - 仍然没有任何进展。 我错过了什么?感谢任何帮助。

即使是 react-faux-dom 也是最简单的 D3 渲染方式,它破坏了对象的动态变化,例如缩放。这里没有虚假是一个非常简单的例子来实现缩放:https://swizec.com/blog/two-ways-build-zoomable-dataviz-component-d3-zoom-react/swizec/7753

我只需要x轴缩放,解决方法如下:

import { Component} from 'react'
import { PropTypes} from 'prop-types'
import React from 'react'
import ReactDOM from 'react-dom';
import ReactFauxDOM from 'react-faux-dom'
import * as d3 from 'd3'

import styles from './chart.css';


const random = d3.randomNormal(2, 1);

class Scatterplot extends React.Component {
  constructor(props) {
    super(props);
    this.updateD3(props);
  }
  componentWillUpdate(nextProps) {
    this.updateD3(nextProps);
  }
  updateD3(props) {
    const { data, width, height, zoomTransform } = props;
    this.xScale = d3.scaleLinear()
                    .domain([0, d3.max(data, ([x, y]) => x)])
                    .range([0, width]);
  }

  get transform() {
    const { x, y, zoomTransform } = this.props;
    let transform = "";
    if (zoomTransform) {
      transform = `translate(${x + zoomTransform.x}, ${y}) scale(${zoomTransform.k} 1)`;
    }
    return transform;
  }

  render() {
    const { data } = this.props;
    return (
      <g transform={this.transform} ref="scatterplot">
        {data.map(([x, y]) => <rect x={this.xScale(x)} y={y} width={this.xScale(4)} height = {5} />)}
      </g>
    )
  }
}

class Chart extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      data: d3.range(5).map(_ => [random(), random()]),
      zoomTransform: null
    }
    this.zoom = d3.zoom()
                  .scaleExtent([-5, 5])
                  .translateExtent([[-100, -100], [props.width+100, props.height]])
                  .extent([[-100, -100], [props.width+100, props.height]])
                  .on("zoom", this.zoomed.bind(this))
  }
  componentDidMount() {
    d3.select(this.refs.svg)
      .call(this.zoom)
  }
  componentDidUpdate() {
    d3.select(this.refs.svg)
      .call(this.zoom)
  }
  zoomed() {
    this.setState({
      zoomTransform: d3.event.transform
    });
  }
  render() {
    const { zoomTransform } = this.state,
          { width, height } = this.props;

    return (
      <svg width={width} height={height} ref="svg">
        <Scatterplot data={this.state.data}
                     x={0} y={0}
                     width={width/2}
                     height={height}
                     zoomTransform={zoomTransform}/>
        </svg>
    )
  }
}
export default Chart