动画/过渡svg过滤图像元素

时间:2016-09-01 20:11:56

标签: css svg css-transitions css-animations transition

嘿,我在你的网站上显示了很多商业图标。我想添加与它们相关的炫酷动画。我认为图标会保持灰色,直到你将它们悬停。然后他们慢慢变色。首先我用filter: grayscale(100%)做了这个效果。但是这些图标有不同的灰色阴影,看起来很糟糕。然后我找到了一个svg过滤器,如下所示。不幸的是,我不知道如何为此过滤器设置过渡效果的动画。因此,我正在寻找帮助以使这个动画工作或以其他方式实现这种效果。



img {
  -webkit-filter: url(#gray-filter);
  filter: url(#gray-filter);
  transition: filter 2s;
  -webkit-transition: filter 2s;
}
img:hover {
  -webkit-filter: none;
  filter: none;
}

<svg style="position: absolute; width: 140px; height: 140px;">
  <defs>
    <filter id="gray-filter">
      <feColorMatrix type="luminanceToAlpha" result="L2A"></feColorMatrix>
      <feFlood flood-color="#b3b4bd" result="colorfield"></feFlood>
      <feBlend mode="multiply" in="L2A" in2="colorfield"></feBlend>
      <feComposite operator="in" in2="SourceGraphic"></feComposite>
    </filter>
  </defs>
</svg>
<img src="http://iconshow.me/media/images/logo/brand-logo-icon/png/128/cocacola-128.png" />
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:6)

动画css过滤器标签充其量是不可靠的,应该避免。还有其他动画SVG过滤器的方法,所以不用担心

在开始之前,我想指出代码中与解决方案无关的缺陷,但希望您可以从中学习:

您已将SVG设置为position: absolute;并为其指定大小,以便在其他内容之上呈现。这对::hover伪选择器来说很困惑。将visibility: hidden;样式添加到SVG以消除闪烁

现在解决方案。在HTML中有很多动画元素的方法。最常见的是javascript / jQuery和CSS动画/过渡。几乎在每种情况下,CSS动画和过渡都应该足够,但是有些CSS属性不受支持,并且会立即改变而不是转换。在这种情况下,幸运的是我们可以使用SVG动画

SVG动画允许我们更改SVG过滤器的属性。在我们这样做之前,我们应该简化您的SVG过滤器代码,以便我们可以为单个属性设置动画。

&#13;
&#13;
img {
  -webkit-filter: url(#gray-filter);
  filter: url(#gray-filter);
}
&#13;
<svg style="position: absolute; width: 128px; height: 128px; visibility: hidden;">
  <defs>
    <filter id="gray-filter">
      <feColorMatrix type="matrix" values="0 0 0 0.6 0  0 0 0 0.6 0  0 0 0 0.6 0  0 0 0 1 0"></feColorMatrix>
    </filter>
  </defs>
</svg>
<img src="http://iconshow.me/media/images/logo/brand-logo-icon/png/128/cocacola-128.png" />
&#13;
&#13;
&#13;

如果您运行上面的代码,您应该获得灰色显示。我们使用颜色矩阵创建了这个。我们根据像素的alpha属性设置红色,绿色和蓝色组件。

现在我们可以添加一个SVG动画

&#13;
&#13;
$('#my-img').on('click',function(oEvent) {
  $('#gray-filter-anim-in')[0].beginElement();
});
&#13;
#my-img {
  -webkit-filter: url(#gray-filter);
  filter: url(#gray-filter);
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<svg style="position: absolute; width: 128px; height: 128px; visibility: hidden;">
  <defs>
    <filter id="gray-filter">
      <feColorMatrix type="matrix" values="0 0 0 0.5 0  0 0 0 0.5 0  0 0 0 0.5 0  0 0 0 1 0">
        <animate id="gray-filter-anim-in"  attributeName="values" attributeType="XML" begin="indefinite" dur="2" end="indefinite" from="0 0 0 0.5 0  0 0 0 0.5 0  0 0 0 0.5 0  0 0 0 1 0" to="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 1 0" fill="freeze" />
      </feColorMatrix>
    </filter>
  </defs>
</svg>
<img id="my-img" src="http://iconshow.me/media/images/logo/brand-logo-icon/png/128/cocacola-128.png" />
&#13;
&#13;
&#13;

必须在另一个定义中声明SVG动画(在这种情况下,我们希望设置动画的滤镜元素)。它具有以下属性

attributeName = The property name on the filter that will be changing
attributeType = "XML"
begin         = The time offset until the animation begins. Indefinite stops it from triggering automatically so we can trigger it
end           = The time offset until the animation ends
dur           = The time duration the animation will run for. Default unit is seconds
from          = The value of the filter's property at the start of the animation
to            = The value of the filter's property at the end of the animation

如果我们访问动画DOM对象,我们可以通过调用其beginElement方法来触发动画。要结束动画,请调用endElement方法。通过设置fill="freeze"我们告诉动画在持续时间结束时停止,而不是将过滤器恢复为其初始属性。

以下是实现动画淡入和动画淡出的完整代码

&#13;
&#13;
var fFadeIn = function(oEvent) {
  document.getElementById('gray-filter-anim-in').beginElement();
};

var fFadeOut = function(oEvent) {
  document.getElementById('gray-filter-anim-out').beginElement();
};

$('#my-img').hover(fFadeIn,fFadeOut);
&#13;
#my-img {
  -webkit-filter: url(#gray-filter);
  filter: url(#gray-filter);
  border: 1px solid black;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<svg style="position: absolute; width: 128px; height: 128px; visibility: hidden;">
  <defs>
    <filter id="gray-filter">
      <feColorMatrix type="matrix" values="0 0 0 0.5 0  0 0 0 0.5 0  0 0 0 0.5 0  0 0 0 1 0">
        <animate id="gray-filter-anim-in" attributeName="values" attributeType="XML" begin="indefinite" dur="0.5" end="indefinite" to="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 1 0" fill="freeze" />
        <animate id="gray-filter-anim-out" attributeName="values" attributeType="XML" begin="indefinite" dur="0.5" end="indefinite" to="0 0 0 0.5 0  0 0 0 0.5 0  0 0 0 0.5 0  0 0 0 1 0" fill="freeze" />
      </feColorMatrix>
    </filter>
  </defs>
</svg>
<img id="my-img" src="http://iconshow.me/media/images/logo/brand-logo-icon/png/128/cocacola-128.png" />
&#13;
&#13;
&#13;

请注意:我删除了动画的from属性和endElement方法调用,这样如果你在图像褪色时将鼠标移出图像,它就不会跳转。我还为图像添加了边框,以便您可以看到鼠标悬停在它上面

我在下面的博客文章中找到了所有这些信息 https://satreth.blogspot.co.za/2013/01/animating-svg-filters.html

祝你好运

答案 1 :(得分:1)

这是实现所需效果的一种方法。

我使用了两张图片副本。底部是灰色的。当你盘旋时,未经过滤的顶部会消失。

&#13;
&#13;
img.grey {
  -webkit-filter: url(#gray-filter);
  filter: url(#gray-filter);
  opacity: 1;
  transition: filter 2s;
  -webkit-transition: filter 2s;
}

img.real {
  opacity: 0;
  transition: opacity 2s;
  -webkit-transition: opacity 2s;
}

img.real:hover {
  opacity: 1;
  transition: opacity 2s;
  -webkit-transition: opacity 2s;
}

.fader {
  position: relative;
}

.fader img {
  position: absolute;
}
&#13;
<svg style="position: absolute; width: 140px; height: 140px;">
  <defs>
    <filter id="gray-filter">
      <feColorMatrix type="luminanceToAlpha" result="L2A"></feColorMatrix>
      <feFlood flood-color="#b3b4bd" result="colorfield"></feFlood>
      <feBlend mode="multiply" in="L2A" in2="colorfield"></feBlend>
      <feComposite operator="in" in2="SourceGraphic"></feComposite>
    </filter>
  </defs>
</svg>
<div class="fader">
  <img class="grey" src="http://iconshow.me/media/images/logo/brand-logo-icon/png/128/cocacola-128.png" />
  <img class="real" src="http://iconshow.me/media/images/logo/brand-logo-icon/png/128/cocacola-128.png" />
</div>
&#13;
&#13;
&#13;