【问题标题】:Why d3 tree svg doubles on zoom or pan?为什么 d3 tree svg 在缩放或平移时翻倍?
【发布时间】:2020-11-14 21:32:14
【问题描述】:

我正在创建一个 d3 树。我完全确定它不应该在缩放时重复,但我不知道它为什么会这样。我查看了各种缩放和平移教程,并且我正在遵循确切的步骤,教程代码完美运行,但我的树在缩放时重复。

我正在创建一个 d3 树。我完全确定它不应该在缩放时重复,但我不知道它为什么会这样。我查看了各种缩放和平移教程,我正在按照确切的步骤进行操作,教程代码完美运行,但我的树在缩放时重复

我正在创建一个 d3 树。我完全确定它不应该在缩放时重复,但我不知道它为什么会这样。我查看了各种缩放和平移教程,我正在按照确切的步骤进行操作,教程代码完美运行,但我的树在缩放时重复

我正在创建一个 d3 树。我完全确定它不应该在缩放时重复,但我不知道它为什么会这样。我查看了各种缩放和平移教程,我正在按照确切的步骤进行操作,教程代码完美运行,但我的树在缩放时重复

import React, { useRef, useEffect } from "react";
import { select, stratify, tree, linkHorizontal, zoom, event } from "d3";
import useResizeObserver from "./useResizeObserver";
import './treeChart.css';


function TreeChart({ data }) {
    const svgRef = useRef();
    const wrapperRef = useRef();
    const dimensions = useResizeObserver(wrapperRef);

    // we save data to see if it changed

    // will be called initially and on every data change
    useEffect(() => {
        const svg = select(svgRef.current);

        // use dimensions from useResizeObserver,
        // but use getBoundingClientRect on initial render
        // (dimensions are null for the first render)
        const { width, height } =
            dimensions || wrapperRef.current.getBoundingClientRect();

        // transform hierarchical data
        const root = stratify().id((arg) => arg.PID).parentId((arg) => arg.dependent)(data);
        //height of the created hiererchy
        const max_height = root.height;

        const margin = { top: 0, right: 0, bottom: 0, left: 50 };
        const innerWidth = width - margin.left - margin.right;
        const innerHeight = height - margin.top - margin.bottom;

        tree().size([innerHeight * 2, innerWidth * 2])(root);

        const g = svg
            .attr('width', width)
            .attr('height', height)
            .append("a")
            .attr('cursor', 'pointer')
            .attr('transform', `translate(${margin.left}, ${margin.top})`);

        svg.call(zoom().on('zoom', () => {
            g.attr('transform', event.transform);
        }));

        const linkGenerator = linkHorizontal()
            .x(link => link.y)
            .y(link => link.x);



        // nodes
        g
            .selectAll(".node").append()
            .data(root.descendants())
            .enter().append('circle')
            .attr("class", "node")
            .attr("cx", node => node.y)
            .attr("cy", node => node.x)
            .attr("r", (arg) => ((max_height - arg.depth + 1) / max_height) * 10)
            .attr("opacity", 1)
            .attr("fill", function (d) { if (d.data.status === "1") { return "green"; } else { return "red"; } });

        // links
        g
            .selectAll(".link")
            .data(root.links())
            .join("path")
            .attr("class", "link")
            .attr("d", linkGenerator)
            .attr("stroke-dasharray", function () {
                const length = this.getTotalLength();
                return `${length} ${length}`;
            })
            .attr("stroke", "blue")
            .attr("fill", "none")
            .attr("opacity", 1);


        // labels
        g
            .selectAll(".label")
            .data(root.descendants())
            .join(enter => enter.append("text"))
            .attr("class", "label")
            .attr("x", node => node.y)
            .attr("y", node => node.x - (1 - (node.depth / max_height)) * 8)
            .attr('fill', "#171717")
            .text(node => node.data.pname)
            .attr("font-size", (arg) => ((max_height + 10 - arg.depth) / (max_height + 10) + 'em'))
            .attr("opacity", 1);

        //time
        g
            .selectAll(".timing")
            .data(root.descendants())
            .join(enter => enter.append("text"))
            .attr("class", "label")
            .attr("x", node => node.y)
            .attr("y", node => node.x + (1 - ((node.depth - 5) / max_height)) * 14)
            .attr("text-anchor", "middle")
            .attr("font-size", (arg) => ((max_height + 10 - arg.depth) / (max_height + 10) + 'em'))
            .attr('fill', '#3D3D3D')
            .text(node => node.data.time)
            .attr("opacity", 1);

    }, [data, dimensions]);


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

export default TreeChart;

【问题讨论】:

    标签: reactjs web d3.js tree


    【解决方案1】:

    我注意到你的效果钩子有 2 个依赖项,如果这些变量发生变化会触发重新运行,这可能会导致多个绘图。如果不运行代码,我无法确定,但是当缩放事件发生时dimensions 可以改变吗?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-05-12
      • 2015-01-23
      • 1970-01-01
      • 2013-05-16
      • 2020-10-20
      • 1970-01-01
      • 2017-12-13
      • 2019-07-25
      相关资源
      最近更新 更多