大家好,我是vue-fabric-editor开源图片编辑器项目的作者,很多开发者都会问我图片跨域的问题如何处理,今天就详细的跟大家分享一下fabric.js图片跨域怎么处理。
问题现象
会报两种错误,要么保存新图片时报错,要么插入图片时报错:
- 图片插入到画布成功了,画布保存新图片时报错。
- 图片无法插入到画布,直接提示CORS报错。
先说结论:必须后端设置跨域,然后前端也设置跨越,才能正常将图片插入画布,并保存为新图片。
跨域的设置
跨域区分前端跨域与后端跨域设置,我通过http-server模拟跨域,8080下的HTML文件 访问8081的图片,测试视频,得出如下结果:
- 都不设置跨域:渲染正常,保存不正常。
- 仅前端设置跨域:渲染不正常。
- 仅后端设置跨域:渲染正常,保存不正常。
前后端均设置跨域:渲染正常,保存正常。
4种插入图片的方式
fabric.js 提供了多种插入图片的方式,主要流程都是将原生的Img对象转换成fabric.Image对象,然后插入到画布中。
fabric.Image.fromURL
:通过回调直接返回fabric的img对象,直接插入到画布中。fabric.util.loadImage
:通过回调返回原生img对象,转换为fabric对象后插入画布中。new Image()
与document.createElement('img')
:创建原生img对象,转换为fabric对象后插入画布中。<img />
:将页面中的img元素,通过选择器获取到原生img对象,转换为fabric对象后插入画布中。// 1. 通过fabric.Image.fromURL插入图片 function addImgByUrl(url) { fabric.Image.fromURL( url, (imgEl) => { imgEl.set({ left: 100, top: 100, }); // 设置缩放 canvas.add(imgEl); canvas.setActiveObject(imgEl); canvas.renderAll(); }, { crossOrigin: 'anonymous' } ); } // 2. fabric.util.loadImage function addImgByUtils(url) { fabric.util.loadImage(url, function(catImg) { const mycatImg = new fabric.Image(catImg) mycatImg.set({ left: 180, top: 180, }); canvas.add(mycatImg); canvas.setActiveObject(mycatImg); canvas.renderAll(); }, null, {crossOrigin: 'Anonymous'}); } // 3. new Image() 与 document.createElement('img')是等价的方式 // MDN文档:https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLImageElement/Image function addImgByNewImage(url) { const image = new Image() image.setAttribute('crossOrigin', 'anonymous') image.onload = function () { fabricImage = new fabric.Image(image) fabricImage.set({ left: 150, top: 150, }); canvas.add(fabricImage); canvas.setActiveObject(fabricImage); canvas.renderAll(); } image.src = url } function addImgByCreateTag(url) { const tagImg = document.createElement('img') tagImg.crossOrigin = 'anonymous' tagImg.src = url // 等待图片加载完 tagImg.onload = function() { const myTagImg = new fabric.Image(tagImg) myTagImg.set({ left: 190, top: 190, }); canvas.add(myTagImg); canvas.setActiveObject(myTagImg); canvas.renderAll(); } } // 4.<img /> // <img id="imgTag" src="http://127.0.0.1:8081/1.png" crossorigin="anonymous" alt=""> function addImgByTag() { const catImg = document.getElementById('imgTag') // 等待图片加载完 catImg.onload = function() { const mycatImg = new fabric.Image(catImg) mycatImg.set({ left: 190, top: 190, }); canvas.add(mycatImg); canvas.setActiveObject(mycatImg); canvas.renderAll(); } }
源码实现
源码中原生Img对象与fabric.Image
对象的关系
new fabric.Image()
只接收原生image对象。
fabric.Image.fromURL(url)
等于fabric.util.loadImage
+new fabric.Image
,在源码内部实现了转换的操作。
fabric.util.loadImage()
等于fabric.util.createImage
=document.createElement('img')
,等同于手动创建原生img对象。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。