为什么添加crossOrigin会破坏结构.图片来自URL

Why does adding crossOrigin break fabric.Image.fromURL?

本文关键字:URL 结构 添加 crossOrigin 为什么      更新时间:2023-09-26

我有一个图像编辑器,我正试图将外部图像添加到其中。

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

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: '' });

这是一个演示

根据我的经验,您必须将crossOrigin设置为Anonymous。例如:

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

这直接来自Mozilla开发人员文档。

然而,您也会在文档中看到,并非所有浏览器都支持这一点,即Internet Explorer。我发现它在IE10和更旧的版本中确实有效。我正在为IE10及以上版本使用一种变通方法-请参阅下文。这不起作用的原因是,旧版本的IE没有实现完整的CORS规则集,也没有在其代码库中添加完整的HTML5(Canvas是其中的一部分)。然而,Firefox和Webkit浏览器(Chrome、Safari等)总是在更新,因此在这些新标准中远远领先于IE浏览器。

然而,另一个问题是,托管映像的服务器确实需要将Access Control Allow Origin标头设置为发出请求的页面的域或*。这来自Mozilla CORS文档。正如@CBroe上面提到的,你引用的youtube图片确实有这个标题集。因此,此图像会污染您的画布。

解决IE10及更早版本的crossOrigin的方法是使用服务器端代理,我猜这种解决方法可能适用于没有设置Access Control Allow Origin标头的图像。这里的概念是,您向网页所在域的服务器发送对YouTube图像的请求。这样可以将所有图像请求保持在同一个域上,从而传递CORS规则。但YouTube上的图片当然不是托管在服务器上的。然后,在服务器上响应的脚本会请求YouTube服务器(或任何其他服务器),在服务器中捕获图像,然后将其传回浏览器。这可以通过CURL请求或其他一些方法来完成。请确保从代理服务器设置"访问控制允许原点"标头。您可以在此处找到有关CORS服务器代理的更多信息。

尽管如此,遗憾的是,你的问题没有一个快速/简单的答案。浏览器正试图为用户提供最高的安全性,而跨站点脚本可能会产生一些问题,从而窃取身份等。这就是需要克服额外困难的原因。

同样值得注意的是,您可以查看JSONP解决方案(CORS的替代方案),但它是一个较旧的标准,有一些缺点——我认为它在一些更现代的浏览器中没有得到完全支持,并且存在一些安全问题。在谷歌上快速搜索,了解更多关于该选项的信息。

尝试添加这样的图像:

                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);
                }

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

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

尝试了上述所有解决方案,但在我的情况下都不起作用。我使用的是AWS s3
图像URL。在本地环境中工作良好,但没有在云中部署。所以这对我有效。

const toDataUrl = (url, callback) => {
    var xhr = new XMLHttpRequest();
    xhr.onload = function () {
        var reader = new FileReader();
        reader.onloadend = function () {
            callback(reader.result);
        }
        reader.readAsDataURL(xhr.response);
    };
    xhr.open('GET', url);
    xhr.responseType = 'blob';
    xhr.send();
}
//it cal be on load OR call it manually
useEffect(() => {
    //s3 image url 
    let testimonial_bg = 'https://s3.amazonaws.com/bucketname/foldername/imagename.jpg';
    toDataUrl(`${testimonial_bg}?time=${Date.now()}`, (myBase64) => {
            var img = new Image();
            img.onload = () => {
                let loadedImage = new fabric.Image(img, {
                    selectable: false,
                    id: 'mainbg',
                    left: 0,
                    top: 0,
                    crossOrigin: 'Anonymous'
                });
                loadedImage.scaleToHeight(canvasWidth);
                loadedImage.scaleToWidth(canvasWidth);
                canvas.current.setBackgroundImage(loadedImage);
                canvas.current.renderAll();
            }
            img.src = myBase64;
        });
}, []);

希望能有所帮助。:)

搜索1天后,我发现了这个

代替fabric.Image.fromURL

fabric.util.loadImage为我工作

就像这里的