zoukankan      html  css  js  c++  java
  • html2canvas 截图不完整 图片缺失问题

    核心是在html2canvas执行前先替换所有图片转换为Blob,这种方式不会出现图片缺失的情况 

    /**
     * @description 替换 去全部图片真实地址为blob  渲染 截图
     * @param {element} el       截图的dom区域
     * @param {function} success  成功
     * @param {function} error    错误
    */
    function getHandle({ el, success, error } = {}) {
        let imgArr = el.querySelectorAll('img')
        imgArr = Array.from(imgArr)
        let i = 0
        if (imgArr[0]) {
            let timer = setInterval(() => {
                clearInterval(timer)
                if (imgArr.length !== i) {
                    error && error('超时')
                }
            }, 10000);
            [...imgArr].forEach((dom) => {
                dom.src = `${dom.src}?${Math.random()}`;
                getUrlBlob(dom.src, ((blob) => {
                    if (blob !== false) {
                        dom.src = blob
                    }
                    i++
                    // 校验是否全部替换完毕
                    if ((imgArr.length) === i) {
                        clearInterval(timer)
                        IsRender.call(this, el, success, error)
                    }
                }))
            })
            return
        }
        IsRender.call(this, el, success, error)
    }
    /**
     * @description blob转换处理
     * @param {string}   url 传 url 和 一个回调 
     * @param {function} callback    false  说明已是blob 或者 当前img 无 src
     *                              返回值  转成的blob临时地址(成功)
     *                              原图的img src  (转换失败 返回原图)
    */
    const getUrlBlob = (url, callback) => {
        const str = url.substring(0, 50)
        // 避免重复加载
        if (str.includes('blob:')) {
            return callback(false)
        }
        // 避免img未有src属性的情况,导致未返回
        if (!str) {
            return callback(false)
        }
        let canvas = document.createElement("canvas")
        let ctx = canvas.getContext("2d")
        let img = new Image
        img.crossOrigin = 'Anonymous'
        img.src = url
        img.onload = function () {
            canvas.height = img.height
            canvas.width = img.width
            ctx.drawImage(img, 0, 0)
            try {
                canvas.toBlob((blob) => {
                    callback(URL.createObjectURL(blob))
                })
            } catch (err) {
                callback(img.src)
                console.error('转换失败,使用原图', err)
            }
            canvas = null
        }
        // img.error = function () {
        //     callback(img.src)
        //     console.error('转换失败,使用原图', img.error)
        // }
    }
    /**
     * @description 截图操作
     * @param {element} el       截图的dom区域
     * @param {function} success  成功  返回完整的base64
     * @param {function} error    错误  返回err信息
    */
    function IsRender(el, success, error) {
        setTimeout(() => {
            var width = el.offsetWidth; //获取dom 宽度
            var height = el.offsetHeight; //获取dom 高度
            var canvas = document.createElement("canvas"); //创建一个canvas节点
            // 兼容清晰度
            const scale = window.devicePixelRatio; //定义任意放大倍数 支持小数
            canvas.width = width * scale; //定义canvas 宽度 * 缩放
            canvas.height = height * scale; //定义canvas高度 *缩放
            var context = canvas.getContext('2d');
            // 去图片锯齿 官网
            context.mozImageSmoothingEnabled = false;
            context.webkitImageSmoothingEnabled = false;
            context.msImageSmoothingEnabled = false;
            context.imageSmoothingEnabled = false;
            // options配置
            var opts = {
                scale: scale,
                canvas: canvas,
                logging: false,
                 width,
                height: height,
                dpi: 300,
                useCORS: true,
                backgroundColor: "transparent",
                allowTaint: false,
            };
            // 进行截图
            html2canvas(el, opts)
                .then(canvas => {
                    try {
                        const base64 = canvas.toDataURL('image/png');
                        success && success.call(this, base64)
                    } catch (err) {
                        error && error(err)
                    }
                })
                .catch(err => {
                    error && error(err)
                })
        }, 500)
    }
    // 调用方法
        getHandle.call(this, {
            el: document.querySelector('.card_jt'),
            // 成功回调
            async success(val) {
                // val就是拿到的 base64
            },
            error(err) {
                console.error(err)
            }
        })
  • 相关阅读:
    Netty 源码解读(二)-ChannelPipeline、ChannelHandler、ChannelHandlerContext
    Netty源码解读(一)-服务启动和接收请求源码
    浅谈自动化测试框架开发
    程序运行时环境
    常见的Linux内核线程
    一个好用gdb扩展工具
    使用Qemu模拟Numa机器
    使用qemu的nat方式登录
    2021.32 量化
    2021.31 模型
  • 原文地址:https://www.cnblogs.com/Im-Victor/p/15675320.html
Copyright © 2011-2022 走看看