一起画只百度熊吧

起因

  • 第三节Css大会上(PPT)看到了微信 方潇仪 工程师分享的关于 svg动画的相关知识
  • 刚刚拿到百度实习offer (/∇\
  • 喜欢萌萌的百度熊

样式

思路

原理

其实方潇仪 也提到了,就是利用SVG 的filter标签,让两个圆高斯模糊后的边缘处虚化后再将两个源合并。

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="0" height="0">
    <defs>
        <filter id="gooey">
            <feGaussianBlur in="SourceGraphic" stdDeviation="10" result="step1"/>
            <feColorMatrix in="step1" mode="matrix" values="
                1 0 0 0 0
                0 1 0 0 0
                0 0 1 0 0  
                0 0 0 19 -9" result="step2" />
            <feComposite in="SourceGraphic" in2="step2" operator="atop"/>
        </filter>
    </defs>
</svg>

其中 我们可以想像 每一步都是一个图层,每一个标签都是一个处理工具。

in 属性将图层输入 result 将结果输出,但是不会将原来的图层改变,只会增加一个新的图层。

那么实际上就很明显了。

我们使用 feGaussianBlur 高斯模糊将原图层 模糊 10个单位 然后使用 feColorMatrix 调节图层整体对比度,让其回归清晰。

再将之前未处理过的图层和处理好的图层进行合并(feComposite),让原来图层上的图标、文字等能够清晰显现(因为经过高斯模糊处理所以文字图标都没了)。

然后我们把处理过的图层对其进行引用:

.nose {
    ...
    filter: url(./baidu_beer.html#gooey);
}

@彦子 同学 和 @大漠 老师对SVG研究的十分透彻和深入 大家可以去看 W3cplus SVG 标签下的相关内容

布局

filter 只能影响被设置的元素,以及其下的子元素。

如果设置过多的filter 又会使性能下降,所以我们将需要粘性变形的布局进行嵌套:

<div class="nose">
    <div class="nose-be"></div>
    <div class="nose-mi"></div>
    <div class="nose-af"></div>

    <div class="l-eye-wrap">
        <div class="eye eye-be"></div>
        <div class="eye eye-mi"></div>
        <div class="eye eye-af"></div>

        <div class="l-eye-face"></div>
        <div class="l-ear-wrap">
            <div class="ear l-ear">
                <div class="ear-hole l-ear-hole"></div>
                <div class="ear-hole-mask l-ear-hole-mask"></div>
            </div>
        </div>
    </div>

    <div class="r-eye-wrap">
        <div class="eye eye-be"></div>
        <div class="eye eye-mi"></div>
        <div class="eye eye-af"></div>
        <div class="r-eye-face"></div>
        <div class="r-ear-wrap">
            <div class="ear r-ear">
                <div class="ear-hole r-ear-hole"></div>
                <div class="ear-hole-mask r-ear-hole-mask"></div>
            </div>
        </div>
    </div>
</div>

这样布局的好处:

  • 给根元素添加粘性滤镜之外就能使所有的子元素都有粘性的效果
  • 方便我们对动画进行分割,从动画中我们也可以看出来,动画是先从鼻子先变化,然后出来两个眼睛,然后眼睛再分别出来耳朵,层层分割,让我们便于使用JS 进行控制

流程控制

不得不说,Promise 真的很好用。我们可以使用Promise 模拟一个 Sleep函数:

function Sleep(timeout) {
    return new Promise(function(resolve) {
        setTimeout(function () {
            resolve();
        },timeout);
    });
}

这样就可以使用Promise 很好的对动画进行控制

 let process = Promise.resolve();

  process.then(() => {
      oNose.classList.add('show');
      return Sleep(600);
  })
  .then(() => {
      oFace.classList.add('show');
      return Sleep(600);
  })
  .then(() => {
      oFace.classList.add('face-mor');
      oHeader.classList.add('show');
      return Sleep(600);
  })
  .then(() => {
      oNose.classList.add('nose-mor');
      oLeyeWrap.classList.add('l-eye-wrap-mor');
      oReyeWrap.classList.add('r-eye-wrap-mor');
      return Sleep(300);
  })

    ...

大家可以看出, 通过 很多个then 将一个连续的动画分割成了很多小的部分,通过控制class并配合 transitionkeyframes animation ,我们就能画出这只萌萌哒的百度熊。

源代码

想深入研究其他细节的同学,请参照源码。喜欢该效果的朋友可以不要吝惜您的star哦~

Owen

大三码农,对新技术有着强烈的热爱,喜欢 W3cplus 这样前沿的前端研究平台,希望在这里能够学到更多有意思的东西, Long May The Sunshine~。

如需转载,烦请注明出处:https://www.w3cplus.com/svg/bear-animation-width-svg.html

返回顶部