【问题标题】:SVG filter with CSS transitions带有 CSS 过渡的 SVG 过滤器
【发布时间】: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

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

【问题讨论】:

    标签: html css animation svg css-transitions


    【解决方案1】:

    SVG 滤镜有一个定义的“滤镜区域”,在其中应用效果。这是因为某些操作可能非常慢(例如高斯模糊),并且您通常希望限制计算它们的区域。

    一个过滤器的默认过滤区域是:

    x="-10%" y="-10%" width="120%" height="120%"
    

    换句话说,被过滤的元素,加上一个 10% 的边框围绕它的外部。该区域之外的任何内容都将被剪裁(并且不可见)。

    解决方案是增加过滤器区域,使其包含所有 blob。因此,例如,如果我们将边距提高到 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>

    【讨论】:

      【解决方案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%。

      【讨论】:

        猜你喜欢
        • 2015-09-17
        • 2013-01-30
        • 2014-11-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-01-09
        • 2019-11-01
        • 2016-08-10
        相关资源
        最近更新 更多