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
我正在尝试按 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