web端canvas绘制海报下载分享的相关问题

大家好,我是南游。

最近遇到了使用canvas绘制分享海报的需求,在这里对开发过程中遇到的一些问题进行了整理。

1.图片的绘制是异步的,要在图片上进行内容绘制需要在背景图片绘制完成后进行绘制,即在回调里面执行。

scss 复制代码
        img.onload = () => {
            ctx.drawImage(img, 0, 0)
            //do something
        }

2.海报绘制完成时保存下载图片报错(跨域)的问题。

ini 复制代码
   <div className="poster-wrap">
       <canvas  className="canvas" id="canvas" width="375" height="820" > </canvas>
   </div>

如果使用跨域的资源画到canvas中,并且资源没有使用CORS去请求,canvas会被认为是被污染了, canvas可以正常展示,但是没办法使用[toDataURL()]或者[toBlob()])导出数据。

详情见 Allowing cross-origin use of images and canvas

因此需要在img标签上设置crossorigin,启用CORS,属性值为anonymous

ini 复制代码
        const canvas = document.getElementById('canvas')
        const ctx = canvas.getContext('2d')
        const img = new Image()
        img.crossOrigin = 'anonymous'
        img.src = 'xxxxxxx'
        img.onload = () => {
            ctx.drawImage(img, 0, 0)
        }

添加crossOrigin="anonymous"允许跨域后图片却无法显示了,依然报错跨域,此时需要在服务端配置跨域设置

因为我的图片是放在阿里云上的,因此需要在阿里云的oss跨域设置里进行配置,允许 *.test.com 跨域。详情见

设置成功后可以在f12上看请求静态资源的响应头,如果响应头里面带了Access-Control-Allow-Origin域名,那么浏览器就允许跨域访问。

图片已经通过img标签加载过,浏览器默认会缓存下来,下次使用js方式再去请求,直接返回缓存的图片,如果缓存中的图片不是通过CORS请求或者响应头中不存在Access-Control-Allow-Origin,都会导致报错。使用js方式请求图片资源, 需要避免使用缓存,设置url后加上时间戳,或者http头设置Cache-Control为no-cache。

ini 复制代码
  let img = new Image()
  img.crossOrigin = 'anonymous'
  img.src = url + '?time=' + new Date().valueOf()
  img.onload = () => {
    // ... do something
  }
  img.onerror = (err) => {
    console.log(err)
  }

最后就是根据需求画好海报并下载。

ini 复制代码
        ctx.fillStyle = '#ffffff'
        ctx.font = 'bold 20px sans-serif'
        ctx.fillText('hello world', 15, 24)
        ctx.font = 'bold 10px sans-serif'
        ctx.fillText('hello', 30, 24)
javascript 复制代码
        function downloadPoster() {
            let imgSrc = canvas.toDataURL('image/png', 0.9)
            let imgName = '海报'
            let elem = document.createElement('a')
            elem.setAttribute('href', imgSrc)
            elem.setAttribute('download', imgName)
            document.body.appendChild(elem)
            elem.click()
            document.body.removeChild(elem)
        }
相关推荐
passerma10 分钟前
解决qiankun框架子应用打包后css里的图片加载404失败问题
前端·微前端·qiankun
Aliex_git22 分钟前
性能优化 - Vue 日常实践优化
前端·javascript·vue.js·笔记·学习·性能优化
董世昌4125 分钟前
添加、删除、替换、插入元素的全方法指南
java·开发语言·前端
qq_3168377531 分钟前
Element-Plus el-table lazy 自动更新子列表
前端·vue.js·elementui
林恒smileZAZ1 小时前
Electron 的西天取经
前端·javascript·electron
这就是佬们吗1 小时前
告别 Node.js 版本冲突:NVM 安装与使用全攻略
java·linux·前端·windows·node.js·mac·web
IT_陈寒1 小时前
2024年JavaScript开发者必备的10个ES13新特性实战指南
前端·人工智能·后端
满栀5851 小时前
基于 jQuery 实现商品列表增删改查与数据统计
前端·javascript·jquery
web小白成长日记1 小时前
CSS 作用域隔离实战:React、Vue 与 Styled Components 的三种范式
前端·css·vue.js·react.js
Mr -老鬼1 小时前
Electron 与 Tauri 全方位对比指南(2026版)
前端·javascript·rust·electron·nodejs·tauri