祖安之光
2025-11-17 3b491dc5782fce3c5a504ad4364e1c93f6fbc37b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/**
 * Vue3 在线图片 URL 转 base64
 * @param {string} imgUrl - 在线图片地址(如 "https://xxx.com/sign.png")
 * @param {Object} options - 配置项
 * @param {string} options.format - 图片格式(默认 png,可选 jpeg/webp)
 * @param {number} options.quality - 压缩质量(0-1,默认 1.0 无损)
 * @returns {Promise<string>} 完整 base64 字符串(含 data:image/xxx;base64, 前缀)
 */
export function imageUrlToBase64(
    imgUrl,
    { format = 'png', quality = 1.0 } = {}
) {
    return new Promise((resolve, reject) => {
        if (!imgUrl) {
            reject(new Error('图片 URL 不能为空'));
            return;
        }
 
        // 处理 URL 特殊字符(如空格、中文)
        const encodedUrl = encodeURI(imgUrl);
 
        const img = new Image();
        // 跨域关键配置(需图片服务器支持 CORS)
        img.crossOrigin = 'Anonymous';
 
        // 图片加载成功
        img.onload = () => {
            const canvas = document.createElement('canvas');
            const ctx = canvas.getContext('2d');
            if (!ctx) {
                reject(new Error('Canvas 初始化失败'));
                return;
            }
 
            // 保持图片原始尺寸(避免拉伸)
            canvas.width = img.naturalWidth;
            canvas.height = img.naturalHeight;
 
            // 绘制图片(清除透明背景,适配 jpeg 格式)
            if (format === 'jpeg') {
                ctx.fillStyle = '#ffffff';
                ctx.fillRect(0, 0, canvas.width, canvas.height);
            }
            ctx.drawImage(img, 0, 0);
 
            // 转换为 base64
            try {
                const base64 = canvas.toDataURL(`image/${format}`, quality);
                resolve(base64);
            } catch (err) {
                reject(new Error(`base64 转换失败:${err.message}`));
            }
 
            // 释放内存(销毁临时元素)
            canvas.remove();
            img.remove();
        };
 
        // 图片加载失败(跨域、URL 无效、网络错误)
        img.onerror = (err) => {
            reject(new Error(`图片加载失败:${err.message},可能是跨域限制或 URL 无效`));
        };
 
        // 触发加载(必须放在回调绑定后)
        img.src = encodedUrl;
    });
}