微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何通过D3从ReactJS中删除先前的实例?

如何解决如何通过D3从ReactJS中删除先前的实例?

我想每次更改数据(数据是基于用户交互(例如按钮单击)生成的数据)时绘制的树状图。每次更改数据时,都会创建一个新的树形图,但它会在前一个树形图的上方绘制-这意味着我可以在屏幕上看到两个树形图。不知何故,前一个实例并未删除

我查看了thisthis,并应用了remove()函数通过d3删除了先前的实例。但是,它不起作用。我可能在生命周期中没有正确使用remove函数

d3.select("treemap").remove();用于第二种useEffect方法

export function Treemap({ width,height,data }) {
  const ref = useRef();

  useEffect(() => {
    const svg = d3
      .select(ref.current)
      .attr("id","treemap")
      .attr("width",width)
      .attr("height",height);

  },[]);

  useEffect(() => {
    //THIS IS WHERE I USE REMOVE FUNCTION;
    d3.select("treemap").remove();
    draw();
  },[data]);

  const draw = () => {
    const svg = d3.select(ref.current);

    // Give the data to this cluster layout:
    var root = d3.hierarchy(data).sum(function (d) {
      return d.value;
    });

    // initialize treemap
    d3
      .treemap()
      .size([width,height])
      .paddingTop(28)
      .paddingLeft(0)
      .paddingRight(0)
      .paddingBottom(7)
      .paddingInner(3)(root);

    const color = d3
      .scaleOrdinal()
      .domain(["Diary","Sweetner","Fruit"])
      .range(["#8FD175","#402D54","#E67E22"]);

    const opacity = d3.scaleLinear().domain([10,30]).range([0.5,1]);

    // Select the nodes
    var nodes = svg.selectAll("rect").data(root.leaves());

    // draw rectangles
    nodes
      .enter()
      .append("rect")
      .attr("x",function (d) {
        return d.x0;
      })
      .attr("y",function (d) {
        return d.y0;
      })
      .attr("width",function (d) {
        return d.x1 - d.x0;
      })
      .attr("height",function (d) {
        return d.y1 - d.y0;
      })
      .style("stroke","black")
      .style("fill",function (d) {
        return color(d.parent.data.name);
      })
      .style("opacity",function (d) {
        return opacity(d.data.value);
      });

    nodes.exit().remove();

    // select node titles
    var nodeText = svg.selectAll("text").data(root.leaves());

    // add the text
    nodeText
      .enter()
      .append("text")
      .attr("x",function (d) {
        return d.x0 + 5;
      }) // +10 to adjust position (more right)
      .attr("y",function (d) {
        return d.y0 + 20;
      }) // +20 to adjust position (lower)
      .text(function (d) {
        return d.data.name;
      })
      .attr("font-size","19px")
      .attr("fill","white");

    // select node titles
    var nodeVals = svg.selectAll("vals").data(root.leaves());

    // add the values
    nodeVals
      .enter()
      .append("text")
      .attr("x",function (d) {
        return d.y0 + 35;
      }) // +20 to adjust position (lower)
      .text(function (d) {
        return d.data.value;
      })
      .attr("font-size","11px")
      .attr("fill","white");

    // add the parent node titles
    svg
      .selectAll("titles")
      .data(
        root.descendants().filter(function (d) {
          return d.depth == 1;
        })
      )
      .enter()
      .append("text")
      .attr("x",function (d) {
        return d.y0 + 21;
      })
      .text(function (d) {
        return d.data.name;
      })
      .attr("font-size",function (d) {
        return color(d.data.name);
      });

  };

  return (
    <div className="chart">
      <svg ref={ref}></svg>
    </div>
  );
}

解决方法

通常,对于d3,您永远不会删除已经绘制的节点。 (从计算上来说)便宜得多,并且只需重新调整用途即可!

如果您确实要删除所有节点,d3.select("treemap")不会执行任何操作,因为“ treemap”不是有效的选择器。尝试使用#treemap

或者,如果要重新利用已绘制的位,请考虑以下事项:

function Treemap({
  width,height
}) {
  const ref = React.useRef();
  const [data,setData] = React.useState(`
    {
      "name": "Fruit","children": [
        { "name": "Apples","value": 1 },{ "name": "Oranges",{ "name": "Bananas","value": 1 }
      ]
    }
  `);

  React.useEffect(() => {
    const svg = d3
      .select(ref.current)
      .attr("id","treemap")
      .attr("width",width)
      .attr("height",height);

  },[]);

  React.useEffect(() => {
    draw();
  },[data]);

  const draw = () => {
    const svg = d3.select(ref.current);

    let parsedData
    try {
      parsedData = JSON.parse(data);
    } catch (e) {
      console.log(e);
      return;
    }

    // Give the data to this cluster layout:
    var root = d3.hierarchy(parsedData).sum(function(d) {
      return d.value;
    });

    // initialize treemap
    d3
      .treemap()
      .size([width,height])
      .paddingTop(28)
      .paddingLeft(0)
      .paddingRight(0)
      .paddingBottom(7)
      .paddingInner(3)(root);

    const color = d3
      .scaleOrdinal()
      .domain(["Diary","Sweetner","Fruit"])
      .range(["#8FD175","#402D54","#E67E22"]);

    const opacity = d3.scaleLinear().domain([10,30]).range([0.5,1]);

    // Select the nodes
    var nodes = svg.selectAll("rect").data(root.leaves());

    // draw rectangles
    var newNodes = nodes
      .enter()
      .append("rect")
      .style("stroke","black");

    nodes.merge(newNodes)
      .attr("x",function(d) {
        return d.x0;
      })
      .attr("y",function(d) {
        return d.y0;
      })
      .attr("width",function(d) {
        return d.x1 - d.x0;
      })
      .attr("height",function(d) {
        return d.y1 - d.y0;
      })
      .style("fill",function(d) {
        return color(d.parent.data.name);
      })
      .style("opacity",function(d) {
        return opacity(d.data.value);
      });

    nodes.exit().remove();

    // select node titles
    var nodeVals = svg.selectAll(".val").data(root.leaves());
    nodeVals.exit().remove();

    // add the values
    var newNodeVals = nodeVals
      .enter()
      .append("text")
      .classed("val",true)
      .attr("font-size","11px")
      .attr("fill","white");

    nodeVals.merge(newNodeVals)
      .attr("x",function(d) {
        return d.x0 + 5;
      }) // +10 to adjust position (more right)
      .attr("y",function(d) {
        return d.y0 + 35;
      }) // +20 to adjust position (lower)
      .text(function(d) {
        return d.data.value;
      });

    // add the parent node titles
    var titles = svg
      .selectAll(".title")
      .data(
        root.descendants().filter(function(d) {
          return d.depth == 1;
        })
      );

    titles.exit().remove();
    var newTitles = titles
      .enter()
      .append("text")
      .classed("title","19px");

    titles.merge(newTitles)
      .attr("x",function(d) {
        return d.x0 + 5;
      })
      .attr("y",function(d) {
        return d.y0 + 21;
      })
      .text(function(d) {
        return d.data.name;
      })
      .attr("fill",function(d) {
        return color(d.data.name);
      });
  };

  return ( <
    div className = "chart" >
    <
    textarea onChange = {
      (el) => setData(el.target.value)
    }
    value = {
      data
    }
    rows = "20"
    cols = "50" / >
    <
    svg ref = {
      ref
    } > < /svg> <
    /div>
  );
}

ReactDOM.render( <
  Treemap width = "600"
  height = "300" / >,document.getElementById('root')
)
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.js"></script>
<div id="root"></div>

无论如何,所有选择器都缺少.类前缀。我建议您阅读选择器以及enter(),exit(),merge()生命周期。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。