【问题标题】:Is there any way of applying svg filter with specific shape?有什么方法可以应用具有特定形状的 svg 过滤器吗?
【发布时间】:2019-10-22 11:14:15
【问题描述】:

我正在尝试使用 svg 过滤器来获得漂亮的动画和效果。这是我刚刚发现的一个新世界,但我面临一个问题。 我试图重现这种效果:https://www.youtube.com/watch?v=GcSU4xH6_Ro
我不知道如何重现失真的圆圈。

我知道我可以使用过滤器和 svg,但实际上如果我将我的 svg 过滤器应用于框所有 div 都会受到影响,而不是这个圆圈。

我想知道是否可以让 svg 像“镜头”一样 如果你想看代码,我做了一个 jsFiddle:https://jsfiddle.net/wekhz7rb/

我想只用 CSS 来做这个

    <div class="box">
    <svg class="svg" xmlns="http://www.w3.org/2000/svg" id="effect"     
     width="275px" height="275px">
    <filter id="noise">
    <feTurbulence baseFrequency="0.05" numOctaves="2" result="noise">    
    </feTurbulence>
    <feComposite operator="in" in2="SourceGraphic"></feComposite>
    <feDisplacementMap in="SourceGraphic" in2="noise" scale="50">        
    </feDisplacementMap>
    </filter>
    <!-- <circle cx="137" cy="137" r="137" fill="red" filter="url(#noise)">            
    </circle> -->
    </svg>
    <div class="text">DREAMS</div>
    <div class="text">DREAMS</div>
    <div class="text">DREAMS</div>
    <div class="text">DREAMS</div>
    <div class="text">DREAMS</div>
    <div class="text">DREAMS</div>
    <div class="text">DREAMS</div>
    <div class="text">DREAMS</div>
    <div class="text">DREAMS</div>
    <div class="text">DREAMS</div>
    <div class="text">DREAMS</div>
    <div class="text">DREAMS</div>
    <div class="text">DREAMS</div>
    <div class="text">DREAMS</div>
    <div class="text">DREAMS</div>
    </div>
    @import url(//fonts.googleapis.com/css?family=Archivo+Black);
    body {
      display: flex;
      justify-content: center;
      align-items: center;
      flex-direction: column;
      background-color: #7427FF;
      height: 100vh;
      width: 100vw;
    }
    .box {
      height: 550px;
      width: 550px;
      position: relative;
      overflow: hidden;
      text-align: center;
      filter: url(#noise); 
   // mask: url(#effect);
    }
    .svg {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translateY(-50%) translateX(-50%);
    z-index: 10;
    }

.text {
  font-family: 'Archivo Black', sans-serif;
  display: inline-block;
  font-size: 116px;
  line-height: 90px;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  z-index: 0;
  background: linear-gradient(0deg, rgba(117,62,255,1) 0%, 
   rgba(249,37,166,1) 40%, rgba(246,154,180,1) 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  animation-name: translate;
  animation-timing-function: linear;
  animation-duration: 10s;
  animation-iteration-count: infinite;
  animation-fill-mode: backwards;

@for $i from 1 through 16 {
    &:nth-child(#{$i}) {
      animation-delay:  #{$i * 1}s
    }
  }
}

@keyframes translate {
  from {
     transform: translateY(-90px) translateZ(0)
  }
  to {
      transform: translateY(555px) translateZ(0)
  }
}

【问题讨论】:

    标签: html css animation svg


    【解决方案1】:

    是的,这是可能的。阅读feDisplacementMap 的工作原理。

    https://www.w3.org/TR/SVG11/single-page.html#filters-feDisplacementMapElement

    您所要做的就是确保圆外的像素导致位移为 0。为此,颜色通道值必须为 0.5 (128)。

    因此,如果 X 通道是红色通道,Y 通道是绿色通道,那么将圆圈外的区域设置为 50% 的黄色(即 #808000),应该会产生零位移。

    更新:feDisplacementMap 的工作原理

    feDisplacement 的工作原理是它从“置换贴图”(in2) 中获取一个像素值,并使用该像素的颜色通道确定in 图像顶部复制一个像素的其他位置。

    例如,假设我们当前正在查看像素 (100,200)。

    • 查看in2 中 (100,200) 处的像素
    • 确定位移偏移。可以说它是(-0.4,0.5)。稍后我们将看到如何获得这些值。
    • 将偏移量乘以scale。如果比例为10,则新的偏移量为 (-4, 5)
    • in 中获取(100 - 4, 200 - 5) 处的像素
    • 在输出 (result) 中将该像素值写入 (100,200)。

    计算偏移量

    首先查看in2 像素中的适当颜色通道(R、G、B 或 A)。用于 X 和 Y 偏移的颜色通道是使用 xChannelSelectoryChannelSelector 属性设置的。

    这些通道中的每一个都可以有一个从 0 到 255 的值。对于 R 通道,0 表示没有红色,255 表示全红色。为了计算偏移量,0..255 范围转换为 0..1 范围。

    +----------------------+------+------------+
    | Colour channel value | XC() | XC() - 0.5 |
    +----------------------+------+------------+
    |        0  (00)       |  0   |    -0.5    |
    |       26  (1A)       |  0.1 |    -0.4    |
    |      128  (80)       |  0.5 |     0      |
    |      255  (FF)       |  1   |     0.5    |
    +----------------------+------+------------+
    

    因此,如果xChannelSelector="R"yChannelSelector="G",那么in2 中的像素值#1AFF00 将导致我们上面使用的位移偏移量为(-0.4, 0.5)。

    返回特定形状的置换贴图

    从上面,希望您可以看到,如果in2 像素通道的值为128,那将导致零偏移。这意味着result 中的输出像素将直接从输入中的相同位置(in)复制。

    所以要创建一个带有圆形边界的地图。您所要做的就是将圆圈外的所有像素都设为128

    feDisplacementMap的问题

    过去几年为防止与feDisplacementMap 相关的一些安全问题所做的更改意味着它现在可能很难使用。 该过程仍然存在遗留错误。例如:https://bugs.chromium.org/p/chromium/issues/detail?id=798001

    另外还有feImage 的错误:例如。 https://bugzilla.mozilla.org/show_bug.cgi?id=455986

    您可能需要将外部图像与 feImage 一起使用,并确保您的 CORS 设置在您的网络服务器上正确。

    使用带有feImage 的数据URL 似乎也可以。见this CodePen from @enxaneta

    希望这会有所帮助。

    【讨论】:

    • 感谢您的回答。所以我阅读了w3的文档,但他并没有给我太多帮助。我想知道你是否有视觉示例?他可以提供很多帮助,而不仅仅是文本(我更擅长可视化)。我现在很迷茫,我什么都不懂
    猜你喜欢
    • 2018-09-17
    • 2020-02-18
    • 2015-05-10
    • 2021-01-04
    • 2021-02-02
    • 2018-03-16
    • 1970-01-01
    • 1970-01-01
    • 2019-11-01
    相关资源
    最近更新 更多