svg 转 png/jpg

2,082 阅读1分钟

在前端如何将svg文件转为png或者jpg呢?

  1. 读取svg file得到xml内容
  2. 将xml内容转为base64格式图片
  3. 加载base64图片为image元素
  4. 使用canva绘制image元素
  5. 使用canva将image数据导出为png或jpg格式的base64图片
const isCrossOriginUrl = url => {
    const origin = location.host;

    return url.indexOf('data:') !== 0 && url.indexOf(origin) < 0;
};
/**
 *
 * @param url url -> image
 */
const loadImage = url => {
    return new Promise((resolve, reject) => {
        const img = new Image();

        if(isCrossOriginUrl(url)) {
            img.crossOrigin = 'Anonymous';
        }

        img.onload = () => {
            resolve(img);
        };

        img.onerror = function() {
            const msg = 'Image load error: ' + url;

            reject(new Error(msg));
        };

        img.src = url;
    });
};
/**
 * image元素 -> base64 Data
 * @param image image node
 */
export const imageToPng = (image: HTMLImageElement) => {
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');
    canvas.width = image.width;
    canvas.height = image.height;
    ctx.drawImage(image, 0, 0, image.width, image.height);
    return canvas.toDataURL('image/png');
};


/**
 * 
 * @param xml svg 的xml内容
 */
export const svgToPng = async(xml: string) => {
    const base64 = window.btoa(unescape(encodeURIComponent(xml)));
    const image64 = `data:image/svg+xml;base64,${base64}`;
    const image = await loadImage(image64);
    return imageToPng(image);
};

/**
 * 
 * @param 读取文件内容
 */
export const readFile = (file, dataType = 'DataURL') => {
    return new Promise((resolve, reject) => {
        const reader = new FileReader();
        const fnName = `readAs${dataType}`;

        if(!reader[fnName]) {
            throw new Error('File read error, dataType not support');
        }

        reader.onerror = () => {
            reject(new Error('File read error'));
        };

        reader.onload = () => {
            resolve(reader.result);
        };

        reader[fnName](file);
    });
};

export const svgFile2Png = (file) => {
	return readFile(file, 'Text').then(svgToPng)
}