【发布时间】: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;
【问题讨论】: