Skip to main content

GOOD MOOD part 3: applying filters

· 4 min read

In the third part, I apply filters.


Applying fiters

I created filters with the filter element, which lives is inside the defs element. In this animation, I used the feTurbulence, feDisplacementMap and feGaussianBlur filters. I applied the filters by referencing their id attribute.

To maintain color consistency, I set the color-interpolation-filters="sRGB" attribute.

Distortion filter

To get the irregular drawing effect on the letters, I used a combination of feTurbulence and feDisplacementMap. I experimented with different values for the baseFrequency, numOctaves and scale attributes until I got a result that was close to the original animation on screens with different pixel ratios. I'll talk more about this in part 4.

The feTurbulence element generates an image using Perlin's Noise function (according to the type, baseFrequency, numOctaves and seed attributes), while the feDisplacementMap element uses the pixel values of the generated image (in2="turbulence") to spatially shift the animation (in="SourceGraphic").

The feTurbulence element's result attribute defines a name for the result, which can be referred to by the in or in2 attributes.

The feDisplacementMap element's scale attribute defines the scale factor, the smaller the number, the smaller the effect.

I wrapped the letters in a g element, and referenced the filter in it.

<!--   I omitted the div elements defined in part 2  to keep the code concise --><svg viewBox="0 0 63 51" color-interpolation-filters="sRGB">  <defs>    <filter id="distortion-filter">      <feTurbulence        type="turbulence"        baseFrequency="1"        numOctaves="2"        seed="0"        result="turbulence"      />      <feDisplacementMap        in="SourceGraphic"        in2="turbulence"        scale="0.3"      />    </filter>    <!--      I omitted the defs element's other elements      to keep the code concise     -->  </defs>  <!-- background -->  <rect width="63" height="51" fill="#000" />  <!-- letters -->  <g filter="url(#distortion-filter)">    <!--      I omitted the use elements      to keep the code concise     -->  </g></svg>

Animating the distortion filter

To create the "shaky" effect, I used the animate element inside the feTurbulence element to animate the seed attribute. In the interval of 1s, the seed attribute assumes values from 1 to 5.

<!--   I omitted other elements and attributes  to keep the code concise --><feTurbulence>  <animate    attributeName="seed"    from="1"    to="5"    dur="1s"    repeatCount="indefinite"  /></feTurbulence>

Gaussian blur filter

The animation isn't entirely sharp, so I applied a little bit of Gaussian blur.

In most browsers, the filter attribute can reference multiple filters: filter="url(#distortion-filter) url(#blur-filter)". However, this doesn't work in Safari, so I had to add one more g element wrapping existing one to apply the blur on top of the distortion.

Here the order also matters, in this case the blur effect should be applied on top of the distortion effect.

<!--   I omitted the div elements defined in part 2  to keep the code concise --><svg viewBox="0 0 63 51" color-interpolation-filters="sRGB">  <defs>    <filter id="blur-filter">      <feGaussianBlur        in="SourceGraphic"        stdDeviation="0.06"      />    </filter>    <!--      I omitted the defs element's other elements      to keep the code concise     -->  </defs>  <!-- background -->  <rect width="63" height="51" fill="#000" />  <!-- letters -->  <g filter="url(#blur-filter)">    <g filter="url(#distortion-filter)">      <!--        I omitted the use elements        to keep the code concise       -->    </g>  </g></svg>

Conclusion

Having the filters applied, I decided that the reproduction was done.

In the next part, I do some comparisons between browsers and pixel ratios: GOOD MOOD part 4: pixel ratio.

Recommended reading