将SVG过滤器应用于HTML5 Canvas?

时间:2012-05-25 15:55:01

标签: html5 internet-explorer canvas svg windows-runtime

目标:使用html5和JavaScript将CSS过滤器应用于视频。

约束:解决方案必须 Internet Exporer 10(适用于Windows 8)兼容。我正在制作一个Metro应用程序。

到目前为止: 我有一个<video>我正在加注<canvas>。我以为我可以直接对此应用CSS过滤器(例如invertbrightness),但事实证明这些过滤器与IE10不兼容。

思考:我希望有一种方法可以将SVG过滤器应用到画布上。这可能吗?我是否需要将<canvas>复制到<image>并对其应用过滤器?或者,是否应该有一种方法将画布包裹在<foreignObject>

感谢您的帮助!

以下是一些感兴趣的代码:

filters.svg:

<?xml version="1.0" standalone="no"?>
<svg width="1" height="1" version="1.1"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
  <defs>
    <filter id="blur">
      <feGaussianBlur in="SourceGraphic" stdDeviation="2 3" />
    </filter>
  </defs>
</svg>

的style.css:

.a {
    filter: url(filter.svg#blur);
    -ms-transform: matrix(-1, 0, 0, 1, 0, 0);
}

page.html中:

<div class="itemtemplate" data-win-control="WinJS.Binding.Template">
            <canvas class="a" style="width: 180px;height:180px;margin-bottom: -5px;" data-win-bind="style.backgroundColor: bc; id: effectId" />
</div>

以下代码正常工作,尽管速度很慢,但仍能实现我的目标。谢谢,安东尼!

<html>
<head>

</head>
<body>
<svg id="svgroot"  viewbox="0 0 800 800" width="800" height="800"  preserveAspectRatio="xMidYMin">
    <defs>
<filter id="myHueRotate">
<feColorMatrix type="hueRotate" values="270"/>
</filter>
</defs>
<image id="a" filter="url(#myHueRotate)"  x="0" y="0" width="300" height="300" />
<image id="b" filter="url(#myHueRotate)"  x="300" y="0" width="300" height="300" />
<image id="c" filter="url(#myHueRotate)"  x="0" y="300" width="300" height="300" />
<image id="d" filter="url(#myHueRotate)"  x="300" y="300" width="300" height="300" />
</svg>
<canvas id="canvas" height="300" width="300"></canvas>
<video id="vid" src="movie.m4v" height="300" width="300" style="display: none" autoplay/>


<script>
  var ctx = document.getElementById('canvas').getContext('2d');
  var img = new Image();
  img.src = 'img.jpg';
  img.onload = function(){
    //ctx.drawImage(img,0,0);
    //var canvasImage = canvas.toDataURL("image/png");
    //var svgImage = document.getElementById('a');
    //svgImage.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", canvasImage);
    draw();
  }
img.load();

function draw(){
    var ctx = document.getElementById('canvas').getContext('2d');
    var vid = document.getElementById('vid')
    ctx.drawImage(vid,0,0,300,300);
    var canvasImage = canvas.toDataURL("image/png");
    document.getElementById('a').setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", canvasImage);
    document.getElementById('b').setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", canvasImage);
    document.getElementById('c').setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", canvasImage);
    document.getElementById('d').setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", canvasImage);
    setTimeout(draw,40);
}
</script>
</body>
</html>

1 个答案:

答案 0 :(得分:6)

首先,文章阅读:

moving-to-standards-based-web-graphics-in-ie10

特别注意以下部分:

  

使用SVG,而不是VML

  

使用CSS3,而不是DX过滤器

在第二部分,他们提到:

  

DX过滤器与SVG过滤器效果不同,但两者都使用CSS属性名称过滤器。

第二篇文章:

Introduction to Filters and Transitions

他们给出了一个如何使用invert的具体示例,但是,假设它是IE中的 方式,我可以看到为什么它不容易找到并且可能或者可能不适合你的情况。但css将是:

#yourTargetElement {
     filter: DXImageTransform.Microsoft.BasicImage(invert=1);
}

他们没有提到亮度,但他们确实提到了其他几个过滤器和转换,第一篇文章提到了使用SVG。更多细节(希望有用的):

SVG Filter Effects in IE10

这看起来像关键的第1部分:

  

过滤器通过filter属性以filter =“url(#filterId)”的形式应用于SVG元素,或者可以将其应用为CSS属性过滤器:url(#filterId)

这是第2部分:

  

有16种不同的过滤器原语。

现在,我相信他们所提到的16是SVG的全套,但是知道MS,它也可能意味着:

  1. 这些是我们支持的16,或
  2. 这些是我们发明的16个,以便继续我们的声明,使IE标准兼容和SVG / MathML友好,但使它比任何其他浏览器更难...因为我们可以。
  3. 或者,引用Lily Tomlin的话:“我们不在乎,我们没有......我们是电话公司。”

    但是,假设MS终于意识到他们需要赶上来,进一步阅读16个原始过滤器,据说你只需要嵌入式SVG,过滤器位于正确的位置(defs)并通过CSS。以下是他们的一个例子(由我稍作修改和简化):

    HTML w / Embedded SVG:

    <div id="svg_wrapper">
    <svg xmlns="http://www.w3.org/2000/svg" id="svgroot" viewBox="0 0 800 533" preserveAspectRatio="xMidYMin">
        <defs>
         <filter id="filtersPicture">
                 <feComposite operator="arithmetic" k1="0" k2="1" k3="0" k4="0" 
                   in="SourceGraphic" in2="SourceGraphic" result="inputTo_6">
                 </feComposite>      
                 <feColorMatrix type="saturate" id="filter_6" values="2" 
                                data-filterId="6">
                 </feColorMatrix>
                 </filter>
       </svg>
      </div>
    

    CSS(他们使用JS使其变得动态,所以要小心):

    <style type="text/css">
         #yourTargetElement{
                 filter:url(#filtersPicture);
          }
     </style>
    

    我告诫他们看起来“简单”的原因是因为他们通过js和互动形式添加风格(也许你有同样的想法),但我认为这与调用相同的风险脚本在DOM之前的一个元素,因为它找不到过滤器并抛出错误。因此,请确保您想要保持简单(非动态)并且事情仍然无效,尝试将过滤器/ svg放在样式上方(即使这会导致闪烁)。