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

时间:2018-06-22 14:37:54

标签: reactjs d3.js zoom

我正在尝试按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函数-仍然没有任何进展。 我想念什么?感谢任何帮助。

1 个答案:

答案 0 :(得分:0)

即使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