我想在窗口调整大小时刷新仪表,因为出于某种原因,手动调整大小时,在 d3 中创建的仪表在小屏幕上被裁剪,但如果您在同一个较小的屏幕上刷新,它的位置很好。这使我得出结论,我需要在调整屏幕大小时重绘 d3 组件。
这是我的代码:
import * as d3 from "d3";
import React, { useRef, useEffect, useContext } from "react";
import styled, {ThemeContext} from "styled-components"
const Container = styled.div`
display: flex;
align-items: center;
justify-content: center;
border: 1px solid ${({theme}) => theme.colors.primaryBlack};
border-radius: 10px;
box-shadow: 0.5px 0.5px 3.5px ${props => props.theme.colors.primaryBlack};
`
const SVGContainer = styled.svg`
display: block;
width: 23em;
height: 20em;
`
const Gauge = ({percent}) => {
const theme = useContext(ThemeContext)
const d3Ref = useRef(null)
const createArc = d3.arc()
.innerRadius(110)
.outerRadius(140)
.startAngle((-2/3)*Math.PI)
const arcTween = newAngle => {
return d => {
const interpolate = d3.interpolate(d.endAngle, newAngle)
return t => {
d.endAngle = interpolate(t)
return createArc(d)
}
}
}
const draw = () => {
const d3Container = d3.select(d3Ref.current)
// Refresh the container, remove old drawings
const container = d3Container.append("g").style("transform", "translate(50%, 60%)")
// Create the 100% custom arc for background
container.append("path")
.datum({endAngle: (2/3)*Math.PI})
.style("fill", "#F2F2F2")
.attr("d", createArc)
// Create the progress custom arc for background
const progress = container.append("path")
.datum({endAngle: (-2/3)*Math.PI})
.style("fill", "#4ABDAC")
.attr("d", createArc)
container.append("text")
.style("font-size", "6.2rem")
.style("font-weight", "900")
.style("font-family", "Lato")
.style("transform", "translate(0%, 7%)")
.attr("text-anchor", "middle")
.text(`${percent}`)
container.append("text")
.style("font-size", "1.2rem")
.style("font-family", "Lato")
.attr("text-anchor", "middle")
.style("transform", "translate(0%, 15%)")
.text("Looking good!")
container.append("text")
.style("font-size", "1.2rem")
.style("font-family", "Lato")
.style("fill", "#4ABDAC")
.style("transform", "translate(0%, -20%)")
.attr("text-anchor", "middle")
.text("↑ 5 pts")
progress.transition().duration(2000).attrTween("d", arcTween(((2/3)*Math.PI)*(((2*percent)/100)-1)))
d3Container.exit().remove()
}
useEffect(() => {
if(d3Ref.current){
draw()
}
}, [d3Ref.current])
useEffect(() => {
if(typeof window !== undefined){
window.addEventListener("resize", draw)
}
return () => window.removeEventListener("resize", null)
}, [])
return (
<Container theme={theme}>
<SVGContainer ref={d3Ref} />
</Container>
)
}
export default Gauge
我遇到的最大问题是 d3 一直在追加,这让我相信 .exit().remove
不起作用,或者我只是缺少某种 React导致这种行为的知识。
有什么线索吗?
最佳答案
经过反复试验,
看来我需要通过D3 手动删除g 元素。
我在每次抽奖前添加了 d3.select("g").remove()
。
关于javascript - 即使在 React 中使用 .exit().remove(),D3 也会继续重新渲染,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58055910/