如何使用 React Faux DOM 在 D3 分组条形图中呈现矩形?
Posted
技术标签:
【中文标题】如何使用 React Faux DOM 在 D3 分组条形图中呈现矩形?【英文标题】:How to render rectangles in a D3 grouped bar chart using React Faux DOM? 【发布时间】:2016-12-03 15:17:20 【问题描述】:我非常接近使用 react-faux-dom
包在 React 中完成一个组条形图。除了实际的矩形之外,一切都设置好了。已经旋转了几个小时,所以我希望有人能看到我缺少的东西。我在is here 工作的示例。我的目标是有一个带有多条组的时间刻度 x 轴。 X 轴和 Y 轴当前渲染没有问题。
数据结构目前如下所示:
[
key: "oauths", values: [
date: Tue Jul 26 2016 00:00:00 GMT-1000 (HST), key: "oauths", value: 3060,
date: Tue Jul 27 2016 00:00:00 GMT-1000 (HST), key: "oauths", value: 2060,
date: Tue Jul 28 2016 00:00:00 GMT-1000 (HST), key: "oauths", value: 3270,
...],
key: "user_stats", values: [
date: Tue Jul 26 2016 00:00:00 GMT-1000 (HST), key: "user_stats", value: 2976,
...
]
]
React 组件的渲染方法如下。它在最终的svg.append()...
上出错
render()
const data = [ , ]; // see above
// Constants
const margin = top: 30, right: 20, bottom: 30, left: 50,
width = 600 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom,
n = this.props.dataQueryPeriod.length, // number of samples
m = 2; // number of series
// Parse the date / time
const parseDate = d3.time.format("%Y-%m-%d").parse;
// Set ranges
const yScale = d3.scale.linear()
.range([height, 0]);
const x0 = d3.scale.ordinal()
.domain(d3.range(n))
.rangeBands([0, width], .2);
const x1 = d3.scale.ordinal()
.domain(d3.range(m))
.rangeBands([0, x0.rangeBand()]);
const xScale = d3.time.scale().range([0, width]);
// Test colors
var z = d3.scale.category10();
// Define axes
const xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.ticks(d3.time.days);
const yAxis = d3.svg.axis()
.scale(yScale)
.orient("left")
.tickFormat(d3.format("s"));
// Convert structured data to nested data
const nest = d3.nest()
.key(function(d) return d.key; )
.sortKeys(d3.ascending);
// Create node
let node = ReactFauxDOM.createElement('svg');
let svg = d3.select(node)
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom+40)
.append("g")
.attr("transform", `translate($margin.left,$margin.top)`);
data.forEach(function(d)
d.date = parseDate(d.date);
d.value = +d.value;
);
const nestedData = nest.entries(data);
console.log("nested data", nestedData);
console.log("pre nest data", data);
// Define axes domains
xScale.domain(d3.extent(data, function(d) return d.date; ));
yScale.domain([0, d3.max(data, function(d) return d.value; )]);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
svg.append("g")
.attr("class", "x axis")
.attr("transform", `translate(0,$height)`)
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", function(d)
return "rotate(-65)";
);
svg.append("g").selectAll("g")
.data(nestedData)
.enter().append("g")
.style("fill", function(d, i) return z(i); )
.attr("transform", function(d, i) return `translate($x1(i),0)`; )
.selectAll("rect")
.data(function(d) return d.value; )
.enter().append("rect")
.attr("width", x1.rangeBand())
.attr("height", yScale)
.attr("x", function(d, i) return x0(i); )
.attr("y", function(d) return height - yScale(d.value); );
return node.toReact();
【问题讨论】:
如果追加不是已经选择了吗?svg.append("g").selectAll("g")
对我来说似乎无关紧要。你得到的确切错误是什么?编辑:哦,我明白了,原来的例子就是这样。不过,这个错误会非常有用。
更好的是,如果你可以在 JSFiddle 中运行它,我可以仔细看看 :) 如果我们都确信这是一个错误,请随时提出问题,也许将其添加为测试用例。
@Kwhitejr 我也碰巧认为工作是一种分心。不知道为什么,但 Bossman 先生强烈反对。
你能解释一下究竟是什么不起作用吗? minimal runnable example 会很棒。
【参考方案1】:
如果您的数据与您提供的示例一样开始,则它已经嵌套和 d3.nest()。假设您示例中的数据是nestedData
,那么您的问题是您需要绑定values
而不是value
。见下文:
svg.append("g").selectAll("g")
.data(nestedData)
.enter()
.append("g")
.style("fill", function(d, i) return z(i); )
.attr("transform", function(d, i) return `translate($x1(i),0)`; )
.selectAll("rect")
.data(function(d) return d.values; ) // This needs to be values
.enter().append("rect")
.attr("width", x1.rangeBand())
.attr("height", yScale)
.attr("x", function(d, i) return x0(i); )
.attr("y", function(d) return height - yScale(d.value); );
【讨论】:
以上是关于如何使用 React Faux DOM 在 D3 分组条形图中呈现矩形?的主要内容,如果未能解决你的问题,请参考以下文章
d3.js Faux-3D Arcs - Uncaught typeerror:无法读取未定义的属性“对象”