在 React 应用程序中使 D3 图表具有响应性
Posted
技术标签:
【中文标题】在 React 应用程序中使 D3 图表具有响应性【英文标题】:Making D3 chart Responsive in React app 【发布时间】:2016-07-25 12:22:45 【问题描述】:我目前正在尝试使用 D3 在 React 中渲染绘图。为了整合它们,我使用了以下链接:
http://oli.me.uk/2015/09/09/d3-within-react-the-right-way/。
我还尝试了链接中提供的使图表响应的解决方案:
Resize svg when window is resized in d3.js
虽然它在与 React 集成后在独立代码中运行良好,但它开始省略 ticks 。单独为 D3 工作 jsfiddle:https://jsfiddle.net/adityap16/11edxrnq/1/
独立 D3 代码:
var data = [
"mytime": "2015-12-01T11:10:00.000Z", "value": 64,
"mytime": "2015-12-01T11:15:00.000Z", "value": 67,
"mytime": "2015-12-01T11:20:00.000Z", "value": 70,
"mytime": "2015-12-01T11:25:00.000Z", "value": 64,
"mytime": "2015-12-01T11:30:00.000Z", "value": 72,
"mytime": "2015-12-01T11:35:00.000Z", "value": 75,
"mytime": "2015-12-01T11:40:00.000Z", "value": 71,
"mytime": "2015-12-01T11:45:00.000Z", "value": 80
];
var parseDate = d3.time.format("%Y-%m-%dT%H:%M:%S.%LZ").parse;
data.forEach(function(d)
d.mytime = parseDate(d.mytime);
);
//var margin = top: 30, right: 30, bottom: 40, left:50 ,
var margin = top: 30, right: 30, bottom: 40, left:50 ,
height = 200,
width = 800;
var color = "green";
var xaxis_param = "mytime";
var yaxis_param = "value"
var params1 = margin:margin,height:height,width:width, color: color, xaxis_param:xaxis_param, yaxis_param :yaxis_param;
draw_graph(data,params1);
function draw_graph(data,params)
//Get the margin
var xaxis_param = params.xaxis_param;
var yaxis_param = params.yaxis_param;
var color_code = params.color;
var margin = params.margin;
var height = params.height - margin.top - margin.bottom,
width = params.width - margin.left - margin.right;
var x_extent = d3.extent(data, function(d)
return d[xaxis_param]);
var y_extent = d3.extent(data, function(d)
return d[yaxis_param]);
var x_scale = d3.time.scale()
.domain(x_extent)
.range([0,width]);
var y_scale = d3.scale.linear()
.domain([0,y_extent[1]])
.range([height,0]);
//Line
var lineGen = d3.svg.line()
.x(function (d)
return x_scale(d[xaxis_param]);
)
.y(function (d)
return y_scale(d[yaxis_param]);
);
var myChart = d3.select('body')
.append("div")
.classed("svg-container", true)
.append('svg')
.attr("preserveAspectRatio", "xMinYMin meet")
.attr("viewBox", "0 0 800 600")
//class to make it responsive
.classed("svg-content-responsive", true)
.attr('class','my-chart')
.style('background', '#E7E0CB')
.append('g')
.attr('transform', 'translate('+ margin.left +', '+ margin.top +')');
myChart
.append('svg:path')
.datum(data)
.attr('class', 'line')
.attr("d",lineGen)
.attr('stroke', color_code)
.attr('stroke-width', 1)
.attr('fill', 'none');
var legend = myChart.append("g")
.attr("class", "legend")
.attr("transform", "translate(" + 5 + "," + (height - 25) + ")")
legend.append("rect")
.style("fill", color_code)
.attr("width", 20)
.attr("height", 20);
legend.append("text")
.text(yaxis_param)
.attr("x", 25)
.attr("y", 12);
var vGuideScale = d3.scale.linear()
.domain([0,y_extent[1]])
.range([height, 0])
var vAxis = d3.svg.axis()
.scale(vGuideScale)
.orient('left')
.ticks(5)
var hAxis = d3.svg.axis()
.scale(x_scale)
.orient('bottom')
.ticks(d3.time.minute, 5);
myChart.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(hAxis);
myChart.append("g")
.attr("class", "y axis")
.call(vAxis)
我可能需要在调整大小时设置 setState 或其他东西,这应该会触发 React 使用新信息重新渲染,但是对于 React 来说是新手,我无法使其工作。
编辑:我仍在尝试编辑,但问题似乎是 x 轴和 y 轴上的刻度,当您缩小窗口时,您可以看到刻度但不是全屏。仍在试图理解为什么?
谢谢!
【问题讨论】:
除了 React 之外应该有错误导致 svg 没有响应。毕竟,viewbox
和 width: 100%; height: 100%
是使 svg 响应的全部内容。尝试查看您的 DOM 结构,以确保 svg 的父级响应开始。
不会导致错误,xaxis 和 yaxis 上的刻度都被省略了。我尝试调整视图框中的宽度和高度以及 .css 文件中的底部填充,但无济于事。
你能在 jsfiddle 上重新创建问题吗?通过查看损坏的副本而不是工作副本更容易发现问题。
反应组件在另一个反应组件中。作为 React 的新手,不确定我是否可以让它在 jsfiddle 中工作。我的道歉
确保 svg 元素本身也有 width="100%"
和 height="100%"
。另外,检查是否没有可能具有静态大小的中间 DOM 元素。
【参考方案1】:
所以我能够在 React on Github(react-d3 组件)中的一个未解决问题中找到答案。附上链接和代码sn-p:
https://github.com/codesuki/react-d3-components/issues/9
代码:
let AreaGraph = React.createClass(
mixins: [React.addons.PureRenderMixin],
getInitialState()
return
parentWidth: 0
,
getDefaultProps()
return
width: '100%',
height: 300,
margin: left: -1, top: 10, bottom: 0, right: 1
,
handleResize(e)
let elem = this.getDOMNode();
let width = elem.offsetWidth;
this.setState(
parentWidth: width
);
,
componentDidMount()
if(this.props.width === '100%')
window.addEventListener('resize', this.handleResize);
this.handleResize();
,
componentWillUnmount()
if(this.props.width === '100%')
window.removeEventListener('resize', this.handleResize);
,
render()
let width, height, margin, xScale, yScale, xAxis, ...props = this.props;
// Determine the right graph width to use if it's set to be responsive
if(width === '100%')
width = this.state.parentWidth || 400;
// Set scale ranges
xScale && xScale.range([0, width - (margin.left + margin.right)]);
yScale && yScale.range([height - (margin.top + margin.bottom), 0]);
return (
<div className="usage__cpu__graph "+props.className>
<AreaChart
ref="chart"
width=width
height=height
margin=margin
xScale=xScale
yScale=yScale
xAxis=xAxis
...props
/>
</div>
);
)
【讨论】:
以上是关于在 React 应用程序中使 D3 图表具有响应性的主要内容,如果未能解决你的问题,请参考以下文章