【问题标题】:Apply SVG Filter to HTML5 Canvas?将 SVG 过滤器应用于 HTML5 画布?
【发布时间】:2012-06-01 05:26:58
【问题描述】:

目标:使用 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>

【问题讨论】:

  • 我建议先尝试将画布或视频嵌入到SVG 直接通过&lt;foreignObject&gt; 看看你是否可以获得过滤器来应用它。但首先:您是否验证过 IE10 完全支持您想要的 SVG 过滤器,即使是在静态图像上?
  • 很遗憾 IE9/10 不支持&lt;foreignObject&gt;
  • @RobertLongson - IE10 确实支持通过 CSS 调用 SVG 过滤器,所以有希望。和IE9一样,它承诺最终会被赶上,现在与IE7和IE8一样,除非你的老板拒绝升级,否则无关紧要。阅读我在回答中引用的 Ma Bell 名言。除非我们作为开发人员不再担心 IE 用户(我知道这很难),否则他们将永远支持我们,而这显然应该是 4 种主要替代品和更好的浏览器。
  • 我想知道 Internet Exporer 是不是故意的失误? ;)

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


【解决方案1】:

首先,要阅读的文章:

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 属性应用于 SVG 元素,形式为 filter="url(#filterId)",或者可以作为 CSS 属性 filter:url(#filterId)

这是第 2 部分:

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

现在,我相信他们所指的 16 个是完整的 SVG 集,但了解 MS,它也可能意味着:

  1. 这些是我们支持的 16 个,或者
  2. 这些是我们发明的 16 个,以继续我们的声明,即使 IE 标准兼容和 SVG/MathML 友好,但比在任何其他浏览器中更难...因为我们可以。李>

或者,引用 Lily Tomlin 的话:“我们不在乎,我们不必……我们是电话公司。”

但是,假设 MS 最终意识到他们需要赶上,进一步阅读 16 个原始过滤器,假设您只有嵌入的 SVG,过滤器位于正确的位置 (defs) 并通过 css 调用它们。这是他们的一个例子(我稍作修改和简化):

带有嵌入式 SVG 的 HTML:

<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 中之前,因为它找不到过滤器并引发错误。因此,请确保如果您想保持简单(非动态)并且事情仍然无法正常工作,请尝试将 filter/svg 放在样式上方(即使这会导致闪烁)。

【讨论】:

  • 感谢安东尼的帮助!我根据您的回答编辑了我的问题。我基本上拍摄视频,每秒将其复制到画布 25 次,将画布复制到数据 url,然后将每个图像的 src 设置为该 url。 (然后将 SVG 应用于图像)。有没有更好的方法来做到这一点?即使是一个视频也很慢,我希望能够同时制作 9 个视频(要求有点多,我知道)。我的方法基本上是你推荐的吗?
  • 老实说,自从我迁移到 Linux/Mac 后,我就不再使用 IE。我可能仍然会用它来测试它是否是一个选项,但幸运的是它不是。所以你说你在加载每个图像时都在应用 svg 过滤器,你不确定这是否是它变慢的原因,或者你想知道你是否正在使用滚动渲染方法视频逐帧是瓶颈?我倾向于使用后者,因为我只能想象获取每一帧的数据 url 是内存谋杀。我什至不知道这是画布的一个选项。您使用的是 base64 数据 URL 还是临时 URL?
  • 最后一个问题是基于这样的假设,即 IE/JS 处理生成类似于 HTML5 文件 API 的 base64 数据 URL,它提供了完整的数据 URL(它很大并且可能会减慢速度输出它)和一个临时 url(这是一个简短的本地 url,基本上指向数据被缓存的位置)。后者也更快,因为它不必预先加载和读取整个文件来生成 base64。不确定这是否是您使用的画布技术的一个选项,但要深入挖掘的关键字是“对象 URL”与“数据 URL”(后者是 base64)。
猜你喜欢
  • 2016-12-03
  • 2013-06-07
  • 2014-03-29
  • 2020-07-09
  • 2013-01-02
  • 2013-04-05
  • 2014-07-05
  • 2018-03-13
  • 1970-01-01
相关资源
最近更新 更多