React+D3.js条形竞速图:添加无需重绘的播放/暂停功能求助
React + D3.js 条形竞速图:添加无需重绘的播放/暂停功能问题
我正在使用React结合d3.js库开发条形竞速图,已实现某示例效果,但无法添加无需重绘整个图表的播放/暂停功能以停止和恢复动画。以下是我的代码:
export default function RacerBar(){ const ref = useRef() const [animationEnabled, setAnimationEnabled] = useState(true); const [isFetched, setIsFetched] = useState(false); const [data, setData] = useState([{}]); const [selectedIndicator, setSelectedIndicator] = useState("indicator_1"); useEffect(()=>{ const fetchData = async () => { await fetch("/api/chart").then( res => res.json()) .then((data) => { setData(data) setIsFetched(true) }) } fetchData() },[]) useEffect(()=>{ if (isFetched) { const names = new Set(data.map(d => d.client)) const datavalues = Array.from(d3.rollup(data, ([d]) => d[selectedIndicator], d => +d.year, d => d.client)) const svg = d3.select(ref.current) svg.selectAll("*").remove() //other svg settings const ticker = 2500; async function plotChart(data) { const dateList = new Set(data.map(d=>d.year)); const fontSize = 16; const rectProperties = {height: 20, padding: 10} const container = svg.append("g") .classed("container", true) .style("transform", "translateY(25px)") const widthScale = d3.scaleLinear() const axisTop = svg .append('g') .classed('axis', true) .style("transform", "translate(10px, 20px)") .call(d3.axisTop(widthScale)) //This part is responsible for the animation. const update = (date) => { const presentData = []; for (var i=0; i < data.length; i++){ if (data[i].year === date){ var key=data[i].client; var value = data[i][selectedIndicator] presentData.push({"key": key, "value": value}) } } //svg maniplation, drawing bars and labels similar to the example } // iterating through the data for (const date of dateList) { update(date) await new Promise(done => setTimeout(() => done(), ticker)); } } plotChart(data) } },[isFetched, selectedIndicator]) const handleIndicatorChange = (event) => { setSelectedIndicator(event.target.value); } return ( <div className="RacerBar"> <Dropdown label="Chooes option" options={dropDownItems} value={selectedIndicator} onChange={handleIndicatorChange}/> <div className="container"> <svg ref={ref} style={{width: parseInt(width, 10) || 1000, height: parseInt(height, 10) || 1000}} id={`racerbar_chart`} /> </div> <Button onClick={() => { setAnimationEnabled(!animationEnabled) }}> {animationEnabled ? "Pause" : "Play"} </Button> </div> ) }
代码说明
- 通过
useEffect等待数据获取完成,这部分运行正常。 - 数据获取完成后,另一个
useEffect触发并调用plotChart函数:该函数先处理svg对象,再定义负责绘制条形、创建标签的update函数,最后通过for循环迭代数据调用update更新图表。 - 作为React新手,尚未完全理解其DOM管理,尝试多种方法后仍无法将
update函数独立出来通过useEffect调用,特此求助。
更新
感谢帮助,我已找到合适解决方案,最终代码已上传至我的GitHub页面,欢迎查看或评论。
内容的提问来源于stack exchange,提问作者abigel
相关产品推荐
相关产品推荐

