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.