D3和React Hooks-如何在不重绘整个图表的情况下更新柱线?

时间:2020-08-11 19:33:41

标签: javascript reactjs d3.js charts react-hooks

我是D3的新手,我正在尝试创建BarChart组件。 在 exit() remove()函数下面的代码中,它们不起作用,并且每次绘制新图表而不是用新值更新条形图。

我尝试使用这条线 selectAll('svg> g')。remove(); ,但它会重绘整个图表 数据更新的时间。

我还尝试在 useEffect 之外创建SVG,但是它不起作用。

import React, { useEffect, useRef } from 'react';
import {
    select,
    selectAll,
    max,
    scaleLinear,
    scaleBand
} from 'd3';
import { BarChartContainer } from './BarChart.style';

const DEFAULT_MARGIN = { top: 25, right: 20, bottom: 20, left: 55 };
const BAR_PADDING_RATIO = 0.25;
const ALL_BARS_CLASS = 'bars';

const BarChart = ({ dataset, onBarClick, size }) => {
    const svgRef = useRef(null);

    const margin = DEFAULT_MARGIN;

    const width = size.width - margin.left - margin.right;
    const height = size.height - margin.top - margin.bottom;

    const getXScale = () =>
        scaleLinear()
            .domain([0, max(dataset, d => d.value)])
            .range([0, width]);

    const getYScale = () =>
        scaleBand()
            .domain(dataset.map(d => d.label))
            .range([0, height])
            .padding(BAR_PADDING_RATIO);

    const drawBars = (svg, xScale, yScale) => {
        // HORIZONTAL BARS
        const bars = svg.append('g').attr('class', ALL_BARS_CLASS);
        const rects = bars.selectAll('rect').data(dataset);

        rects
            .exit()
            .transition()
            .duration(700)
            .attr('width', 0)
            .attr('x', 0)
            .remove();

        // UPDATE
        rects
            .transition()
            .duration(700)
            .attr('x', 0)
            .attr('y', d => yScale(d.label))
            .attr('width', d => xScale(d.value))
            .attr('height', yScale.bandwidth())
            .attr('fill', 'blue');

        rects
            .enter()
            .append('rect')
            .attr('class','bar')
            .attr('x', 1)
            .attr('y', d => yScale(d.label))
            .attr('height', yScale.bandwidth())
            .transition()
            .duration(700)
            .attr('width', d => xScale(d.value))
            .attr('fill', 'green')
    };

    useEffect(
        () => {
            // remove all nested groups and redraw the chart when data changes
            // selectAll('svg > g').remove();

            // include the SVG and nested g element in which to plot the visualization
            const svg = select(svgRef.current)
                .attr('viewBox', `0 0 ${size.width + margin.left} ${size.height + margin.top}`)
                .append('g')
                .attr('transform', 'translate(85, 15)');

            // SCALES
            const xScale = getXScale();
            const yScale = getYScale();
            // BARS
            drawBars(svg, xScale, yScale);
        },
        [JSON.stringify(dataset)]
    );

    return (
        <BarChartContainer>
            <svg ref={svgRef} />
        </BarChartContainer>
    );
};

export default BarChart;

0 个答案:

没有答案