html2canvas节点导出为图片相关方法

 html2canvas节点导出为图片的相关方法总结,如:等待函数、文件流转Blob函数、节点导出为单个图片、多个图片合成一张长图

需要提前安装html2canvas,安装方法:npm install html2canvas

具体方法:

import html2canvas from 'html2canvas';

/**
 * 等待几毫秒后执行
 * @param {number} ms 等待时间, 单位毫秒
 */
function waitTimeMS(ms) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve();
        }, ms);
    });
}

/**
 * 只要函数条件不满足就一直等待, 直到超时
 * @param {Function} fun [async] fun要运行的函数, 可以是异步函数
 * @param {number} [timeout=3] 超时时间, 单位秒
 * @returns {*} 函数计算结果
 */
async function waitFun(fun, timeout = 5) {
    let i = 0;
    let f = async() => {
        return await fun().catch(() => false);
    }
    let r = await f();
    while (!r && i < timeout * 10) {
        await waitTimeMS(100);
        r = await f();
        i = i + 1;
    }
    return r;
}

function dataURLToBlob(o) {
    const t = o.split(","),
        n = t[0].match(/:(.*?);/)[1],
        i = atob(t[1]);
    let s = i.length;
    const l = new Uint8Array(s);
    for (; s--;) l[s] = i.charCodeAt(s);
    return new Blob([l], { type: n });
    // return new File([l], fileName, { type: n }); // 文件流
}

// 单个图片
function saveFun() {
    let n = "png",
        i = "图片名称";
    let ele = document.body.querySelector(".background-box");
    const y = document.createElement("canvas");
    y.style.backgroundColor = getComputedStyle(ele.parentElement, null).backgroundColor;
    let width = ele.offsetWidth,
        height = ele.offsetHeight;
    y.style.width = width;
    y.style.height = height;
    y.width = width;
    y.height = height;
    let cxt = y.getContext('2d')
    cxt.translate(100, -10000) // 元素下载为图片的开始位置, 默认是cxt.translate(0, 0)
    html2canvas(ele, {
        tainttest: true,
        backgroundColor: y.style.backgroundColor,
        scale: 1,
        canvas: y,
        logging: !0,
        width: width,
        height: height,
        useCORS: !0,
        allowTaint: !0,
        imageTimeout: 60000,
    }).then((canvas) => {
        const c = document.body.appendChild(canvas);
        c.style.display = "none";
        console.log(11, 222, "createImage_html2canvas_2", c.toDataURL(`image/${n}`));
        const a = dataURLToBlob(c.toDataURL(`image/${n}`));
        document.body.removeChild(c);
        const r = document.createElement("a");
        r.style.display = "none";
        try {
            if (window.navigator && window.navigator.msSaveOrOpenBlob) {
                // 兼容IE/Edge
                window.navigator.msSaveOrOpenBlob(a, `${i}.${n}`)
            } else {
                let url = window.URL.createObjectURL(a)
                r.setAttribute('href', url)
                r.setAttribute('download', `${i}.${n}`)
                document.body.appendChild(r)
                r.click()
                window.URL.revokeObjectURL(url)
                document.body.removeChild(r)
            }
        } catch (h) {}
    });
}

// 多个图片合成一张长图 解决画布超过16300px后渲染问题,但是仍需注意 在 60000 * 1000,40000 *1500以内
function mergeImgs(list, cwidth = 500, cheight = 1000, sumHeight = 7800, urlType = 'image/png') {
    return new Promise((resolve, reject) => {
        const baseList = [];
        // 创建 canvas 节点并初始化
        const canvas = document.createElement('canvas');
        canvas.width = cwidth;
        canvas.height = sumHeight;
        const context = canvas.getContext('2d');
        list.map((item, index) => {
            const img = new Image();
            img.src = item; // base64,或者图片路径
            // 跨域
            img.crossOrigin = 'Anonymous';
            img.onload = () => {
                let canvasHeight = cheight * (index + 1) > sumHeight ? sumHeight - cheight * index : cheight;
                context.drawImage(img, 0, cheight * index, cwidth, canvasHeight);
                const base64 = canvas.toDataURL(urlType);
                baseList.push(base64);
                if (baseList[list.length - 1]) {
                    // 返回新的图片
                    resolve(baseList[list.length - 1]);
                }
            };
        });
    });
}

async function saveBatchFun(cheight = 10000) {
    let n = "png",
        i = "图片名称";
    let ele = document.body.querySelector(".background-box");
    const y = document.createElement("canvas");
    y.style.backgroundColor = getComputedStyle(ele.parentElement, null).backgroundColor;
    let scale = 1; // 图片放大倍数
    let width = ele.offsetWidth * scale,
        height = ele.offsetHeight * scale;
    let nums = Math.ceil(height / cheight)
    let arr = []
    for (let ns = 0; ns < nums; ns++) {
        arr.push(cheight * ns)
    }
    arr.push(height)
    let urlList = []
    for (let idx = 0; idx < arr.length - 1; idx++) {
        let imgHeight = arr[idx + 1] - arr[idx];
        y.style.width = width;
        y.style.height = imgHeight;
        y.width = width;
        y.height = imgHeight;
        let cxt = y.getContext('2d')
        cxt.translate(0, -arr[idx]) // 元素下载为图片的开始位置, 默认是cxt.translate(0, 0)
        html2canvas(ele, {
            tainttest: true,
            backgroundColor: y.style.backgroundColor,
            scale: scale,
            canvas: y,
            logging: !0,
            width: width,
            height: imgHeight,
            useCORS: !0,
            allowTaint: !0,
            imageTimeout: 60000,
        }).then((canvas) => {
            const c = document.body.appendChild(canvas);
            c.style.display = "none";
            const baseStr = c.toDataURL(`image/${n}`);
            document.body.removeChild(c);
            urlList.push(baseStr)
        });
        await waitFun(() => urlList[idx], 30)
    }
    mergeImgs(urlList, width, cheight, height, `image/${n}`).then((base64) => {
        const a = dataURLToBlob(base64);
        const r = document.createElement("a");
        r.style.display = "none";
        try {
            if (window.navigator && window.navigator.msSaveOrOpenBlob) {
                // 兼容IE/Edge
                window.navigator.msSaveOrOpenBlob(a, `${i}.${n}`)
            } else {
                let url = window.URL.createObjectURL(a)
                r.setAttribute('href', url)
                r.setAttribute('download', `${i}.${n}`)
                document.body.appendChild(r)
                r.click()
                window.URL.revokeObjectURL(url)
                document.body.removeChild(r)
            }
        } catch (h) {}

    });
}

export default {
    dataURLToBlob,
    saveFun,
    saveBatchFun,
    mergeImgs
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值