嘿,我在你的网站上展示了很多商业图标。我想添加与它们相关的酷动画。我想让图标保持灰色,直到你把它们悬停。然后他们慢慢地变成了有色人种。首先我用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" />
动画化css过滤器标签是不可靠的,应该避免。还有其他方法可以让SVG滤镜动画化,所以不用担心
在我开始之前,我想指出你代码中的一个与解决方案无关的缺陷,但希望你能从中吸取教训:
您已经将SVG设置为position: absolute;
并给它一个大小,以便它呈现在其他内容的顶部。这是混淆的::hover
伪选择器。为SVG添加visibility: hidden;
样式以消除闪烁
现在来看解决方案。在HTML中有很多方法可以使元素动画化。最常见的是javascript/jQuery和CSS动画/过渡。在几乎所有情况下,CSS动画和过渡应该是足够的,但有一些CSS属性是不支持的,会立即改变,而不是过渡。在这种情况下,幸运的是我们可以使用SVG动画
SVG动画允许我们更改SVG过滤器的属性。在此之前,我们应该简化SVG过滤器的代码,以便我们可以动画单个属性。
img {
-webkit-filter: url(#gray-filter);
filter: url(#gray-filter);
}
<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" />
如果你运行上面的代码,你应该得到一个灰色的显示。我们通过使用颜色矩阵来创建它。我们根据像素的alpha属性设置红色,绿色和蓝色组件。
现在我们可以添加一个SVG动画$('#my-img').on('click',function(oEvent) {
$('#gray-filter-anim-in')[0].beginElement();
});
#my-img {
-webkit-filter: url(#gray-filter);
filter: url(#gray-filter);
}
<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" />
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"
,我们告诉动画在持续时间结束时停止,而不是将过滤器恢复到其初始属性。
下面是实现动画淡入和淡出的完整代码
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);
#my-img {
-webkit-filter: url(#gray-filter);
filter: url(#gray-filter);
border: 1px solid black;
}
<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" />
请注意:我删除了动画的from属性和endElement方法调用,这样如果你在图像褪色时将鼠标移出图像,它将不会跳转。我还为图片添加了边框这样你就可以看到当你把鼠标放在它上面
我在下面的博客文章中找到了所有这些信息https://satreth.blogspot.co.za/2013/01/animating-svg-filters.html
好运这里有一种方法可以达到你想要的效果。
我使用图像的两个副本。下面那个灰色的。当你把鼠标悬停在上方时,它会淡入画面。
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;
}
<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>