繁体   English   中英

更新 d3 数据反应钩子

[英]Update d3 data react hooks

得到了这段代码:

export default function Chart({ data, changeData}) {
  console.log(data);
  const ref = useRef();

  const createGraph = (data) => {
    var margin = { top: 20, right: 20, bottom: 30, left: 40 },
      width = 1360 - margin.left - margin.right,
      height = 500 - margin.top - margin.bottom;

    var x = d3.scaleBand().range([0, width]).padding(0.1);
    var y = d3.scaleLinear().range([height, 0]);

    var svg = d3
      .select(ref.current)
      .append("svg")
      .attr("id", "chart")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    x.domain(
      data.map(function (d) {
        return d.name;
      })
    );
    y.domain([
      0,
      d3.max(data, function (d) {
        return d.number;
      }),
    ]);

    // append the rectangles for the bar chart

    const bars = svg.selectAll().data(data).enter().append("rect");

    bars
      .attr("class", "bar")
      .attr("x", function (d) {
        return x(d.name);
      })
      .attr("width", x.bandwidth())
      .attr("y", function (d) {
        return y(d.number);
      })
      .attr("fill", "pink")
      .attr("height", function (d) {
        return height - y(d.number);
      })
      .on("mouseenter", function (actual, i) {
        d3.select(this).attr("opacity", 0.5);
        d3.select(this)
          .transition()
          .duration(300)
          .attr("opacity", 0.6)
          .attr("x", (a) => x(a.name) - 5)
          .attr("width", x.bandwidth() + 10);
      })
      .on("mouseleave", function (actual, i) {
        d3.select(this).attr("opacity", 1);
        d3.select(this)
          .transition()
          .duration(300)
          .attr("opacity", 1)
          .attr("x", (a) => x(a.name))
          .attr("width", x.bandwidth());
      });

    bars
      .append("text")
      .attr("class", "value")
      .attr("x", (a) => x(a.name) + x.bandwidth() / 2)
      .attr("y", (a) => y(a.number) + 30)
      .attr("fill", "blue")
      .attr("text-anchor", "middle")
      .text((a) => `${a.number}%`);

    d3.selectAll("bars").append("text").attr("class", "divergence");
    // add the x Axis
    svg
      .append("g")
      .attr("transform", "translate(0," + height + ")")
      .call(d3.axisBottom(x));

    // add the y Axis
    svg.append("g").call(d3.axisLeft(y));
  };

  useEffect(() => {
    createGraph(data);
  }, [data]);

  return (
    <React.Fragment>
      <Filter>
        <h2>By</h2>
        <span>Popularity</span>
        <span onClick={() => changeData()}>Following</span>
      </Filter>
      <div style={{ marginLeft: "100px" }} ref={ref}></div>
    </React.Fragment>
  );
}

如何在每次渲染时更新数据?

我尝试创建一个 function 删除 SVG 并添加一个新但位置在第一次渲染后搞砸了,我也尝试在 useEffect 中使用 exit() 和 remove() 但没有结果。

我试图实现的结果是我有一个图表,数据被提取并传递到这个组件中,每当我按下按钮时,数据都会改变。 我现在不看任何动画,我只想看看如何更改数据。

这有点晚了,但万一有人在搜索时遇到这个问题。

useEffect(() => {
  *// your d3 code here*
  instead of using .enter().append('rect')
  use .join('rect')
}, [data]) *// runs the d3 code every time the data changes*

更多 about.join() https://observablehq.com/@d3/selection-join

在返回语句中指定 svg 和 g 标签。
代替 div 上的 ref,在 svg 标签上做 useRef
而不是.append(g),do.select('.x-axis') 等
这样你就不会在每次运行 useEffect 时 append new g

  <svg ref={d3Container}>
    <g className="chart">
      <g className="x-axis" />
      <g className="y-axis" />
    </g>
  </svg>

我在看了这个系列的第 1 和第 3 个视频https://muratorium.com/using-react-hooks-with-d3后了解了以上内容

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM