【问题标题】:Challenge: Fix a Canvas plugin to work with CORS?挑战:修复 Canvas 插件以与 CORS 一起使用?
【发布时间】:2015-03-31 15:28:32
【问题描述】:

我正在向任何 Canvas 专家寻求帮助!

我需要一个固定的 jQuery/Canvas 插件。我在画布方面很弱。

基本上,我希望能够模糊图像,这是我使用这个 Canvas 脚本完成的: http://www.quasimondo.com/BoxBlurForCanvas/FastBlur2Demo.html

https://github.com/Quasimondo/QuasimondoJS/blob/master/blur/StackBoxBlur.js

但它不适用于托管在另一个域上的图像(我在 app.example.com 和 api.example.com 上拥有所有内容)。所以我需要更新它以尊重 CORS/crossOrigin。我与原始开发人员有documented the issue,但我怀疑他是否会修复它(自从他以主要方式触及它以来已经有好几年了)。

对于 Canvas 大师来说,工作时间可能很轻松。

插件通过调用这个来工作:

stackBoxBlurImage( sourceImageID, targetCanvasID, radius, blurAlphaChannel, iterations );

我试过这样做:

var img = document.getElementById( imageID );
    img.crossOrigin = '';
var w = img.naturalWidth;
var h = img.naturalHeight;

但这并不能解决问题。

理想情况下,我希望能够输入 $('.image')(或只是一个 URL,因为我不需要弄乱 DOM 的未模糊图像)和 $('.canvas') 元素,而不是两个身份证。这样,在事件中切换模糊图像可能会更容易一些(例如在菜单打开时模糊图像等)。

如果重要的话,我会在 Ember 应用中使用它。我也不想使用某种 PHP 代理脚本,这似乎是一种 hack 方式。

更新

我在这里添加了一个例子: http://dev.rickanddrew.com/

图片就在这里。如果您查看响应标头,我认为 CORS 设置正确: http://image.rickanddrew.com/image.jpg

回答

感谢下面的肯,我想通了!这就是我现在运行它的方式:

function stackBoxBlurImage( imageURL, $canvasObj, radius, blurAlphaChannel, iterations )
{

// Cache vars
var img = document.createElement('img');
var canvas = $canvasObj[0];

// Make it work with CORS
img.crossOrigin = '';
img.src = imageURL;     

// Wait till image loads
img.onload = function(e) {

    // Setup image vars         
    var w = img.naturalWidth;
    var h = img.naturalHeight;

    // Setup Canvas size
    canvas.style.width  = w + "px";
    canvas.style.height = h + "px";
    canvas.width = w;
    canvas.height = h;

    // Add image to Canvas
    var context = canvas.getContext("2d");  
    context.drawImage(img, 0, 0, canvas.width, canvas.height);
    context.clearRect( 0, 0, w, h );
    context.drawImage( img, 0, 0 );    

    // Abort if radius is invalid
    if ( isNaN(radius) || radius < 1 ) return;

    // Blur!
    stackBoxBlurCanvasRGB( canvas, 0, 0, w, h, radius, iterations );
};
}

谢谢!

【问题讨论】:

  • 您必须在源服务器上启用 CORS。或者查看我的 realtime-blur,它没有任何 CORS 限制(而且它是免费的)。
  • @KenFyrstenberg 我希望能够使用 CSS 模糊,但我无法处理它产生的内部阴影/白色效果。我需要图像适合全屏,边缘到边缘。我确实在服务器映像上启用了 CORS。
  • 你说你允许匿名跨域服务在你的服务器上的图像?如果是,那么您所要做的就是在 javascript 中设置 crossOrigin 标志,您的画布就不会被污染。您可能会仔细检查来自图像服务器的响应标头,因为听起来您没有正确设置跨域服务。
  • @markE 我为您添加了一个示例,向您展示我认为 CORS 设置正确。

标签: javascript jquery canvas cors


【解决方案1】:

#1 CORS 顺序很重要

CORS 请求未正确使用。就像现在一样,设置了图像标签的src,然后在模糊脚本中设置crossOrigin post:

function stackBoxBlurImage( imageID, canvasID, radius, blurAlphaChannel, iterations )
{

    var img = document.getElementById( imageID );   // we already have the image.
        img.crossOrigin = '';                       // too late for this...

    ...

这不起作用,因为crossOrigin 必须在之前设置图像src。 CORS 使用请求与 URL 请求一起发送(如果服务器不喜欢它,我们就没有图像......)。

所以要解决,要么将crossOrigin添加到img标签本身:

<img id="image" crossOrigin="anonymous" src="image.jpg">

如果您喜欢或需要动态设置src,或者在加载JavaScript 之前不要设置src(在这种情况下,我建议也动态创建图像元素):

<img id="image">

然后:

var image = document.getElementById("image");
image.crossOrigin = "";
image.onload = blur;
image.src = "image.jpg";

function blur() {
    stackBoxBlurImage( 'image', 'canvas', 30);              
}

#2 加载事项

脚本的调用方式也存在问题,这可能会阻止图像数据可用(新加载、无缓存等)。如果图像已存在于缓存中,则更难检测到此问题(但该站点的新用户可能在第一次加载时看不到任何内容..)。

改变这个:

jQuery(document).ready(function(){
    stackBoxBlurImage( 'image', 'canvas', 30);              
})

到:

$(window).load(function() {
    stackBoxBlurImage( 'image', 'canvas', 30);
})

ready 仅表示 DOM 已准备好,但不一定是图像数据。为此必须使用load

还有一个来自服务器的有趣响应,其中图像请求似乎被解释为纯文本。但是我没有进一步挖掘,因为上面的步骤应该首先解决(或者我可能只是眨了眨眼:)):

【讨论】:

  • 你好,肯!谢谢!我拿着你说的跑了,看看这里:dev.rickanddrew.com
  • @DrewBaker 很好,就是这样 :) 很高兴我能帮上忙!
猜你喜欢
  • 2014-04-26
  • 2020-12-24
  • 2018-12-20
  • 2015-09-10
  • 2012-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-02
相关资源
最近更新 更多