【发布时间】:2021-07-12 05:45:54
【问题描述】:
我正在使用 D3.js 和 react-hooks 来创建图表,所以我尝试通过搜索创建一个 Line 图表并得到了一个。
- 但我正在使用的是示例数据,在我的例子中,我有 JSON 数据。
- 我也使用
resize-observer-polyfill这个库使图表具有响应性。 - 现在我正在努力用 JSON 数据实现它,用动态数据呈现它。
我做了什么
const svgRef = useRef();
const wrapperRef = useRef();
const dimensions = useResizeObserver(wrapperRef); // for responsive
// will be called initially and on every data change
useEffect(() => {
const svg = select(svgRef.current);
const { width, height } =
dimensions || wrapperRef.current.getBoundingClientRect();
// scales + line generator
const xScale = scaleLinear()
.domain([0, data.length - 1]) // here I need to pass the data
.range([0, width]);
const yScale = scaleLinear()
.domain([0, max(data)])
.range([height, 0]);
const lineGenerator = line()
.x((d, index) => xScale(index))
.y((d) => yScale(d))
.curve(curveCardinal);
// render the line
svg
.selectAll('.myLine')
.data([data])
.join('path')
.attr('class', 'myLine')
.attr('stroke', 'black')
.attr('fill', 'none')
.attr('d', lineGenerator);
svg
.selectAll('.myDot')
.data(data)
.join('circle')
.attr('class', 'myDot')
.attr('stroke', 'black')
.attr('r', (value, index) => 4)
.attr('fill', (value, index) => 'red')
.attr('cx', (value, index) => xScale(index))
.attr('cy', yScale);
// axes
const xAxis = axisBottom(xScale);
svg
.select('.x-axis')
.attr('transform', `translate(0, ${height})`)
.call(xAxis);
const yAxis = axisLeft(yScale);
svg.select('.y-axis').call(yAxis);
}, [data, dimensions]);
<React.Fragment>
<div ref={wrapperRef} style={{ marginBottom: '2rem' }}>
<svg ref={svgRef}>
<g className="x-axis" />
<g className="y-axis" />
</svg>
</div>
</React.Fragment>
这里我无法传递数据,我的数据在下面
[
{ anno: 2014, consumo: 300, color: "#ff99e6" },
{ anno: 2015, consumo: 290, color: "blue" },
{ anno: 2016, consumo: 295, color: "green" },
{ anno: 2017, consumo: 287, color: "yellow" },
{ anno: 2018, consumo: 282, color: "red" },
{ anno: 2019, consumo: 195, color: "white" }
]
在我的数据中,每个数据都有颜色,我想在生成的每个点中显示。
working code sandbox of line chart
同样,我尝试制作条形图,效果很好
我对标签做了一些动态渲染,当我们调整窗口大小时,标签会自动调整。
Here is the full working bar chart what I am trying to implement to line chart
我还评论了我正在做什么。
编辑/更新
我一直在关注@MGO 的回答,它对我有很大帮助,但我仍然面临对齐标签和将颜色填充为点的问题。
实际上很明显它会因为文本大小而重叠,但只是为了克服在条形图中我使用下面的代码
const tickWidth = 40;
const width = xScaleLabels.range()[1];
const tickN = Math.floor(width / tickWidth);
const keepEveryNth = Math.ceil(xScaleLabels.domain().length / tickN);
const xScaleLabelDomain = xScaleLabels
.domain()
.filter((_, i) => i % keepEveryNth === 0);
xScaleLabels.domain(xScaleLabelDomain);
它所做的是当设备尺寸较小时,它会过滤一些标签并且不会显示标签。
我也在使用下面的代码来给颜色
.attr("fill", ({ color }) => color)
但是它没有采用任何颜色,而是默认采用黑色。
我有数据要显示为July.9.2021 11:18:28 的标签,但我只想显示时间,所以我在条形图代码中所做的如下
const xScaleLabels = scaleBand()
.domain(
data.map(
({ sensorValueAddedTime }) => sensorValueAddedTime.split(' ')[2] // this I am using to show only time
)
)
.range([0, dimensions.width])
.padding(padding);
我想用折线图做同样的事情,以一种简单的方式,我不想将其更改为任何时间。
这是第二个数据,所以基本上我得到的答案只适用于第一个数据而不是第二个数据,如果数据以我想要显示的任何这些格式出现,我希望它是动态的。
sensorValueAddedTime 我想在 x 轴上显示
sensorValue在y轴上
我已经添加了我的条形图完整的工作代码,我想对折线图做同样的事情。
[
{
sensorValue: 32,
sensorValueAddedTime: "July.9.2021 10:56:22",
color_code: null,
condition: null,
__typename: "sensorData"
},
{
sensorValue: 32,
sensorValueAddedTime: "July.9.2021 10:56:23",
color_code: null,
condition: null,
__typename: "sensorData"
},
{
sensorValue: 35,
sensorValueAddedTime: "July.9.2021 11:17:51",
color_code: null,
condition: null,
__typename: "sensorData"
},
{
sensorValue: 35,
sensorValueAddedTime: "July.9.2021 11:17:52",
color_code: null,
condition: null,
__typename: "sensorData"
},
{
sensorValue: 36,
sensorValueAddedTime: "July.9.2021 11:18:08",
color_code: null,
condition: null,
__typename: "sensorData"
},
{
sensorValue: 36,
sensorValueAddedTime: "July.9.2021 11:18:09",
color_code: null,
condition: null,
__typename: "sensorData"
},
{
sensorValue: 38,
sensorValueAddedTime: "July.9.2021 11:18:27",
condition: null,
color_code: null,
__typename: "sensorData"
},
{
sensorValue: 38,
sensorValueAddedTime: "July.9.2021 11:18:28",
condition: null,
color_code: null,
__typename: "sensorData"
}
]
【问题讨论】:
-
澄清一下,您是要使用具有 {anno: 2014, consumo: 300, color: "#ff99e6" } 的数组还是使用 Codesandbox 中的数组生成折线图?我已经使用 Codesandbox 中提供的数据进行了回答。你问的是这个吗?
标签: javascript reactjs d3.js react-hooks