fabric.js里添加图片因为跨域问题无法正常渲染和canvas污染无法保存问题

fabric.js里添加图片因为跨域问题无法正常渲染和canvas污染无法保存问题

问题

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

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

我在网上查询了很多资料,有说fabric.js没有配置跨域,后端没有配置跨域,浏览器缓存原因等等,这些都遗漏了一个比较常见根本的因素,往下继续看。

前提检查

前提是我们需要使用img标签的crossorigin="anonymous"来测试前后端是否产生跨域问题,如果后端服务器没有正确配置图片资源的跨域问题,是无法显示图片的,会报跨域的错误。
在浏览器控制台中我们能看到没有配置跨域的图片响应头是这样的:

在这里插入图片描述
在响应头中是并没有看到Access-Control-Allow-Origin: *;那么这个请求就会被浏览器规则所拦截无法正常渲染。

解决方法

有人疑惑说我后端明明在头部加了header(Access-Control-Allow-Origin: *)呀,为什么还是无法渲染,关键的问题是在nginx上,针对http:xxx/static/1.png这种图片链接,我们需要在nginx的location /static/ { … }中一定要加入add_header跨域配置!!!

 server{
        listen 80;
        server_name xxx.xxx.xxx.xxx;
        index index.html index.htm index.php;
        root  /www/wwwroot/xxx.xxx.xxx.xxx/frontEnd/build;
        include enable-php.conf;
        access_log  /www/wwwlogs/access.log;
        
          location /static/ {
            alias /www/wwwroot/xxx.xxx.xxx.xxx/static/; #静态资源路径
            add_header Access-Control-Allow-Origin *;
            add_header Access-Control-Allow-Methods 'DELETE,PATCH,PUT,VIEW,GET, POST, OPTIONS';
            add_header Access-Control-Allow-Headers 'ACCEPT,Accept-Encoding,AUTHORIZATION,ORIGIN,Access-Token,DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
          }
          location / {
            proxy_pass http://127.0.0.1:8000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            
          }
    }

再次访问图片资源,会发现响应头中添加了Access-Control-Allow-Origin,图片在img标签下也能正常渲染!
在这里插入图片描述

我是django项目部署到堡塔服务器的,项目中的settings.py也是需要配置跨域请求,具体看其他人配置的就行:
通过 django-cors-headers 库来实现跨域

如果是其他语言的,如PHP项目的,可以看看除了添加header(Access-Control-Allow-Origin: *)外,还记得针对图片文件http:xxx/static/1.png的路径location /static/添加跨域!

通过fabric.js渲染图片加入canvas和保存图片:

1.添加图片进入canvas:

canvas = new fabric.Canvas("canvas", {
    width: "400",
    height: "400",
    backgroundColor: "#f5deb3",
  });

// 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();
  }, {crossOrigin: 'Anonymous'});
}

// 3. new Image() 与 document.createElement('img')是等价的方式
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();
    }
}

为了防止浏览器缓存,可使用**var Url = url+‘?time=’ + new Date().valueOf()**来避免缓存!

2.保存图片或PDF:

function canvasToImage() {
 // 保存图片
  var canvas = document.getElementById("canvas");
  const MIME_TYPE = "image/png";
  const imgURL = canvas.toDataURL(MIME_TYPE);

  // 创建一个隐藏的 a 标签
  const dlLink = document.createElement("a");
  const filename = "个人画板_" + new Date().getTime() + ".png";

  // 设置下载文件名和链接的 href 属性
  dlLink.download = filename;
  dlLink.href = imgURL;

  // 触发下载
  document.body.appendChild(dlLink);
  dlLink.click();
  document.body.removeChild(dlLink);
	
  // 保存ptf
  //import html2Canvas from "html2canvas";
  //import JsPDF from "jspdf";
  // var title = "单页报告";
  // var dom = document.getElementById("canvas"); // 生成pdf的html内容
  // html2Canvas(dom, {
  //   allowTaint: true,
  //   scrollY: 0,
  //   scrollX: 0,
  //   useCORS: true, // 开启跨院
  //   // width: 1000, // 宽度
  //   height: dom.offsetHeight,
  // }).then(function (canvas) {
  //   var contentWidth = canvas.width;
  //   var contentHeight = canvas.height;
  //   var pdfWidth = ((contentWidth + 10) / 2) * 0.75;
  //   var pdfHeight = ((contentHeight + 200) / 2) * 0.75; // 500为底部留白
  //   var imgWidth = pdfWidth;
  //   var imgHeight = (contentHeight / 2) * 0.75; //内容图片这里不需要留白的距离
  //   var pageData = canvas.toDataURL("image/jpeg", 1.0);
  //   var pdf = new JsPDF("", "pt", [pdfWidth, pdfHeight]);
  //   pdf.addImage(pageData, "jpeg", 0, 0, imgWidth, imgHeight);
  //   pdf.addPage();
  //   // pdf.save(title + ".pdf");
  //   let blob = new Blob([pdf.output("blob")], { type: "application/pdf" });

  //   let name = "pdfFile";
  //   let file = new File([blob], `${name}.pdf`, { type: blob.type });
  //   pdf.save(file);
  // });
}

跨域的设置
跨域区分前端跨域与后端跨域设置,得出如下结果:

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

多看看请求响应头中是否带有Access-Control-Allow-Origin,带有则表明后端开启跨域,前端img标签中设置crossorigin="anonymous“或js中设置 {crossOrigin: ‘Anonymous’}这种,说明前端开启了跨域,不然可打印img标签出来,看是否带有。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值