【问题标题】:Why does adding crossOrigin break fabric.Image.fromURL?为什么添加 crossOrigin 会破坏 fabric.Image.fromURL?
【发布时间】:2019-03-07 01:25:47
【问题描述】:

我有一个图像编辑器,我正在尝试向其中添加外部图像。

当我将 crossOrigin 属性添加到 img 对象时,它无法在画布上加载图像,并且我在控制台中收到错误“加载时出错 https://i.ytimg.com/vi/JphpLkmimVo/hqdefault.jpg”。如果我删除 crossOrigin 它允许添加图像但是当我将画布导出为图像时出现安全错误。我读过在没有 crossOrigin 的情况下添加它会污染画布。谁能告诉我为什么我可以只保留 crossOrigin 属性?

var stockImageSrc = 'https://i.ytimg.com/vi/JphpLkmimVo/hqdefault.jpg';
fabric.Image.fromURL(stockImageSrc, function (oImg) {
                        oImg.setWidth(640);
                        oImg.setHeight(390);
                        canvas.add(oImg); 
                        canvas.renderAll();
                    }, { crossOrigin: '' });

Here is a demo

【问题讨论】:

  • 远程站点需要允许您在您的域上以这种方式使用他们的图像 - 他们必须这样做,这没什么可以决定。
  • @CBroe 据我所知,这些图片是 YT 缩略图,是从他们的 API 返回的,旨在用于不同的域。有没有办法判断他们是否不允许这样做?
  • 您显示的示例 URL 未发送任何 CORS 标头。所以不,它似乎不是为了以这种方式使用而设计的。我建议您查看他们的文档/常见问题解答,看看他们是否在任何地方提到了 CORS。

标签: javascript html canvas html5-canvas fabricjs


【解决方案1】:

根据我的经验,您必须将 crossOrigin 设置为匿名。举个例子:

var stockImageSrc = 'https://i.ytimg.com/vi/JphpLkmimVo/hqdefault.jpg';
fabric.Image.fromURL(stockImageSrc, function (oImg) {
    ... other code here...
 }, { crossOrigin: 'Anonymous' });

这直接来自Mozilla developer documentation

但是,您还会在该文档中看到并非所有浏览器(即 Internet Explorer)都支持此功能。我发现它在 IE10 和更早版本中确实 NOT 工作 - IE11 确实工作。我正在为 IE10 和更早版本使用解决方法 - 见下文。这不起作用的原因是旧版本的 IE 没有实现完整的 CORS 规则集,并且缺少完整的 HTML5(Canvas 是其中的一部分)添加到它的代码库中。然而,Firefox 和 Webkit 浏览器(Chrome、Safari 等)一直在更新,因此在这些较新的标准中它们远远领先于 IE 同行。

然而,另一部分是托管图像的服务器确实需要将 Access-Control-Allow-Origin 标头设置为发出请求的页面的域或至 *。这来自Mozilla CORS documentation。正如上面提到的@CBroe,您引用的 youtube 图片确实 NOT 设置了该标题。因此,此图像会污染您的画布。

解决 IE10 和更早版本的 crossOrigin 的方法,我猜这种解决方法可能适用于没有设置 Access-Control-Allow-Origin 标头的图像,是使用服务器端代理。这里的概念是,您将 YouTube 图片的请求发送到您的网页所在域上的服务器。这将所有图像请求保持在同一个域上,从而通过 CORS 规则。但 YouTube 图片当然不在该服务器上。然后,在您的服务器上响应的脚本将请求 YouTube 服务器(或任何其他服务器),在服务器上捕获图像,然后将其传递回浏览器。这可以通过 CURL 请求或其他一些方法来完成。确保从代理服务器设置 Access-Controls-Allow-Origin 标头。您可以在CORS Server Proxy here 上找到更多信息。

说了这么多,遗憾的是,您的问题没有快速/简单的答案。浏览器正试图为其用户提供最高的安全性,而跨站点脚本可能会产生一些可能窃取身份等的问题。这就是要跳过额外的障碍的原因。

另外值得注意的是,您可以查看 JSONP 解决方案(CORS 的替代方案),但它是一个较旧的标准并且有一些负面影响 - 我相信它在一些更现代的浏览器中并不完全支持并且存在一些安全问题。快速进行 Google 搜索以了解有关该选项的更多信息。

【讨论】:

  • 我正在使用fabric 2.x,为了实现这一点,您需要稍微修改Image对象声明。 fabric.Image.fromURL(ImageSrc, callback, null, { crossOrigin: 'Anonymous' })
  • 我们可以在织物画布上加载视频吗?
  • 不确定,从未尝试过。遗憾的是,现在几年没有使用画布了……谷歌搜索表明它是可能的。
  • 嗨@PromInc:即使我也申请了crossOrigin: 'Anonymous',我也有同样的问题。我仍然面临与以下相同的错误:CORS 策略已阻止从源“localhost:9001”访问“localhost:9000/assets/images/image.png”处的图像:没有“Access-Control-Allow-Origin”请求的资源上存在标头。参考:jsfiddle.net/jasie/r3fqu4p6/33
  • 这个解决方案实际上确实在一个用例中节省了一天的时间:当用户选择一个本地文件上传到您的画布中,并且您希望在他们完成编辑后获取画布的图像快照.在这种情况下,没有服务器(它是客户端的机器上传到客户端的应用程序会话)。但是,当尝试对第 3 方资源(即外部网站)执行相同操作时,这并不能解决 CORS 问题。随心所欲地摔跤,银弹解决方案将始终是制作代理服务器。具有许多好处,例如保护 API 密钥。
【解决方案2】:

尝试像这样添加图像:

                var imgObj = new Image();

                imgObj.crossOrigin = "Anonymous";
                imgObj.src = http://example.com/50/50 ; //the source of your image

                imgObj.onload = function () {
                    // start fabricJS stuff
                    imgObj.width = 100
                    imgObj.height = 100

                    var image = new fabric.Image(imgObj);
                    image.set({
                        top: 100,
                        left: 100 ,
                        padding: 10,
                        cornersize: 10,
                    });

                    //image.scale(0.1).setCoords();
                    canvas.add(image);
                }

【讨论】:

    【解决方案3】:

    你可以尝试这种方式(当然这只是概念证明)

    function getCORSImage(url) {
      var oIm=document.createElement("img");
      oIm.setAttribute('src', url);
      return new fabric.Image(oIm,{
        width: 640
        height: 390
      });
    }
    

    【讨论】:

      【解决方案4】:

      搜索 1 天后,我找到了这个

      而不是fabric.Image.fromURL

      fabric.util.loadImage 为我工作

      喜欢here

      【讨论】:

      • fabric.Image.fromURL 适用于 CORS。我有一段时间没有升级了,但这应该可以:fabric.Image.fromURL(imageUrl, callbackFunction, {crossOrigin: 'anonymous'});
      • 将来,您可能希望用理性和逻辑来支持您的答案,如果您给出的答案结构合理,请避免使用“不要这样做”的答案,您应该用证据说明为什么不这样做至于为什么不应该这样做。这个答案是不久前的,我希望您已经学会提供更好的答案。
      猜你喜欢
      • 2019-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-31
      • 2017-12-04
      • 1970-01-01
      • 2015-03-25
      • 1970-01-01
      相关资源
      最近更新 更多