解决canvas图片getImageData,toDataURL跨域问题
source link: https://www.zhangxinxu.com/wordpress/2018/02/crossorigin-canvas-getimagedata-cors/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
by zhangxinxu from http://www.zhangxinxu.com/wordpress/?p=7378
本文可全文转载,但需要保留原作者和出处。
一、首先,图片服务器需要配置Access-Control-Allow-Origin
一般团队都会有一个专门域名放置静态资源,例如腾讯是gtimg.com
,百度是bdimg.com
;或者很多团队使用的是腾讯云或者阿里云的服务。
而主页面所在域名往往不一样,当需要需要对canvas图片进行getImageData()
或toDataURL()
操作的时候,跨域问题就出来了,而且跨域问题还不止一层。
首先,第一步,图片服务器需要配置Access-Control-Allow-Origin信息,例如:
如PHP添加响应头信息,*
通配符表示允许任意域名:
header("Access-Control-Allow-Origin: *");
或者指定域名:
header("Access-Control-Allow-Origin: www.zhangxinxu.com");
此时,Chrome浏览器就不会有Access-Control-Allow-Origin相关的错误信息了,但是,还会有其他的跨域错误信息。
二、canvas图片getImageData cross-origin跨域问题
对于跨域的图片,只要能够在网页中正常显示出来,就可以使用canvas的drawImage()
API绘制出来。但是如果你想更进一步,通过getImageData()
方法获取图片的完整的像素信息,则多半会出错。
举例来说,使用下面代码获取github上的自己头像图片信息:
var canvas = document.createElement('canvas'); var context = canvas.getContext('2d'); var img = new Image(); img.onload = function () { context.drawImage(this, 0, 0); context.getImageData(0, 0, this.width, this.height); }; img.src = 'https://avatars3.githubusercontent.com/u/496048?s=120&v=4';';
结果在Chrome浏览器下显示如下错误:
Uncaught DOMException: Failed to execute ‘getImageData’ on ‘CanvasRenderingContext2D’: The canvas has been tainted by cross-origin data.
Firefox浏览器错误为:
SecurityError: The operation is insecure.
如果使用的是canvas.toDataURL()方法,则会报:
Failed to execute ‘toDataURL’ on ’HTMLCanvasElement’: Tainted canvased may not be exported
原因其实都是一样的,跨域导致。
那有没有什么办法可以解决这个问题呢?
可以试试crossOrigin
属性。
三、HTML crossOrigin属性解决资源跨域问题
在HTML5中,有些元素提供了支持CORS(Cross-Origin Resource Sharing)(跨域资源共享)的属性,这些元素包括<img>
,<video>
,<script>
等,而提供的属性名就是crossOrigin
属性。
因此,上面的跨域问题可以这么处理:
var canvas = document.createElement('canvas'); var context = canvas.getContext('2d'); var img = new Image(); img.crossOrigin = ''; img.onload = function () { context.drawImage(this, 0, 0); context.getImageData(0, 0, this.width, this.height); }; img.src = 'https://avatars3.githubusercontent.com/u/496048?s=120&v=4';';
增加一个img.crossOrigin = ''
即可,虽然JS代码这里设置的是空字符串,实际上起作用的属性值是anonymous
。
crossOrigin
可以有下面两个值:
其中,只要crossOrigin
的属性值不是use-credentials
,全部都会解析为anonymous
,包括空字符串,包括类似'abc'
这样的字符。
img.crossOrigin = 'abc'; console.log(img.crossOrigin); // 结果是'anonymous'
另外还有一点需要注意,那就是虽然没有crossOrigin
属性,和设置crossOrigin="use-credentials"
在默认情况下都会报跨域出错,但是性质上却不一样,两者有较大区别。
crossOrigin兼容性
IE11+(IE Edge),Safari,Chrome,Firefox浏览器均支持,IE9和IE10会报SecurityError安全错误,如下截图:
四、crossOrigin属性为什么可以解决资源跨域问题?
crossOrigin=anonymous
相对于告诉对方服务器,你不需要带任何非匿名信息过来。例如cookie,因此,当前浏览器肯定是安全的。
就好比你要去别人家里拿一件衣服,crossOrigin=anonymous
相对于告诉对方,我只要衣服,其他都不要。如果不说,可能对方在衣服里放个窃听器什么的,就不安全了,浏览器就会阻止。
五、IE10浏览器不支持crossOrigin怎么办?
我们请求图片的时候,不是直接通过new Image()
,而是借助ajax和URL.createObjectURL()
方法曲线救国。
代码如下:
var xhr = new XMLHttpRequest(); xhr.onload = function () { var url = URL.createObjectURL(this.response); var img = new Image(); img.onload = function () { // 此时你就可以使用canvas对img为所欲为了 // ... code ... // 图片用完后记得释放内存 URL.revokeObjectURL(url); }; img.src = url; }; xhr.open('GET', url, true); xhr.responseType = 'blob'; xhr.send();
此方法不仅IE10浏览器OK,原本支持crossOrigin的诸位浏览器也是支持的。
也就多走一个ajax请求,还可以!
根据,根据实践发现,在IE浏览器下,如果请求的图片过大,几千像素那种,图片会加载失败,我猜是超过了blob尺寸限制。
六、结束语
最近工作中学到的一点小经验,希望可以帮到遇到类似问题的小伙伴。
感谢阅读!
Recommend
-
21
说明 canvas元素标签强大之处在于可以直接在HTML上进行图形操作,具有极大的应用价值。 canvas 可以实现对图像的像素操作,这就要说到 getImageData() 方法了。 解释 CanvasRenderingContext2D.getImag
-
18
zuul+security跨域Cors问题解决 简介 场景 在服务后台都会出现跨域cors问题,不过一般spring解决起来比较方便,在框架+框架的基础上,问题就显得特别明显了,各种冲突,不了解源码的运行原理,解决起来...
-
17
报错详尽信息 Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported. 关键词 canvas.toDataURL() cross...
-
35
源码 package main import ( "github.com/gin-gonic/gin" "strings" "fmt" "net/http" ) func main() { r := gin.Default() r.Use(Cors()) //开启中间件 允许使用跨域请求 r.run() }...
-
43
Nuxt 是 Vue 项目服务器端渲染(SSR)解决方案。而在使用时,就会遇到前后端分离情况下的域名或端口不一致导致的跨域问题。本文将介绍如何通过设置代理解决 Nuxt 与
-
5
Detecting Canvas.toDataURL Support in Browsers Tuesday, February 1, 2011 I am wrapping up a code example that uses the Canvas.toData...
-
4
Setting the background color when generating images from Canvas.toDataURL Monday, January 31, 2011 One of the cool features of the HTML5 canvas element is the toDa...
-
8
Why does HTML Canvas getImageData () not return exactly the same values that were set? advertisements When writing pixels to an HTML Canvas...
-
0
前端性能优化 —— 使用 BMP 图片代替 canvas.toDataURL 前端开发中有时需要...
-
5
关于getImageData ctx.getImageData(),可以获取canvas的data图片数据,这个图片数据返回的data是一个对象,该对象包含指定的 ImageData 对象的图像数据。 对于 ImageData 对象中的每个像素,都存在着四方面的信息,即 RGBA 值: R - 红色 (...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK