diff --git a/src/components/ComponentToImg.js b/src/components/ComponentToImg.js index 28a5789..739130b 100644 --- a/src/components/ComponentToImg.js +++ b/src/components/ComponentToImg.js @@ -1,4 +1,4 @@ -import React, { useContext, useState } from "react"; +import React, { useContext, useState, useRef } from "react"; // import { exportComponentAsPNG } from "react-component-export-image"; import "./CoverImage.css"; import { ImgContext } from "../utils/ImgContext"; @@ -10,7 +10,7 @@ const ComponentToImg = (props) => { const [loading, setLoading] = useState(false) const { unsplashImage } = useContext(ImgContext); - const componentRef = React.createRef(); + const componentRef = useRef(null); async function saveImage(data) { try { @@ -32,39 +32,93 @@ const ComponentToImg = (props) => { try { setLoading(true); + // 等待一小段时间确保组件完全渲染 + await new Promise(resolve => setTimeout(resolve, 100)); + const element = componentRef.current; if (!element) { - throw new Error('无法找到要下载的元素'); + throw new Error('无法找到要下载的元素,请稍后重试'); + } + + // 检查元素是否在DOM中且可见 + if (!document.body.contains(element)) { + throw new Error('元素不在DOM中'); + } + + if (element.offsetWidth === 0 || element.offsetHeight === 0) { + throw new Error('元素尺寸为0,请等待页面完全加载'); } // 等待所有图片加载完成 const images = element.querySelectorAll('img'); - await Promise.all(Array.from(images).map(img => { - if (img.complete) return Promise.resolve(); - return new Promise((resolve, reject) => { - img.onload = resolve; - img.onerror = () => { - console.warn('图片加载失败:', img.src); - resolve(); // 即使图片加载失败也继续 + console.log(`等待 ${images.length} 张图片加载完成...`); + + await Promise.all(Array.from(images).map((img, index) => { + if (img.complete && img.naturalWidth > 0) { + console.log(`图片 ${index + 1} 已加载`); + return Promise.resolve(); + } + return new Promise((resolve) => { + const timeout = setTimeout(() => { + console.warn(`图片 ${index + 1} 加载超时:`, img.src); + resolve(); + }, 8000); + + img.onload = () => { + console.log(`图片 ${index + 1} 加载完成`); + clearTimeout(timeout); + resolve(); }; - // 设置超时 - setTimeout(resolve, 5000); + + img.onerror = () => { + console.warn(`图片 ${index + 1} 加载失败:`, img.src); + clearTimeout(timeout); + resolve(); + }; + + // 如果图片已经加载但事件没触发 + if (img.complete) { + clearTimeout(timeout); + resolve(); + } }); })); - // 简化配置,只使用基本选项 - const data = await domtoimage.toPng(componentRef.current, { + console.log('所有图片处理完成,开始生成PNG...'); + + // 再次确认元素状态 + if (!componentRef.current) { + throw new Error('DOM元素在处理过程中丢失'); + } + + // 使用更保守的配置 + const options = { height: element.offsetHeight * 2, width: element.offsetWidth * 2, style: { - transform: "scale(" + 2 + ")", + transform: "scale(2)", transformOrigin: "top left", width: element.offsetWidth + "px", height: element.offsetHeight + "px", + }, + // 添加过滤器,跳过可能有问题的节点 + filter: (node) => { + // 跳过脚本标签和样式标签 + if (node.tagName === 'SCRIPT' || node.tagName === 'STYLE') { + return false; + } + // 跳过隐藏元素 + if (node.style && node.style.display === 'none') { + return false; + } + return true; } - }); + }; + const data = await domtoimage.toPng(componentRef.current, options); + + console.log('PNG生成成功'); await saveImage(data); // 跟踪 Unsplash 下载 @@ -75,7 +129,6 @@ const ComponentToImg = (props) => { }); } catch (trackError) { console.warn('跟踪下载失败:', trackError); - // 不影响主要功能,只是记录警告 } } @@ -83,14 +136,20 @@ const ComponentToImg = (props) => { console.error('下载图片时出错:', error); setLoading(false); - // 提供更友好的错误信息 - if (error.message.includes('CORS') || error.message.includes('cross-origin')) { - alert('图片下载失败:跨域访问被阻止。请尝试刷新页面后重新选择图片。'); + // 提供更具体的错误信息 + let errorMessage = '图片下载失败,请重试。'; + + if (error.message.includes('cloneNode')) { + errorMessage = '页面还未完全加载,请等待几秒后重试。'; + } else if (error.message.includes('CORS') || error.message.includes('cross-origin')) { + errorMessage = '图片下载失败:跨域访问被阻止。请尝试刷新页面后重新选择图片。'; } else if (error.message.includes('网络')) { - alert('图片下载失败:网络连接问题。请检查网络连接后重试。'); - } else { - alert('图片下载失败,请重试。如果问题持续存在,请尝试选择其他图片。'); + errorMessage = '图片下载失败:网络连接问题。请检查网络连接后重试。'; + } else if (error.message.includes('无法找到要下载的元素')) { + errorMessage = '页面还未准备好,请稍等片刻后重试。'; } + + alert(errorMessage); } }