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

Recharts双饼图问题:单个禁用Tooltip及ResponsiveContainer样式调整

Recharts双饼图问题解决方案

问题概述

  1. 同一PieChart容器内的两个Pie组件,左侧的Tooltip会干扰右侧基于activeIndex的自定义Label,需实现仅为单个Pie显示Tooltip。
  2. 将两个Pie拆分到独立PieChart时出现报错;使用独立ResponsiveContainer虽可行,但难以实现并排布局的样式控制。

解决方案一:单个PieChart内实现Tooltip隔离

Recharts的Tooltip支持通过pieId属性配合filter方法,精准指定仅对目标Pie组件生效:

  1. 给两个Pie组件分别设置唯一pieId
  2. 在Tooltip的filter回调中,只保留目标Pie的tooltip数据

修改后的核心代码片段:

// 左侧Pie:设置pieId并保留Tooltip
<Pie
  pieId="account-balance"
  data={data}
  cx={120}
  cy={120}
  innerRadius={70}
  outerRadius={90}
  fill="#8884d8"
  paddingAngle={5}
  dataKey="value"
>
  {data.map((entry, index) => (
    <Cell key={`cell-${index}`} fill={COLORS[index % COLORS.length]} />
  ))}
  <Label
    value={total_balance}
    offset={0}
    position="center"
    formatter={formatCurrency}
  />
</Pie>
<Tooltip
  formatter={formatCurrency}
  // 仅显示pieId为account-balance的Tooltip
  filter={(payload) => payload.pieId === "account-balance"}
/>

// 右侧Pie:设置独立pieId,不绑定Tooltip
<Pie
  pieId="asset-distribution"
  data={data2}
  cx={380}
  cy={120}
  labelLine={false}
  outerRadius={80}
  fill="#8884d8"
  dataKey="value"
  activeShape={renderActiveShape}
  activeIndex={activeIndex}
  onMouseEnter={onPieEnter}
>
  {data2.map((entry, index) => (
    <Cell key={`cell-${index}`} fill={COLORS[index % COLORS.length]} />
  ))}
</Pie>

解决方案二:独立PieChart实现并排布局

拆分到独立PieChart并通过CSS Flexbox实现并排,解决报错和样式问题:

完整组件代码:

const AccountSummary = (props) => {
  const [activeIndex, setActiveIndex] = useState();

  let data = [];
  let total_balance = 0;
  props.accounts.forEach((account) => {
    data.push({ name: account.name, value: account.current_balance });
    total_balance += account.current_balance;
  });

  const formatCurrency = (value) =>
    new Intl.NumberFormat("en-US", {
      maximumSignificantDigits: 10,
      style: "currency",
      currency: "USD",
    }).format(value);

  const data2 = [
    { name: "Equities", value: 800 },
    { name: "Bonds", value: 400 },
  ];

  const onPieEnter = (_, index) => {
    setActiveIndex(index);
  };

  // 并排布局容器样式
  const chartWrapperStyle = {
    display: "flex",
    gap: "40px",
    justifyContent: "center",
    width: "100%",
    maxWidth: "800px",
    margin: "0 auto",
  };

  // 单个饼图容器样式
  const chartItemStyle = {
    flex: 1,
    minWidth: "200px",
  };

  return (
    <div>
      <h4>Total Account Value: {formatCurrency(total_balance)}</h4>

      <div style={chartWrapperStyle}>
        {/* 第一个独立饼图:账户余额 */}
        <ResponsiveContainer width="100%" height={300} style={chartItemStyle}>
          <PieChart>
            <Pie
              data={data}
              cx="50%"
              cy="50%"
              innerRadius={70}
              outerRadius={90}
              fill="#8884d8"
              paddingAngle={5}
              dataKey="value"
            >
              {data.map((entry, index) => (
                <Cell key={`cell-${index}`} fill={COLORS[index % COLORS.length]} />
              ))}
              <Label
                value={total_balance}
                offset={0}
                position="center"
                formatter={formatCurrency}
              />
            </Pie>
            <Tooltip formatter={formatCurrency} />
          </PieChart>
        </ResponsiveContainer>

        {/* 第二个独立饼图:资产分布 */}
        <ResponsiveContainer width="100%" height={300} style={chartItemStyle}>
          <PieChart>
            <Pie
              data={data2}
              cx="50%"
              cy="50%"
              labelLine={false}
              outerRadius={80}
              fill="#8884d8"
              dataKey="value"
              activeShape={renderActiveShape}
              activeIndex={activeIndex}
              onMouseEnter={onPieEnter}
            >
              {data2.map((entry, index) => (
                <Cell key={`cell-${index}`} fill={COLORS[index % COLORS.length]} />
              ))}
            </Pie>
          </PieChart>
        </ResponsiveContainer>
      </div>
    </div>
  );
};

export default AccountSummary;

关键说明:

  • 外层div使用Flexbox实现并排,通过flex:1让两个饼图容器平分可用宽度
  • 每个PieChart用cx="50%"和cy="50%"自动居中,避免手动设置固定坐标的适配问题
  • 拆分后两个饼图完全独立,无Tooltip干扰或组件冲突问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 04:35:53