详解fabric.js图片跨域

大家好,我是vue-fabric-editor开源图片编辑器项目的作者,很多开发者都会问我图片跨域的问题如何处理,今天就详细的跟大家分享一下fabric.js图片跨域怎么处理。

问题现象

会报两种错误,要么保存新图片时报错,要么插入图片时报错:

  1. 图片插入到画布成功了,画布保存新图片时报错。
  2. 图片无法插入到画布,直接提示CORS报错。

先说结论:必须后端设置跨域,然后前端也设置跨越,才能正常将图片插入画布,并保存为新图片。

跨域的设置

跨域区分前端跨域与后端跨域设置,我通过http-server模拟跨域,8080下的HTML文件 访问8081的图片,测试视频,得出如下结果:

  1. 都不设置跨域:渲染正常,保存不正常。
  2. 仅前端设置跨域:渲染不正常。
  3. 仅后端设置跨域:渲染正常,保存不正常。
  4. 前后端均设置跨域:渲染正常,保存正常。

4种插入图片的方式

fabric.js 提供了多种插入图片的方式,主要流程都是将原生的Img对象转换成fabric.Image对象,然后插入到画布中。

  1. fabric.Image.fromURL:通过回调直接返回fabric的img对象,直接插入到画布中。
  2. fabric.util.loadImage:通过回调返回原生img对象,转换为fabric对象后插入画布中。
  3. new Image()document.createElement('img'):创建原生img对象,转换为fabric对象后插入画布中。
  4. <img />:将页面中的img元素,通过选择器获取到原生img对象,转换为fabric对象后插入画布中。
javascript 复制代码
// 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开源图片编辑器项目

相关推荐
Whisper_Sy21 小时前
Flutter for OpenHarmony移动数据使用监管助手App实战 - 应用列表实现
android·开发语言·javascript·flutter·php
json{shen:"jing"}21 小时前
1. 两数之和
前端·javascript·数据库
github.com/starRTC21 小时前
Claude Code中英文系列教程19:使用subagent子代理与创建自定义子代理【重要】
前端·javascript·数据库
hua_ban_yu21 小时前
vue3 + ts 制作指令,防止按钮在固定时间内重复点击,不会影响到表单的校验
前端·javascript·vue.js
老神在在0011 天前
Token身份验证完整流程
java·前端·后端·学习·java-ee
利刃大大1 天前
【Vue】指令修饰符 && 样式绑定 && 计算属性computed && 侦听器watch
前端·javascript·vue.js·前端框架
多仔ヾ1 天前
Vue.js 前端开发实战之 08-Vue 开发环境
vue.js
源码获取_wx:Fegn08951 天前
计算机毕业设计|基于springboot + vue景区管理系统(源码+数据库+文档)
java·vue.js·spring boot·后端·课程设计
踢球的打工仔1 天前
typescript-接口的基本使用(一)
android·javascript·typescript
徐小夕@趣谈前端1 天前
NO-CRM 2.0正式上线,Vue3+Echarts+NestJS实现的全栈CRM系统,用AI重新定义和实现客户管理系统
前端·javascript·人工智能·开源·编辑器·echarts