You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 06:57:17