我无法从情节中删除路径



我正在做一个复合图。在要实现的功能中,有可能使情节动态地出现和消失。

对于圆和线,我对下面的代码没有问题:

svg.selectAll('circle').remove();
svg.selectAll('line').remove();

但我无法从显示的项目中删除路径。

我已经进行了几次useEffect钩子的lambda中存在的尝试,但都不起作用。

const useState = React.useState;
const useRef = React.useRef;
const useEffect = React.useEffect;
const Fragment = React.Fragment;
const select = d3.select;
const scaleLinear = d3.scaleLinear;
const axisBottom = d3.axisBottom;
const axisLeft = d3.axisLeft;
const line = d3.line;
const curveCardinal = d3.curveCardinal;
const PathPlot = () => {
const [xAxisData] = useState({
min: 100,
max: 700
});
const [yAxisData] = useState({
min: 200,
max: 500
});
const [meta] = useState({
xWidth: 600,
yWidth: 300,
});
const [visible, setVisible] = useState(true);
const handleRemove = () => {
setVisible(false);
}
const [plot] = useState({
color: 'red',
width: '5px',
line: [{
x: '120',
y: '210'
}, {
x: '220',
y: '230'
}, {
x: '320',
y: '250'
}, {
x: '380',
y: '270'
}, {
x: '450',
y: '290'
}]
});
const svgRef = useRef();
useEffect(() => {
if (svgRef.current) {
const svg = select(svgRef.current);
// X-AXIS
const xScale = scaleLinear()
.domain([xAxisData.min, xAxisData.max])
.range([0, meta.xWidth]);
const xAxis = axisBottom(xScale);
svg
.select(".x-axis")
.style("transform", `translateY(${meta.yWidth}px)`)
.call(xAxis);
// Y-AXIS
const yScale = scaleLinear()
.domain([yAxisData.min, yAxisData.max])
.range([meta.yWidth, 0]);
const yAxis = axisLeft(yScale);
svg
.select(".y-axis")
.call(yAxis);
// line plot
if (visible) {
const myLine = line()
.x(value => xScale(value.x))
.y(value => yScale(value.y))
.curve(curveCardinal);
svg
.select(".line-plot")
.data([plot.line])
.join("path")
.attr("d", value => myLine(value))
.attr("fill", "transparent")
.attr("stroke", () => plot.color)
.attr("stroke-width", () => plot.width);
}

}
return () => {
if (svgRef.current !== undefined) {
const svg = select(svgRef.current);
svg
.selectAll('.line-plot')
.attr('d', '')
.attr("fill", 'trasparent')
.attr("stroke", 'transparent')
.attr("stroke-width", '0px')
.attr("opacity", '0');
}
}
}, [xAxisData, yAxisData, meta, line]);
return ( <
Fragment >
<
svg viewBox = {
`0 0 ${meta.xWidth} ${meta.yWidth}`
}
ref = {
svgRef
} >
<
g className = "x-axis" / >
<
g className = "y-axis" / >
<
path className = "line-plot" / >
<
/svg> <
div onClick = {
handleRemove
} > REMOVE < /div> <
/Fragment>
);
}
ReactDOM.render( < PathPlot / > , document.querySelector("body"));
svg {
width: 80%;
height: auto;
background: #eee;
overflow: visible;
margin: 5%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script>

下面就是一个例子。我将visible添加到useEffect的依赖项列表中,并且总是画线。如果visible为false,我只给它不透明度0,否则为1。

const useState = React.useState;
const useRef = React.useRef;
const useEffect = React.useEffect;
const Fragment = React.Fragment;
const select = d3.select;
const scaleLinear = d3.scaleLinear;
const axisBottom = d3.axisBottom;
const axisLeft = d3.axisLeft;
const line = d3.line;
const curveCardinal = d3.curveCardinal;
const PathPlot = () => {
const [xAxisData] = useState({
min: 100,
max: 700
});
const [yAxisData] = useState({
min: 200,
max: 500
});
const [meta] = useState({
xWidth: 600,
yWidth: 300,
});
const [visible, setVisible] = useState(true);
const handleRemove = () => {
setVisible(false);
}
const [plot] = useState({
color: 'red',
width: '5px',
line: [{
x: '120',
y: '210'
}, {
x: '220',
y: '230'
}, {
x: '320',
y: '250'
}, {
x: '380',
y: '270'
}, {
x: '450',
y: '290'
}]
});
const svgRef = useRef();
useEffect(() => {
console.log("hi");
if (svgRef.current) {
const svg = select(svgRef.current);
// X-AXIS
const xScale = scaleLinear()
.domain([xAxisData.min, xAxisData.max])
.range([0, meta.xWidth]);
const xAxis = axisBottom(xScale);
svg
.select(".x-axis")
.style("transform", `translateY(${meta.yWidth}px)`)
.call(xAxis);
// Y-AXIS
const yScale = scaleLinear()
.domain([yAxisData.min, yAxisData.max])
.range([meta.yWidth, 0]);
const yAxis = axisLeft(yScale);
svg
.select(".y-axis")
.call(yAxis);
// line plot
if (visible) {
const myLine = line()
.x(value => xScale(value.x))
.y(value => yScale(value.y))
.curve(curveCardinal);
svg
.select(".line-plot")
.data([plot.line])
.join("path")
.attr("d", value => myLine(value))
.attr("fill", "transparent")
.attr("stroke", () => plot.color)
.attr("stroke-width", () => plot.width);
}

}
return () => {
if (svgRef.current !== undefined) {
const svg = select(svgRef.current);
svg
.selectAll('.line-plot')
.attr('d', '')
.attr("fill", 'trasparent')
.attr("stroke", 'transparent')
.attr("stroke-width", '0px')
.attr("opacity", '0');
}
}
}, [xAxisData, yAxisData, meta, line, visible]);
return ( <
Fragment >
<
svg viewBox = {
`0 0 ${meta.xWidth} ${meta.yWidth}`
}
ref = {
svgRef
} >
<
g className = "x-axis" / >
<
g className = "y-axis" / >
<
path className = "line-plot" / >
<
/svg> <
div onClick = {
handleRemove
} > REMOVE < /div> <
/Fragment>
);
}
ReactDOM.render( < PathPlot / > , document.querySelector("body"));
svg {
width: 80%;
height: auto;
background: #eee;
overflow: visible;
margin: 5%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script>

最新更新