Javascript 我的SVG过滤器运行非常慢

Javascript 我的SVG过滤器运行非常慢,javascript,css,svg,svg-filters,Javascript,Css,Svg,Svg Filters,我有以下SVG过滤器: <svg style="visibility: hidden; height: 0; width: 0;"> <filter id="rgbShift"> <feOffset in="SourceGraphic" dx="1" dy="-1" result="text1" /> <feFlood flood-color="#FF0000" result="redColor" />

我有以下SVG过滤器:

<svg style="visibility: hidden; height: 0; width: 0;">
    <filter id="rgbShift">
        <feOffset in="SourceGraphic" dx="1" dy="-1" result="text1" />
        <feFlood flood-color="#FF0000" result="redColor" />
        <feComposite in="redColor" in2="text1" operator="arithmetic" k1="1" result="red" />
        <feOffset in="SourceGraphic" dx="-1" dy="2" result="text2" />
        <feFlood flood-color="#00FF00" result="greenColor" />
        <feComposite in="greenColor" in2="text2" operator="arithmetic" k1="1" result="green" />
        <feOffset in="SourceGraphic" dx="-2" dy="1" result="text3" />
        <feFlood flood-color="#0000FF" result="blueColor" />
        <feComposite in="blueColor" in2="text3" operator="arithmetic" k1="1" result="blue" />
        <feComposite in="red" in2="green" operator="lighter" result="rb" />
        <feComposite in="rb" in2="blue" operator="lighter" />
    </filter>
</svg>


该过滤器应用于我正在制作的游戏中的菜单屏幕。我想对游戏本身应用相同的过滤器,但运行速度非常慢,可能是因为页面上的元素几乎一直在移动。有没有办法让我的过滤器运行得更快?

虽然我没有正式的结果,但在Inkscape中的一张jpg图片上测试它给我的印象是,以下过滤器速度明显更快,但在数学上完全相同:

<filter id="rgbShift">
    <feOffset in="SourceGraphic" dx="1" dy="-1" />
    <feComponentTransfer result="red">
        <feFuncG type="discrete" tableValues="0" />
        <feFuncB type="discrete" tableValues="0" />
    </feComponentTransfer>
    <feOffset in="SourceGraphic" dx="-1" dy="2" />
    <feComponentTransfer result="green">
        <feFuncR type="discrete" tableValues="0" />
        <feFuncB type="discrete" tableValues="0" />
    </feComponentTransfer>
    <feOffset in="SourceGraphic" dx="-2" dy="1" />
    <feComponentTransfer result="blue">
        <feFuncR type="discrete" tableValues="0" />
        <feFuncG type="discrete" tableValues="0" />
    </feComponentTransfer>
    <feComposite in="red" in2="green" operator="arithmetic" k2="1" k3="1" result="rb" />
    <feComposite in="rb" in2="blue" operator="arithmetic" k2="1" k3="1" />
</filter>

这是否足够,我不知道。以下措施可能有助于避免时间关键型操作(即为每一帧重新计算过滤器):

  • 不要将过滤器应用于动画元素
  • 不要对图元应用过滤器,使其(过滤图元的边界框加上默认值,每个方向10%)与动画图元的边界框重叠。他们是高于还是低于并不重要

虽然我没有正式的结果,但在Inkscape中的单个jpg图片上测试它给我的印象是,以下过滤器速度明显更快,同时在数学上与AFAIK相同:

<filter id="rgbShift">
    <feOffset in="SourceGraphic" dx="1" dy="-1" />
    <feComponentTransfer result="red">
        <feFuncG type="discrete" tableValues="0" />
        <feFuncB type="discrete" tableValues="0" />
    </feComponentTransfer>
    <feOffset in="SourceGraphic" dx="-1" dy="2" />
    <feComponentTransfer result="green">
        <feFuncR type="discrete" tableValues="0" />
        <feFuncB type="discrete" tableValues="0" />
    </feComponentTransfer>
    <feOffset in="SourceGraphic" dx="-2" dy="1" />
    <feComponentTransfer result="blue">
        <feFuncR type="discrete" tableValues="0" />
        <feFuncG type="discrete" tableValues="0" />
    </feComponentTransfer>
    <feComposite in="red" in2="green" operator="arithmetic" k2="1" k3="1" result="rb" />
    <feComposite in="rb" in2="blue" operator="arithmetic" k2="1" k3="1" />
</filter>

这是否足够,我不知道。以下措施可能有助于避免时间关键型操作(即为每一帧重新计算过滤器):

  • 不要将过滤器应用于动画元素
  • 不要对图元应用过滤器,使其(过滤图元的边界框加上默认值,每个方向10%)与动画图元的边界框重叠。他们是高于还是低于并不重要

我不知道这是否是性能问题的原因,但feComposite是一个缓慢的操作,您的语法有很多错误

  • 在SVG 1.1中,feComposite没有“lighter”操作符。已添加到过滤器1.0规范中,但不支持跨浏览器。您可能需要使用feComposite operator=“算术”k2=“1”k3=“1”,我认为这是等效的
  • 使用feBlend/乘法通常比feComposite/算术更好,它似乎要快得多
我认为您需要的原始过滤器的正确实现如下所示:

<filter id="rgbShift">
    <feOffset in="SourceGraphic" dx="1" dy="-1" result="text1" />
    <feFlood flood-color="#FF0000" result="redColor" />
    <feBlend in="text1" in2="redColor" mode="multiply" result="red"/>
    <feOffset in="SourceGraphic" dx="-1" dy="2" result="text2" />
    <feFlood flood-color="#00FF00" result="greenColor" />
    <feBlend in="text2" in2="greenColor" mode="multiply" result="green"/>
    <feOffset in="SourceGraphic" dx="-2" dy="1" result="text3" />
    <feFlood flood-color="#0000FF" result="blueColor" />
    <feBlend in="text3" in2="blueColor" mode="multiply" result="blue"/>
    <feComposite in="red" in2="green" operator="arithmetic" k2="1" k3="1" result="rb" />
    <feComposite in="rb" in2="blue" operator="arithmetic" k2="1" k3="1"/>
</filter>

我不知道这是否是性能问题的原因,但feComposite是一个缓慢的操作,您的语法有很多错误

  • 在SVG 1.1中,feComposite没有“lighter”操作符。已添加到过滤器1.0规范中,但不支持跨浏览器。您可能需要使用feComposite operator=“算术”k2=“1”k3=“1”,我认为这是等效的
  • 使用feBlend/乘法通常比feComposite/算术更好,它似乎要快得多
我认为您需要的原始过滤器的正确实现如下所示:

<filter id="rgbShift">
    <feOffset in="SourceGraphic" dx="1" dy="-1" result="text1" />
    <feFlood flood-color="#FF0000" result="redColor" />
    <feBlend in="text1" in2="redColor" mode="multiply" result="red"/>
    <feOffset in="SourceGraphic" dx="-1" dy="2" result="text2" />
    <feFlood flood-color="#00FF00" result="greenColor" />
    <feBlend in="text2" in2="greenColor" mode="multiply" result="green"/>
    <feOffset in="SourceGraphic" dx="-2" dy="1" result="text3" />
    <feFlood flood-color="#0000FF" result="blueColor" />
    <feBlend in="text3" in2="blueColor" mode="multiply" result="blue"/>
    <feComposite in="red" in2="green" operator="arithmetic" k2="1" k3="1" result="rb" />
    <feComposite in="rb" in2="blue" operator="arithmetic" k2="1" k3="1"/>
</filter>


Inkscape为feComposite提供了一个
打火机
操作符。它遵循CSS feComposite和定义,因此
k1=k4=0
k2=k3=1
刚刚看到
打火机也在您的系统中实现,是正确的。我不知道过滤器1.0规范中添加了打火机。不过,我对规范的理解是operator=“lighter”是operator=“算术”k2=“1”k3=“1”的缩写,如果您使用“打火机”,则不必指定k?我可能错了。Inkscape为feComposite提供了一个
打火机
操作符。它遵循CSS feComposite和定义,因此
k1=k4=0
k2=k3=1
刚刚看到
打火机也在您的系统中实现,是正确的。我不知道过滤器1.0规范中添加了打火机。不过,我对规范的理解是operator=“lighter”是operator=“算术”k2=“1”k3=“1”的缩写,如果您使用“打火机”,则不必指定k?我可能错了。编辑以符合SVG 1.1 feComposite模式只是一个简短的说明-Edge中有一个bug(我认为Firefox中也有),您必须为type=“discrete”指定tableValues=“0”,编辑以符合SVG 1.1 feComposite模式只是一个简短的说明-Edge中有一个bug(我认为Firefox中也有)其中必须为type=“discrete”指定tableValues=“0”