详解Canvas 跨域脱坑实践


Posted in HTML / CSS onNovember 07, 2018

Canvas 跨域如何解决?这里记录下使用 Canvas 绘图过程中所遇到的跨域问题和解决方案。

先来看下实现方法。

实现方法

目标图片一般是由 图片 + 文本 构成。无论是千奇百怪的大小图片,还是变幻莫测的各式文本,都能用 canvas api drawImage 和 fillText 方法来完成。

基本流程如下:

1、获取 canvas 上下文 -- ctx

const canvas = document.querySelector(selector)
const ctx = canvas.getContext('2d')

2、绘图

忽略图片上的内容,直接用 drawImage 将其画到 canvas 画布上即可。

const image = new Image()
image.src = src
image.onload = () => {
    ctx.save()
    // 这里我们采用以下参数调用
    this.ctx.drawImage(image, dx, dy, dWidth, dHeight)
    this.ctx.restore()
}

drawImage 有3种参数使用方式,具体用法可以查看MDN 文档。

3、获取图像数据

调用 HTMLCanvasElement DOM 对象提供的 toBlob(), toDataURL() 或 getImageData() 方法,即可。

canvas.toBlob(blob => {
    // 你要的 blob
}, mimeType, encoderOptions)

这里的 mimeType 默认值为 image/png。encoderOptions 指定了图片质量,可用于压缩,不过需要 mimeType 格式为 image/jpeg 或者 image/webp。

Canvas 跨域

正常情况下,如果需要将绘制好的图像输出,我们可以调用 canvas 的 toBlob(), toDataURL() 或 getImageData() 方法来获取到图像数据。然而,遇到图片跨域的情况就有些尴尬了。可能回报如下错误:

Failed to execute 'toBlob' on 'HTMLCanvasElement': Tainted canvases may not be exported.

或者

Access to image at 'https://your.image.src' from origin 'https://your.website' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

先来看看第2种情况。

Access-Control-Allow-Origin

如果你跨域使用某些图片资源,并且该服务未正确响应 Access-Control-Allow-Origin 头信息, 则会报出如下错误信息:

Access to image at 'https://your.image.src' from origin 'https://your.website' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

说明不允许跨域访问,那么你可以试着让后台修改 Access-Control-Allow-Origin 的值为 * 或 your.website, 或者改用同域资源(考虑下?)。

接下来,我们来解决第1种情况。

img.crossOrigin = 'Anonymous'

为避免未经许可拉取远程网站信息而导致的用户隐私泄露(如 GPS 等信息,具体可搜索 Exif),在调用 canvas 的 toBlob(), toDataURL() 或 getImageData() 会抛出安全错误:

Failed to execute 'toBlob' on 'HTMLCanvasElement': Tainted canvases may not be exported.

如果你的图片服务允许跨域使用(如果不允许,见上条),那么你该考虑下给 img 元素加上 crossOrigin 属性,即:

const image = new Image()
image.crossOrigin = 'Anonymous'
image.src = src

如此,你便可以拿到图片数据了。如果没招,换同域资源吧~

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

HTML / CSS 相关文章推荐
CSS3属性使网站设计增强同时不消弱可用性
Aug 29 HTML / CSS
两种CSS3伪类选择器详细介绍
Dec 24 HTML / CSS
一款恶搞头像特效的制作过程 利用css3和jquery
Nov 21 HTML / CSS
CSS3实现文字波浪线效果示例代码
Nov 20 HTML / CSS
html5绘制时钟动画
Dec 15 HTML / CSS
HTML5中Localstorage的使用教程
Jul 09 HTML / CSS
HTML5 Canvas实现图片缩放、翻转、颜色渐变的代码示例
Feb 28 HTML / CSS
Canvas与图片压缩的示例代码
Nov 28 HTML / CSS
amazeui页面校验功能的实现代码
Aug 24 HTML / CSS
浅谈CSS不规则边框的生成方案
May 25 HTML / CSS
纯html+css实现打字效果
Aug 02 HTML / CSS
HTML5+CSS+JavaScript实现捉虫小游戏设计和实现
Oct 16 HTML / CSS
浅谈移动端网页图片预加载方案
Nov 05 #HTML / CSS
Canvas中设置width与height的问题浅析
Nov 01 #HTML / CSS
html5 postMessage前端跨域并前端监听的方法示例
Nov 01 #HTML / CSS
HTML5之消息通知的使用(Web Notification)
Oct 30 #HTML / CSS
详解Html5页面实现下载文件(apk、txt等)的三种方式
Oct 22 #HTML / CSS
html5 http的轮询和Websocket原理
Oct 19 #HTML / CSS
canvas实现扭蛋机动画效果的示例代码
Oct 17 #HTML / CSS
You might like
PHP开发中常用的8个小技巧
2008/08/27 PHP
PHP5中虚函数的实现方法分享
2011/04/20 PHP
修改PHP的memory_limit限制的方法分享
2012/02/21 PHP
PHPThumb图片处理实例
2014/05/03 PHP
php实现的替换敏感字符串类实例
2014/09/22 PHP
php实现删除指定目录下相关文件的方法
2014/10/20 PHP
smarty模板引擎中自定义函数的方法
2015/01/22 PHP
PHP面试题之文件目录操作
2015/10/15 PHP
PHP 微信支付类 demo
2015/11/30 PHP
PHP使用ActiveMQ实现消息队列的方法详解
2019/05/31 PHP
Javascript实现的分页函数
2006/12/22 Javascript
gridpanel动态加载数据的实例代码
2013/07/18 Javascript
如何实现JavaScript动态加载CSS和JS文件
2020/12/28 Javascript
Javascript BOM学习小结(六)
2015/11/26 Javascript
实例讲解jQuery中对事件的命名空间的运用
2016/05/24 Javascript
关于JSON.parse(),JSON.stringify(),jQuery.parseJSON()的用法
2016/06/30 Javascript
浅谈addEventListener和attachEvent的区别
2016/07/14 Javascript
Angularjs实现分页和分页算法的示例代码
2016/12/23 Javascript
JS实现多级菜单中当前菜单不随页面跳转样式而发生变化
2017/05/30 Javascript
vue.js实现备忘录功能的方法
2017/07/10 Javascript
JS实现键值对遍历json数组功能示例
2018/05/30 Javascript
vue.js与后台数据交互的实例讲解
2018/08/08 Javascript
vue项目实现表单登录页保存账号和密码到cookie功能
2018/08/31 Javascript
解决vue项目打包上服务器显示404错误,本地没出错的问题
2020/11/03 Javascript
[43:36]Liquid vs Mineski 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
[01:33:30]DOTA2-DPC中国联赛 正赛 RNG vs Phoenix BO3 第二场 2月5日
2021/03/11 DOTA
python subprocess 杀掉全部派生的子进程方法
2017/01/16 Python
python 获取文件下所有文件或目录os.walk()的实例
2018/04/23 Python
Django Admin 上传文件到七牛云的示例代码
2020/06/20 Python
瑞典最好的运动鞋专卖店:Sneakersnstuff
2016/08/29 全球购物
澳大利亚巧克力花束和礼品网站:Tastebuds
2019/03/15 全球购物
班长岗位职责
2013/11/10 职场文书
一份文言文检讨书
2014/09/13 职场文书
2014乡镇干部对照检查材料思想汇报
2014/09/26 职场文书
公安领导班子四风问题个人整改措施思想汇报
2014/10/09 职场文书
创业计划书之家教托管
2019/09/25 职场文书