SVG滤镜与CSS过渡

5

我正在使用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

我遇到了一个问题。动画似乎是在某个盒子内执行的(它的大小似乎取决于初始动画状态的大小)。 有谁能帮我避免这种情况?

3个回答

5
SVG滤镜有一个定义好的“过滤区域”,其中应用效果。这是因为某些操作可能非常缓慢(例如高斯模糊),通常希望限制它们计算的区域。
滤镜的默认过滤区域是:
x="-10%" y="-10%" width="120%" height="120%"

换句话说,被过滤的元素及其周围10%的边框。任何在该区域之外的内容都将被剪切(并且不可见)。
解决方法是扩大过滤区域,以包含所有的斑点。例如,如果我们将边距增加到50%。
<filter id="goo" x="-50%" y="-50%" width="200%" height="200%">

现在它的功能已经正常运作。

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%" width="200%" height="200%">
      <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>


1
如果您没有显式地为替换元素(img、svg等)设置大小,则浏览器会给它一个默认大小为300px x 150px(或接近此值)。如果您不知道大小,则需要通过JavaScript设置它以获得精确的像素,或者使用100%,100%来使其填充其包含元素。

1

我通过给 .blobs 容器设置 width / height,使其正常工作:

.blobs{
  filter:url('#goo');
  position:absolute;
  top:100px;
  left:200px;
  width: 500px;
  height: 500px;
}

你可以找出所需的最大尺寸,并将其设置为该尺寸,而不是500。

感谢您的帮助和快速回答!我也找到了那个解决方案。但是,对我来说似乎不太好,因为我不知道容器的大小,所以设置一些极大的值或用容器覆盖整个主体似乎都不太合适... - Sergey Mell

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接