mirror of
https://github.com/woodchen-ink/CoverView.git
synced 2025-07-18 14:01:56 +08:00
feat: 优化图片下载逻辑,增加加载状态和错误处理,确保元素可见性
This commit is contained in:
parent
c50d7829f7
commit
40c2fc9b0d
@ -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 { exportComponentAsPNG } from "react-component-export-image";
|
||||||
import "./CoverImage.css";
|
import "./CoverImage.css";
|
||||||
import { ImgContext } from "../utils/ImgContext";
|
import { ImgContext } from "../utils/ImgContext";
|
||||||
@ -10,7 +10,7 @@ const ComponentToImg = (props) => {
|
|||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
|
|
||||||
const { unsplashImage } = useContext(ImgContext);
|
const { unsplashImage } = useContext(ImgContext);
|
||||||
const componentRef = React.createRef();
|
const componentRef = useRef(null);
|
||||||
|
|
||||||
async function saveImage(data) {
|
async function saveImage(data) {
|
||||||
try {
|
try {
|
||||||
@ -32,39 +32,93 @@ const ComponentToImg = (props) => {
|
|||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
|
// 等待一小段时间确保组件完全渲染
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 100));
|
||||||
|
|
||||||
const element = componentRef.current;
|
const element = componentRef.current;
|
||||||
|
|
||||||
if (!element) {
|
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');
|
const images = element.querySelectorAll('img');
|
||||||
await Promise.all(Array.from(images).map(img => {
|
console.log(`等待 ${images.length} 张图片加载完成...`);
|
||||||
if (img.complete) return Promise.resolve();
|
|
||||||
return new Promise((resolve, reject) => {
|
await Promise.all(Array.from(images).map((img, index) => {
|
||||||
img.onload = resolve;
|
if (img.complete && img.naturalWidth > 0) {
|
||||||
img.onerror = () => {
|
console.log(`图片 ${index + 1} 已加载`);
|
||||||
console.warn('图片加载失败:', img.src);
|
return Promise.resolve();
|
||||||
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();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
// 简化配置,只使用基本选项
|
console.log('所有图片处理完成,开始生成PNG...');
|
||||||
const data = await domtoimage.toPng(componentRef.current, {
|
|
||||||
|
// 再次确认元素状态
|
||||||
|
if (!componentRef.current) {
|
||||||
|
throw new Error('DOM元素在处理过程中丢失');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用更保守的配置
|
||||||
|
const options = {
|
||||||
height: element.offsetHeight * 2,
|
height: element.offsetHeight * 2,
|
||||||
width: element.offsetWidth * 2,
|
width: element.offsetWidth * 2,
|
||||||
style: {
|
style: {
|
||||||
transform: "scale(" + 2 + ")",
|
transform: "scale(2)",
|
||||||
transformOrigin: "top left",
|
transformOrigin: "top left",
|
||||||
width: element.offsetWidth + "px",
|
width: element.offsetWidth + "px",
|
||||||
height: element.offsetHeight + "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);
|
await saveImage(data);
|
||||||
|
|
||||||
// 跟踪 Unsplash 下载
|
// 跟踪 Unsplash 下载
|
||||||
@ -75,7 +129,6 @@ const ComponentToImg = (props) => {
|
|||||||
});
|
});
|
||||||
} catch (trackError) {
|
} catch (trackError) {
|
||||||
console.warn('跟踪下载失败:', trackError);
|
console.warn('跟踪下载失败:', trackError);
|
||||||
// 不影响主要功能,只是记录警告
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,14 +136,20 @@ const ComponentToImg = (props) => {
|
|||||||
console.error('下载图片时出错:', error);
|
console.error('下载图片时出错:', error);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
|
|
||||||
// 提供更友好的错误信息
|
// 提供更具体的错误信息
|
||||||
if (error.message.includes('CORS') || error.message.includes('cross-origin')) {
|
let errorMessage = '图片下载失败,请重试。';
|
||||||
alert('图片下载失败:跨域访问被阻止。请尝试刷新页面后重新选择图片。');
|
|
||||||
|
if (error.message.includes('cloneNode')) {
|
||||||
|
errorMessage = '页面还未完全加载,请等待几秒后重试。';
|
||||||
|
} else if (error.message.includes('CORS') || error.message.includes('cross-origin')) {
|
||||||
|
errorMessage = '图片下载失败:跨域访问被阻止。请尝试刷新页面后重新选择图片。';
|
||||||
} else if (error.message.includes('网络')) {
|
} else if (error.message.includes('网络')) {
|
||||||
alert('图片下载失败:网络连接问题。请检查网络连接后重试。');
|
errorMessage = '图片下载失败:网络连接问题。请检查网络连接后重试。';
|
||||||
} else {
|
} else if (error.message.includes('无法找到要下载的元素')) {
|
||||||
alert('图片下载失败,请重试。如果问题持续存在,请尝试选择其他图片。');
|
errorMessage = '页面还未准备好,请稍等片刻后重试。';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
alert(errorMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user