解决 html2canvas 跨越

应用场景

场景1:线上域名与图片域名不一样。

出现错误:Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.

场景2:线上域名是 https,图片的域名是 http

出现错误:Redirect from 'http://cdn.******.cn/1551270315991.jpeg' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://h5.******.cn' is therefore not allowed access.

解决思路

  1. 图片的 crossOrigin 设置为 *
  2. 图片 URL 添加随机参数
  3. 图片转为 base64 图片

核心代码

image.crossOrigin = '*'
this.$utils.addURLParam(elem.src, new Date().getTime())
this.getBase64Image(image)

完整参考代码(Vue)

我的业务场景是生成宣传海报,执行 create() 方法

// 转为 base64 图片
getBase64Image(img) {
    let canvas = document.createElement('canvas')

    canvas.width = img.width
    canvas.height = img.height

    let ctx = canvas.getContext('2d')

    ctx.drawImage(img, 0, 0, canvas.width, canvas.height)

    let dataURL = canvas.toDataURL('image/png') // 可选其他值 image/jpeg

    return dataURL
},
// HTML 转成画布,生成图片
getPoster() {
    window.scrollTo(0, 0) // 修复上边有空白 BUG,https://github.com/niklasvh/html2canvas/issues/1878

    // http://html2canvas.hertzen.com/configuration/ 配置设置地址
    let opts = {
        scale: 4, // 画布像素大小。默认为浏览器设备像素比。
        // logging: true, // 日志开关,便于查看 html2canvas 的内部执行流程
        useCORS: true, // 【重要】开启跨域配置
        allowTaint: true, // 【重要】开启画布污染
        backgroundColor: '#0000'
    }

    this.$html2canvas(this.$refs.createContainer, opts).then(canvas => {
        this.posterUrl = canvas.toDataURL('image/jpeg') // 默认转化的格式为 png,也可设置为其他格式
        this.$loading().close()
    })
},
// 生成海报
create() {
    this.$loading({
        showMask: true,
        text: '正在生成海报...'
    })

    let imgs = this.$refs.createContainer.querySelectorAll('img')
    let count = 0 // 计数用

    // 排除 base64 图片,因为 base64 图片无跨域问题
    imgs = Array.from(imgs).filter(elm => {
        return elm.src && !/^data:image\/png;base64/.test(elm.src)
    })

    if (imgs.length > 0) {
        // 将会跨域的图片转为支持跨域 base64 图片,最后再执行 html2canvas
        imgs.forEach((elm, index, arr) => {
            let image = new Image()

            image.crossOrigin = '*' // 支持跨域图片
            image.src = this.$utils.addURLParam(
                elm.src,
                'date=' + new Date().getTime()
            ) // URL 添加随机参数,使 onload 生效

            image.onload = () => {
                elm.src = this.getBase64Image(image) // 移动端还需要转为 base64 图片
                count++

                // 全部图片加载完毕
                if (count === arr.length) {
                    this.getPoster()
                }
            }
        })
    } else {
        this.getPoster()
    }
}

工具方法 this.$utils.addURLParam()

/**
 * 添加 URL 参数
 * @param {String} url 链接,默认 window.location.href
 * @param {String} param 参数,例 id=1
 * @return {String} 新的 URL
 */
export const addURLParam = (url = window.location.href, param) => {
  let parmas = new URLSearchParams(url.split('?')[1])

  return url + (parmas.toString() ? '&' : '?') + param
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值