带有 CSS 过渡的 SVG 过滤器
Posted
技术标签:
【中文标题】带有 CSS 过渡的 SVG 过滤器【英文标题】:SVG filter with CSS transitions 【发布时间】:2017-12-22 03:23:01 【问题描述】:我正在使用 css 动画进行 svg 过滤。我用
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<filter id="goo">
<feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur" />
<feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 18 -7" result="goo" />
<feComposite in="SourceGraphic" in2="goo" operator="atop"/>
</filter>
</defs>
</svg>
和
filter:url('#goo');
用于 CSS 中的容器。
这是一个小提琴 https://codepen.io/sergey_mell/pen/MoRMwR
我陷入了下一个问题。动画似乎在某个盒子内执行(它的大小似乎取决于初始动画状态大小)。 谁能帮我避免这种情况?
【问题讨论】:
【参考方案1】:SVG 滤镜有一个定义的“滤镜区域”,在其中应用效果。这是因为某些操作可能非常慢(例如高斯模糊),并且您通常希望限制计算它们的区域。
一个过滤器的默认过滤区域是:
x="-10%" y="-10%"
换句话说,被过滤的元素,加上一个 10% 的边框围绕它的外部。该区域之外的任何内容都将被剪裁(并且不可见)。
解决方案是增加过滤器区域,使其包含所有 blob。因此,例如,如果我们将边距提高到 50%
<filter id="goo" x="-50%" y="-50%" >
它现在可以正常工作了。
body
background:white;
background-image:url(https://i.imgur.com/d47ZIU3.jpg);
background-size:cover;
.blobs
filter:url('#goo');
position:absolute;
top:100px;
left:200px;
@keyframes blob-left-top-anim
0%
transform:scale(1.1) translate(0,0);
33%
transform:scale(0.9) translate(-65px,0);
62%
transform:scale(0.7) translate(-65px,-65px);
94%
transform:scale(1.1) translate(0,0);
@keyframes blob-right-top-anim
0%
transform:scale(1.1) translate(0,0);
33%
transform:scale(0.9) translate(65px,0);
64%
transform:scale(0.7) translate(65px,-65px);
96%
transform:scale(1.1) translate(0,0);
@keyframes blob-left-bottom-anim
0%
transform:scale(1.1) translate(0,0);
33%
transform:scale(0.9) translate(-65px,0);
66%
transform:scale(0.7) translate(-65px,65px);
98%
transform:scale(1.1) translate(0,0);
@keyframes blob-right-bottom-anim
0%
transform:scale(1.1) translate(0,0);
33%
transform:scale(0.9) translate(65px,0);
68%
transform:scale(0.7) translate(65px,65px);
100%
transform:scale(1.1) translate(0,0);
.blob
position:absolute;
background:#e97b7a;
left:50%;
top:50%;
width:100px;
height:100px;
line-height:100px;
text-align:center;
color:white;
font-size:40px;
border-radius:100%;
margin-top:-50px;
margin-left:-50px;
animation:blob-left-top-anim cubic-bezier(0.770, 0.000, 0.175, 1.000) 4s infinite;
.blob:nth-child(2)
animation-name:blob-right-top-anim;
.blob:nth-child(3)
animation-name:blob-left-bottom-anim;
.blob:nth-child(4)
animation-name:blob-right-bottom-anim;
<div class="blobs">
<div class="blob">4</div>
<div class="blob">3</div>
<div class="blob">2</div>
<div class="blob">1</div>
</div>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<defs>
<filter id="goo" x="-50%" y="-50%" >
<feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur" />
<feColorMatrix in="blur" mode="matrix" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 18 -7" result="goo" />
<feComposite in="SourceGraphic" in2="goo" operator="atop"/>
</filter>
</defs>
</svg>
【讨论】:
【参考方案2】:我实际上是通过将 width
/ height
设置为 .blobs
容器使其工作:
.blobs
filter:url('#goo');
position:absolute;
top:100px;
left:200px;
width: 500px;
height: 500px;
您可能会找到所需的最大尺寸并将其设置为该尺寸而不是 500。
【讨论】:
感谢您的帮助和快速解答!。我也找到了那个解决方案。但是,这对我来说似乎不太好,因为我不知道容器的大小,所以设置一些非常大的值或用容器覆盖整个身体似乎不太好......【参考方案3】:如果您没有明确调整替换元素(img、svg 等)的大小,那么浏览器会为其提供 300 像素 x 150 像素(或接近的值)的默认大小。如果您不知道大小,那么如果您需要精确的像素,则需要通过 javascript 设置它,或者如果您希望它填充其包含的元素,则需要 100%、100%。
【讨论】:
以上是关于带有 CSS 过渡的 SVG 过滤器的主要内容,如果未能解决你的问题,请参考以下文章
应用 CSS 过滤器时,内联 SVG 在 iOS 和 Safari 中消失
如何通过 CSS 将阴影过滤器应用于 SVG 特定元素/路径