中秋节,用SVG滤镜来实现“海上生明月”吧

1,273 阅读3分钟

我正在参加中秋创意投稿大赛,详情请看:中秋创意投稿大赛

中秋佳节来临,中秋月圆,你我都在天涯共相望,寄月相思。借着此情此景我们用CSS可以来画一幅“海上生明月”,刚好前不久看到一篇文章是关于feTurbulence滤镜的,里面的水波纹效果很适合拿来做“海上生明月”效果图。

首先我们来了解一下feTurbulence滤镜是什么,怎么用?

feTurbulence简单来说就是SVG的一款滤镜,我们可以用这款神奇的滤镜做出流动的水,飘动的云,纸张纹理等等,具体见MDN。它有以下几个具体的属性:

  • baseFrequency
  • numOctaves
  • seed
  • stitchTiles
  • type

1、baseFrequency

baseFrequency表示噪声的频率,默认值为0,频率越高,噪声越密集。例baseFrequency="0.025"它的值为一个时,该值同时应用于水平方向x和竖直方向y的频率,例baseFrequency="0.025 0.1"有两个值时分别对应不同方向的频率。

<svg width="400" height="110">
  <filter id="noise1">
    <feTurbulence baseFrequency="0.025" />
  </filter>
  <filter id="noise2">
    <feTurbulence baseFrequency="0.05" />
  </filter>
  <rect x="0" y="0" width="100" height="100" style="filter: url(#noise1);" />
  <rect x="140" y="0" width="100" height="100" style="filter: url(#noise2);" />
</svg>

运行结果如下:

image.png

2、numOctaves

numOctaves表示倍频,倍频程数越高,噪声看起来越自然。它的默认值为1,类型为integer,不能是负数。

<svg width="400" height="110">
  <filter id="noise1">
    <feTurbulence baseFrequency="0.02" numOctaves="1"  />
  </filter>
  <filter id="noise2">
    <feTurbulence baseFrequency="0.02" numOctaves="4"  />
  </filter>

  <rect x="0" y="0" width="100" height="100" style="filter: url(#noise1);" />
  <rect x="140" y="0" width="100" height="100" style="filter: url(#noise2);" />
</svg>

运行结果如下:

image.png

3、seed

seed表示feTurbulence滤镜效果中伪随机数生成的起始值,seed不会改变噪声的频率和密度,改变的是噪声的形状和位置。

<svg width="400" height="110">
  <filter id="noise1">
    <feTurbulence baseFrequency="0.02" seed="1" />
  </filter>
  <filter id="noise2">
    <feTurbulence baseFrequency="0.02" seed="16" />
  </filter>

  <rect x="0" y="0" width="100" height="100" style="filter: url(#noise1);" />
  <rect x="140" y="0" width="100" height="100" style="filter: url(#noise2);" />
</svg>

运行结果:

image.png

4、stitchTiles

stitchTiles表示Perlin噪声在边框处的处理方式,它有两个属性值noStitchstitchnoStitch为默认值,表示SVG中有多个元素同时使用了feTurbulence滤镜效果的图块边界处没有平滑过渡,有明显的边界线。stitch表示会自动调整x值和y值,让下一个噪声图应用上一个噪声图的宽高等,使得边界平滑过渡。

image.png

5、type

type表示feTurbulence滤镜的显示效果类型,有turbulence(默认值,湍流、混乱效果)和fractalNoise(分形噪声效果)两个属性值。

<svg width="400" height="110">
  <filter id="noise1">
    <feTurbulence baseFrequency="0.02" type="turbulence" />
  </filter>
  <filter id="noise2">
    <feTurbulence baseFrequency="0.02" type="fractalNoise"/>
  </filter>

  <rect x="0" y="0" width="100" height="100" style="filter: url(#noise1);" />
  <rect x="140" y="0" width="100" height="100" style="filter: url(#noise2);" />
</svg>

运行结果: image.png

好了,了解完了我们开始动手吧!

1. 找几张图片(星空,月亮,大海),写css让他们摆成这个样子,形成一个对称

image.png 如果你的月亮没有月光,可以给月亮设置box-shadow: 0px 0px 70px 0.5px #fffdca;,同时海里的月亮用filter: blur(1px)模糊一下,显得更自然。

2. 既然是“海上生明月”,就要让月亮动起来,css给月亮设置动画效果

/* 天上月 */
.num1 {
  top: 40px;
  right: 110px;
  animation:firstmoon 10s;
}
/* 海底月 */
.num2 {
  bottom: 50px;
  right: 110px;
  animation:secondmoon 10s;
}
@keyframes firstmoon
{
    from { top: 200px;}
    to {top: 40px;}
}
@keyframes secondmoon
{
    from { bottom: 190px;}
    to {bottom: 50px;}
}

3. 现在月亮完成“升”这个过程了,我们来点大海的波浪吧,可以用我们刚学到的关于feTurbulence的相关属性。

<svg width="0" height="0">
  <filter id="picimg">
      <feTurbulence baseFrequency="0.01 0.1" type="turbulence" seed="4"></feTurbulence>
      <feDisplacementMap in="SourceGraphic" scale="20"/>
  </filter>
</svg> 

注意这里需要使用feDisplacementMap滤镜把静态的大海图片映射到图像上哦,更多关于feDisplacementMap滤镜请见MDN。

4. 大海波浪有了,接下来让它动起来吧,给SVG中加上animate

<animate attributeName="baseFrequency" dur="25s" keyTimes="0;0.3;0.7;1" values="0.01 0.08;0.02 0.13;0.01 0.09;0.01 0.11" repeatCount="indefinite"></animate>

现在让我们来看看最后的成果吧,完整代码

海上升明月.gif

参考:巧用CSS filter,让你的网站更加酷炫!SVG feTurbulence滤镜深入介绍

掘金处女之作,如果文中有不对的地方欢迎批评指教,如果你对本文感兴趣,可否点个赞再走呢(其实是想要这次活动的杯子,哈哈哈),最后提现祝大家中秋节快乐!!!