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

Storybook中Nivo choropleth等值区域图SVG的d3 zoom事件不触发

问题根因
  • 执行d3.select('svg')的时机错误:React函数组件的逻辑执行顺序优先于DOM渲染,你在组件顶层直接选择SVG元素时,StyledResponsiveChoropleth渲染的SVG还没挂载到页面上,选中的元素为空/不符合预期,缩放事件自然没有绑定到正确的DOM上
  • 缩放逻辑没有做去重处理:组件每次重渲染都会重复执行追加rect、绑定缩放事件的逻辑,会导致DOM节点冗余、事件重复绑定
  • 缩放变换的应用逻辑错误:handleZoom里每次触发缩放都新增一个g元素,没有把变换应用到Nivo渲染的实际图表容器上,就算事件触发也看不到缩放效果
修复方案

用useEffect监听组件挂载状态,等SVG渲染完成后再执行缩放初始化逻辑,同时调整变换的应用对象:

import { useEffect, useRef } from 'react'
import { select, zoom, type ZoomBehavior } from 'd3'

export const ChloropethChart: FC<IChoroplethChartProps> = ({
  height, data, featureData, colors, domain
}) => {
  // 存储zoom实例避免重复创建
  const zoomRef = useRef<ZoomBehavior<SVGSVGElement, unknown> | null>(null)

  const handleZoom = (e: any) => {
    // 选择Nivo渲染的实际图表容器组应用变换,不要每次新增g
    select('svg .nivo-choropleth')
      .attr('transform', e.transform)
  }

  useEffect(() => {
    // 组件挂载后再选择SVG,此时DOM已渲染
    const selectSVG = select<SVGSVGElement, unknown>('svg')
    if (!selectSVG.node()) return

    // 只追加一次事件承接层
    if (!selectSVG.select('.zoom-mask').node()) {
      selectSVG
        .append('rect')
        .attr('class', 'zoom-mask')
        .attr('width', '100%')
        .attr('height', '100%')
        .style('fill', 'none')
        .style('pointer-events', 'all')
        .lower() // 放到SVG最底层,不遮挡原有图表交互
    }

    // 初始化缩放行为
    zoomRef.current = zoom<SVGSVGElement, unknown>().on('zoom', handleZoom)
    selectSVG.call(zoomRef.current)

    // 组件卸载时清理事件
    return () => {
      if (zoomRef.current) {
        selectSVG.on('.zoom', null)
        zoomRef.current = null
      }
    }
  }, []) // 空依赖保证只在挂载/卸载时执行一次

  return (
    <StyledChoroplethChart height={height}>
      <StyledResponsiveChoropleth
        data={data}
        features={featureData}
        margin={{ top: 0, right: 0, bottom: 0, left: 0 }}
        colors={colors ? colors : PURPLE_RANGE}
        domain={domain}
      />
    </StyledChoroplethChart>
  )
}

export default ChloropethChart

内容的提问来源于stack exchange,提问作者Loreen

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 15:18:05