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

如何让html-to-image对所有div正常实现截图下载?

问题原因与修复方案

核心问题

你把同一个contentRef绑定到了4个div上,React的useRef在给多个元素赋值时,最终只会保留最后一个被绑定的元素引用。所以不管你切换显示哪个div,contentRef.current始终指向最后一个div,其他隐藏的div因为display:none,截图时自然生成空白黑图。


修复步骤

  1. 用useRef创建对象存储每个div的独立引用,避免引用被覆盖
  2. 用React状态跟踪当前显示的div ID,替代原生DOM操作,更符合React数据流
  3. 修改截图函数,根据当前显示的ID获取对应div的引用进行截图

修改后的完整代码

import { useRef, useState } from 'react';
// 确保已导入html-to-image的toPng和SoccerLineUp组件

export default function App() {
  // 用对象存储每个div的独立ref
  const contentRefs = useRef({
    div1: null,
    div2: null,
    div3: null,
    div4: null
  });
  // 状态管理当前显示的div ID
  const [activeDivId, setActiveDivId] = useState('div1');

  const handleCapture = () => {
    // 获取当前显示的div节点
    const activeNode = contentRefs.current[activeDivId];
    if (!activeNode) return;

    toPng(activeNode, { cacheBust: true, height: 410 })
      .then(dataUrl => {
        const link = document.createElement("a");
        link.download = `${activeDivId}-lineup.png`; // 给不同截图命名区分
        link.href = dataUrl;
        link.click();
      })
      .catch(error => {
        console.error("Error capturing screenshot:", error);
      });
  };

  // 简化切换显示的逻辑
  const showDiv = (divId) => {
    setActiveDivId(divId);
  };

  return (
    <>
      {/* 用条件渲染控制显示,替代原生display操作 */}
      {activeDivId === 'div1' && (
        <div ref={el => contentRefs.current.div1 = el} className="col-9" id="div1">
          <SoccerLineUp
            size={"fill"}
            color={"green"}
            pattern={"lines"}
            homeTeam={homeTeam}
          />
        </div>
      )}
      {activeDivId === 'div2' && (
        <div ref={el => contentRefs.current.div2 = el} className="col-9" id="div2">
          <SoccerLineUp
            size={"fill"}
            color={"green"}
            pattern={"lines"}
            homeTeam={formation}
          />
        </div>
      )}
      {activeDivId === 'div3' && (
        <div ref={el => contentRefs.current.div3 = el} className="col-9" id="div3">
          <SoccerLineUp
            size={"fill"}
            color={"green"}
            pattern={"lines"}
            homeTeam={formation2}
          />
        </div>
      )}
      {activeDivId === 'div4' && (
        <div ref={el => contentRefs.current.div4 = el} className="col-9" id="div4">
          <SoccerLineUp
            size={"fill"}
            color={"green"}
            pattern={"lines"}
            homeTeam={formation3}
          />
        </div>
      )}

      {/* 切换阵容的按钮 */}
      <button onClick={() => showDiv('div1')}>阵容1</button>
      <button onClick={() => showDiv('div2')}>阵容2</button>
      <button onClick={() => showDiv('div3')}>阵容3</button>
      <button onClick={() => showDiv('div4')}>阵容4</button>

      <button className="downloadButton" onClick={handleCapture}>
        Download
      </button>
    </>
  );
}

关键修改说明

  • 多ref存储:contentRefs对象分别保存每个div的引用,避免单个ref被后续元素覆盖
  • 状态驱动显示:用activeDivId状态控制组件渲染,替代原生DOM操作,更符合React的声明式编程风格
  • 动态目标截图:截图时根据当前激活的ID获取对应DOM节点,确保截取的是当前显示的内容
  • 差异化命名:下载文件名加入div ID,方便区分不同阵容的截图

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 06:05:03