我正在尝试让使用 d3 sunburst 图表的反应组件工作。我面临的问题是我需要一种方法来更新 sunburst 组件的缩放级别,作为来自外部组件的触发器。我通过道具将要缩放的节点发送到 sunburst 组件,并且每次有不同组件的外部输入时都会改变。
这是我到目前为止的伪代码,但是每个道具都会发生变化。
function usePrevious(value) {
const ref = useRef();
useEffect(() => {
ref.current = value;
});
return ref.current;
}
const SunburstSmooth = (props) => {
const prevProps = usePrevious(props);
useEffect(() => {
if (!isEqual(prevProps, props)) {
if (props.navigateTo) {
zoomToSunburst(props.navigateTo);
} else {
if (props.data) {
renderSunburstSmooth();
update();
}
}
}
}, [props])
// Global Variables
let root, node;
let gWidth, gHeight, radius, svg;
let color;
let x, y, arc, partition;
const svgRef = useRef();
const zoomToSunburst = (nodeToRender) => {
const gWidth = props.width;
const gHeight = props.height;
const radius = (Math.min(gWidth, gHeight) / 2) - 10
const svg = d3.select(svgRef.current)
const x = d3.scaleLinear().range([0, 2 * Math.PI])
const y = d3.scaleSqrt().range([0, radius])
const partition = d3.partition()
const arc = d3.arc()
// ....
root = d3.hierarchy(nodeToRender);
node = nodeToRender;
svg.selectAll("path")
.transition("update")
.duration(1000)
.attrTween("d", (d, i) =>
arcTweenPath(d, i, radius, x, y, arc));
}
const update = () => {
root.sum(d => d[props.value]);
let gSlices = svg.selectAll("g")
.data(partition(root).descendants())
.enter()
.append("g");
gSlices.exit().remove();
gSlices.append("path")
.style('fill', (d) => {
let hue;
const current = d;
if (current.depth === 0) {
return '#c6bebe';
}
return color((current.children ? current.x0 : current.parent.x0));
})
.attr('stroke', '#fff')
.attr('stroke-width', '1')
svg.selectAll("path")
.transition("update")
.duration(750)
.attrTween("d", (d, i) =>
arcTweenPath(d, i, radius, x, y, arc));
}
// Sets up the initial sunburst
const renderSunburstSmooth = () => {
// Structure
gWidth = props.width;
gHeight = props.height;
radius = (Math.min(gWidth, gHeight) / 2) - 10;
// Size our <svg> element, add a <g> element, and move translate 0,0 to the center of the element.
svg = d3.select(svgRef.current)
.append("g")
.attr("id", "bigG")
.attr("transform", `translate(${gWidth / 2},${gHeight / 2})`);
x = d3.scaleLinear().range([0, 2 * Math.PI]);
y = d3.scaleSqrt().range([0, radius]);
// Calculate the d path for each slice.
arc = d3.arc()
// .....
// Create our sunburst data structure
partition = d3.partition();
// Root Data
root = d3.hierarchy(props.data);
node = props.navigateTo || root;
}
return (
<div id={props.keyId}>
<svg ref={svgRef}/>
</div>
);
}
很多代码库代码来自这里: http ://bl.ocks.org/metmajer/5480307
现在每次更新 prop 时,都会重新渲染整个组件。当 props.navigateTo 在外部更改时,我如何使其仅更新现有的 svg 容器。