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

React中为SVG所有<g>元素添加点击事件并切换背景的方法

问题与解决方案

核心需求

  1. 给SVG内的每个<g>元素批量绑定点击事件
  2. 点击SVG元素时切换其背景样式

实现方案

1. 批量处理<g>元素的点击事件

把每个<g>对应的布局、文本数据抽成数组,通过React的map循环渲染,统一为每个<g>绑定点击事件,同时通过数据中的唯一ID区分点击的是哪个元素。

2. 点击切换背景样式

用React的useState管理当前选中元素的ID,渲染时根据选中状态动态给内容容器添加不同的CSS类,实现背景切换效果。


修改后的完整代码

React组件代码

const App = (props) => {
  // 存储当前选中元素的ID
  const [selectedId, setSelectedId] = React.useState(null);

  // 点击事件处理函数,接收当前元素ID
  const handleClick = (id) => {
    // 点击已选中的元素则取消选中,否则设置为当前选中项
    setSelectedId(prev => prev === id ? null : id);
  };

  // 抽离所有<g>元素的配置数据
  const groupList = [
    {
      id: 1,
      rectAttrs: { width: 57, height: 62 },
      foreignAttrs: { width: 57, height: 62 },
      category: 'Cat1',
      label: 'Label1'
    },
    {
      id: 2,
      rectAttrs: { x: 76, width: 82, height: 62 },
      foreignAttrs: { x: 76, width: 82, height: 62 },
      category: 'Cat2',
      label: 'Label2'
    },
    {
      id: 3,
      rectAttrs: { x: 185, width: 62, height: 160 },
      foreignAttrs: { x: 185, width: 62, height: 160 },
      category: 'Cat2',
      label: 'Label2'
    },
    {
      id: 4,
      rectAttrs: { y: 80, width: 158, height: 80 },
      foreignAttrs: { y: 80, width: 158, height: 80 },
      category: 'Cat2',
      label: 'Label2'
    }
  ];

  return ( 
  <svg
    width={247}
    height={160}
    viewBox="0 0 247 160"
    fill="none"
    xmlns="http://www.w3.org/2000/svg"
    {...props}
  >
    {groupList.map(item => (
      <g key={item.id} onClick={() => handleClick(item.id)}>
        {/* 设置透明填充,确保空白区域也能响应点击 */}
        <rect {...item.rectAttrs} fill="transparent" />
        <foreignObject {...item.foreignAttrs}>
          {/* 根据选中状态切换样式类 */}
          <div className={`item ${selectedId === item.id ? 'active' : ''}`}>
            <div className="category">{item.category}</div>
            <div className="label">{item.label}</div>
          </div>
        </foreignObject>
      </g>
    ))}
  </svg>
  )
}

ReactDOM.render(<App/>, document.getElementById("root"))

CSS样式

.item {
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background:#D9D9D9;
  cursor: pointer;
  transition: background 0.2s;
}

/* 选中状态的背景样式 */
.item.active {
  background: #6AA84F;
}

HTML结构

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

关键细节说明

  • 给<rect>添加fill="transparent":默认透明的SVG元素不会响应点击,设置透明填充后,整个<g>的区域都能触发点击事件
  • 用key属性标记每个<g>:符合React列表渲染的规范,避免渲染异常
  • 点击事件通过传递ID区分元素:精准控制每个<g>的选中状态,实现独立的背景切换

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 09:05:22