大家好,我是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對象。
其他
vue-fabric-editor開源圖片編輯器項目