© Alex Libby  2018
Alex LibbyBeginning SVGhttps://doi.org/10.1007/978-1-4842-3760-1_5

5. Creating Filters

Alex Libby1 
(1)
Rugby, Warwickshire, UK
 

Introduction

Take a look at this Codepen by the front-end developer Sean Free at https://codepen.io/seanfree/full/eBppyE/ . It paints an idyllic picture of a calm, barely shimmering lake, with snow-covered mountains rising in the background and forests in the distance. No signs of other people, no boats, no noise: sounds like the perfect advert for a travel brochure!

I’ll bet that, at first glance, you’d think that this is some sort of animated GIF image, or even a little trickery with video, right? After all, how could we achieve this animated effect…?

Well, what if I said there isn’t a single animated GIF or video being used? Yes, you heard me correctly – the only trickery we’re using is SVG filters. This is a great example of what we can achieve when working with SVG: granted, this demo uses a little JavaScript and the GSAP library, but it is still nevertheless a wonderful example of the art of possible with SVG filters. We’ll explore how to use GSAP later in Chapter 9, “Incorporating SVG Libraries,” but for now let’s wind things back and take a look at why we can benefit from using SVG filters.

The Benefits of Using SVG Filters

So – why would we want to use SVG filters, if many of the effects we might need, can be provided using standard CSS filters? This question is particularly valid, as most CSS filters are merely shortcuts derived from SVG – why go to all that extra effort?

Well, the answer is simple – control. Yes, using an SVG filter gives us far more control over how an image or SVG graphic will look, than with using standard CSS filters. Sure, applying a filter such as sepia(50%) will give an image a more vintage look and is more concise – but what if we don’t like the shade of color used? If we were to expand the standard sepia(X) filter, it would equate to this:
<feColorMatrix type="matrix" values="X..."/>

…where X... is the matrix of color channel values that represents how much of an effect we should apply. The great thing about using SVG filters is that we can manipulate our filter at a color channel level to obtain exactly the right effect we want for our project.

An added bonus is that support for using SVG filters has been excellent for some time now, with only one exception – yes, you guessed it: IE! SVG filters don’t work in IE9 or below but are fully supported for (IE10 and) IE11, as indicated in Figure 5-1.
../images/461821_1_En_5_Chapter/461821_1_En_5_Fig1_HTML.jpg
Figure 5-1

Big Web support for SVG filters

The same applies for the mobile platform – Figure 5-2 shows support is just as good.
../images/461821_1_En_5_Chapter/461821_1_En_5_Fig2_HTML.jpg
Figure 5-2

Mobile support for SVG filters

Okay – let’s move on: assuming that we’re using relatively modern browsers (at least IE10 or above, plus the rest of the usual suspects), what types of filters are there available that we can use? There are a whole host available – I suspect you may be familiar with some of them, such as blur() or sepia(), so without further ado, let’s quickly cover off the full list, as a precursor to converting them to their SVG equivalent versions.

Exploring Existing Filters

In our introduction, we’ve briefly touched on some examples of current CSS filters that are available for us to use. Although the collection looks somewhat diverse, it’s possible to divide them into two groups – the first covers those which adjust the colors used (such as brightness() and sepia()), while the others relate more to the physical appearance (such as drop-shadow() and opacity()). The full list of filters is summarized in Table 5-1:
Table 5-1

List of Available Standard CSS Filters

Name of filter

Purpose of filter

blur()

Applies a Gaussian blur to our image: the value we provide controls the amount of standard deviation to the Gaussian function, or how many pixels on the screen blend into each other. The larger the value, the more blur is created: if a parameter is not provided, then a value of zero is used.

brightness()

Applies a linear multiplier to the image, to change the brightness levels – values should be 0% (completely black), or a multiplier; if no value is specified, then it is assumed to be 100% by default.

contrast()

Adjusts the level of contrast on the specified image – values should be 100% (completely untouched), or a multiplier; if no value is specified, then it is assumed to be 100% by default.

drop-shadow()

This applies a drop-shadow effect to an image – this is a blurred, offset version of the image’s alpha channel, which is drawn in the chosen color, offset to the parent image.

grayscale()

Converts a chosen image to its grayscale equivalent – the value can be from 0 to 100% or a number; 0% is completely unchanged, to 100% which applies a full grayscale effect.

hue-rotate()

This applies a hue rotation on the chosen image – the value provided defines the number of degrees around the color circle. This value can be anything from 0° (untouched, or assumed if the value is missing), to a maximum of 360°.

invert()

Inverts the colors within the chosen image, by a given value – the amount specified defines the proportion of conversion. Values can be in the range of 0% to 100% and cannot be negative – if this is not specified, the default of 100% is assumed.

opacity()

Adjusts the level of transparency within the specified image – the value can be from 0 to 100% or a number; 0% is completely transparent, to 100% which leaves the image unchanged.

saturate()

This saturates the image – this can be 0% (where the image is completely unsaturated), to 100% (where the image is unchanged), or provided as a number. Values over 100% can be provided, which will super-saturate the image.

sepia()

Applies a sepia effect to a chosen image – the input value determines the amount of conversion: 0% leaves the image untouched, to 100% which applies a complete sepia effect.

The odd one out (and not in the list), is url() – this is not a filter as such, but is used to apply any of the other filters to an element within our style sheet.

If we use any of the filters listed in Table 5-1, then we can start to apply effects to our images; this will really start to come alive if we mix and match these effects. This becomes a little cumbersome though, if we’re applying more than just a couple of filters at the same time – what can we do? Well, how about being able to mix and match filters at a more granular level, while at the same time applying custom values?

Introducing SVG Primitives for Filters

Over the last few pages, we’ve explored what filters are available, and the role they play in modifying an image – to really customize how these filters work, and provide those custom values, it’s time to introduce filter primitives.

These primitives make up the building blocks of any filter we can use in our projects. Take, for example, the standard blur() filter: this makes use of the feGausianBlur primitive. Oh – and yes, before you ask: the fe in each name? It stands for “filter effect”; the full list of primitives is summarized in Table 5-2.
Table 5-2

List of SVG Primitives

Name of Primitive

Function – can be used to…

feBlend

Apply a blend mode, similar to CSS, to change how an image or text appears, such as making it lighter or darker.

feColorMatrix

Modify colors used in an image – think of this as changing the color channels using an application such as Photoshop, while retaining the original image.

feComponentTransfer

Alter a specific color channel (red, green, or blue), so an image may appear with a green hue, for example.

feComposite

Uses a set of mathematical algorithms to combine two sources based on their alpha channels at a pixel level, with the alpha channel controlling the shape.

feConvolveMatrix

Apply emboss or beveled type effects to text.

feDiffuseLighting / feSpecularLighting

Add special lighting effects to an image or shape, to give it a gloss or reflective effect.

feDisplacementMap

Move or displace pixels in an image – great for creating warp-effect filters.

feFlood

Completely fill the filter subregion using a specified color and alpha level, without having to create extra SVG elements – this is useful for compositing or merging filters.

feGaussianBlur

Blur an image.

feImage

Load an external image, for later use within other use within other filters (such as feBlend or feComposite).

feMerge

Create a new filter effect, based on applying two or more source filters together concurrently, such as the watercolor filter we create in “Applying a Watercolor Filter,” later in this chapter.

feMorphology

Make the lines of a source image or text appear thinner or fatter (depending on settings).

feOffset

Create a drop-shadow effect.

feTile

Fill a target shape with a repeated, tiled pattern, using an image specified in the filter.

feTurbulence

Allows the creation of synthetic textures using the Perlin Noise turbulence function – it’s perfect for creating artificial textures such as clouds or marble.

We have access to 15 filter primitives in total, which can be used to create anything from the humble drop-shadow effect, through to mimicking shimmering water on a lake – the latter with not a single video or animated GIF in sight!

They open up a world of possibilities, limited only by our imagination; to get us started, let’s take a look at creating one using feGaussianBlur – the technical name for a filter I’m sure you will have used before, although you probably know it under a different name…

Manipulating Content with Filters

Anyone remember the days when we might have had to edit an image to add a blur effect?

Yes, feGaussianBlur is the basis for that well-known, but equally oft-overused effect, blur; long gone are the days where we have to edit images and can simply apply this effect directly in code. This is one of the simpler effects to apply as a filter primitive – we only need to pass in a single value, which represents the amount of blur effect to apply to our image. To see what I mean, let’s run a simple demo to see the effects of blur a SVG shape using this filter primitive; we’ll apply to this to a filled-in circle, as shown in the next exercise.

CREATING A BLUR EFFECT

Let’s make a start on creating our filter:
  1. 1.
    We’ll begin with setting up our basic markup – for this, go ahead and drop the following code into a new document, saving it as simple.html at the root of our project folder:
    <!DOCTYPE html>
    <head>
      <meta charset="utf-8">
      <title>Beginning SVG: Creating a Simple SVG Filter</title>
      <link rel="stylesheet" href="css/simple.css">
    </head>
    <body>
      <h2>Beginning SVG: Creating a Simple SVG Filter</h2>
    </body>
    </html>
     
  2. 2.
    Next, we need to add in our SVG – for this, add the following code, immediately before the closing </body> tag:
    <svg width="230" height="120" >
     <circle cx="60"  cy="60" r="50" fill="darkgrey" />
     <circle cx="170" cy="60" r="50" fill="darkgrey" />
    </svg>
     
  3. 3.

    Go ahead and save the file - if we preview the result at this point, we will see two circles – both gray in color, and with perfectly defined radiuses.

     
  4. 4.
    We’re going to add a blur filter to the circle on the right – for this, we first need to define our filter. Leave a blank line before the first of our <circle> elements, then drop in this code:
    <filter id="demoBlur">
      <feGaussianBlur in="SourceGraphic" stdDeviation="5"/>
    </filter>
     
  5. 5.
    This isn’t enough for the filter to take effect – for this, we need to amend the targeted element. Go ahead and amend the code in the second <circle> element, as indicated:
    fill="darkgray" filter="url(#demoBlur)" />
     
  6. 6.

    Save the file, then preview the results in a browser – if all is well, we should see something akin to the screenshot in Figure 5-3.

     
../images/461821_1_En_5_Chapter/461821_1_En_5_Fig3_HTML.jpg
Figure 5-3

Creating a simple blur filter

See how easy it was to apply that filter? SVG filters work in a similar manner to standard SVG elements – we still have to set up <svg> tags for our SVG shape, but this time, add in a <filter> tag for our effect. There are a couple of key points we should get accustomed to when working with filters, so let’s review our code in more detail.

Dissecting Our Code

Although implementing our feGaussianBlur primitive as a filter is very straightforward, one might be forgiven for asking what the benefit of using it is, in comparison to using the standard blur() property.

It’s a valid point – after all, it does seem like a good chunk of extra code, when we can use a single property! The reason though for using the primitive is the level of customization afforded to us: not just within our filter primitive, but within the SVG itself. Our example is probably a little too simplistic to show off what we can do, but when we get to later demos, you will begin to see something of the level of customization we can achieve when using filter primitives.

Bringing it back to our demo though – how does it work? We start by defining our standard SVG, which contains two circles that are created using the <circle> element. Both have been filled in a dark gray color; one has the extra filter applied. Our filter is defined using <filter> tags – we’ve given it the ID of demoBlur, and set it against SourceGraphic (our image). We’ve only specified a single value of 5 for the amount of blur to apply (controlled by stdDeviation), but we could have specified values for both the x and y axes. In this instance, the value is applied equally to both the x-axis and y-axis. The filter we’ve created is then applied inline using a standard CSS filter attribute: notice that we specify a value using the url() property, which is required for the filter to operate correctly.

Okay – let’s change tack and take things up a notch: we’ve created a simple filter to blur content, but what if we had wanted to change color? For this, we need a different filter primitive; color changes are usually handled by altering values specified for feColorMatrix . This is a really versatile filter: at the heart of this is a matrix of numbers, which control the colors and strengths to use in our filter. We can omit or mix color channels to achieve the desired result – let’s dive in and take a look in more detail.

Creating and Applying Filters

A question – how many times have you applied a filter in CSS, using something akin to this example?
.saturate-filter {
  filter: grayscale(50%);
}
Hopefully the answer is more than once – it’s a great way to apply an effect without the need to edit the original image. Yet, there is one drawback with this approach: we can’t change what “grayscale” means as a color! To work around this, we can make use of primitives in our filter – such an example would look like this, assuming we were using grayscale():
<svg>
  <filter id="gray-on-light">
    <feColorMatrix type="matrix" values="1 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 1 0 "/>
  </filter>
</svg>

This filter makes use of the feColorMatrix property – this versatile primitive is great for replicating a whole variety of existing filters, and creating new ones. To prove this, we’ll work through how the grayscale example operates.

Notice that long string of numbers we used in that example? It might look like binary, but in reality is a color matrix that defines the value of each color channel. We can better explain it using the diagram shown in Figure 5-4.
../images/461821_1_En_5_Chapter/461821_1_En_5_Fig4_HTML.jpg
Figure 5-4

The matrix explained – Source: AListApart.​com

So – what does it all mean? Each value can be anywhere from 0 to 1; zero turns off that color, whereas a value other than zero increases the level of a specified color. The fourth column represents the alpha value, which controls the level of transparency; set to 0 for completely transparent, or 1 to make a color fully opaque.

The fifth column, M, or matrix multiplier can be used to create a new color if we add it to the total of R, G, B, and A. However, in many cases it doesn’t change, so it will be zero – for example, if we were to use the feColorMatrix equivalent for the standard CSS sepia() filter. We can safely ignore it for the purposes of this demo.

We can then add or multiply values together, to arrive at the final color in use. There is a little algebra involved to work out the specifics of our filter; before we dive into this in more detail, let’s put together a simple demo to see what happens when we change a color in a filter.

Changing Color with Filters

As we’ve already seen from earlier in this chapter, we have a range of different filters we can use to apply effects – one of the most useful is feColorMatrix. This allows us to manipulate colors at a channel level; we can use this to achieve almost any change, from a simple color, through to changing light or darkness levels.

For our next exercise, we’re going to keep things relatively simple – we’ll use a basic image of a landscape, then apply a green tint to the whole image, using the feColorMatrix filter. It’s a basic example but perfect for illustrating how we can manipulate each channel level to achieve the desired result.

USING FECOLORMATRIX

Let’s make a start on creating that filter:
  1. 1.
    We’ll start by setting up the markup for our demo – for this, go ahead and drop the following code into a new file, saving it as changecolor.html:
    <!DOCTYPE html>
    <head>
      <meta charset="utf-8">
      <title>Beginning SVG: Changing Colors with Filters</title>
      <link rel="stylesheet" href="css/changecolor.css">
    </head>
    <body>
      <h2>Beginning SVG: Changing Colors with Filters</h2>
    </body>
    </html>
     
  2. 2.
    Next up, let’s add in our source image – for this, go ahead and add this code; this will use the SVG <image> element to store a picture wihtin it:
    <svg width="1198" height="730">
      <image href="img/landscape.png" x="0" y="0"></image>
    </svg>
     
  3. 3.
    If we preview the results now, we won’t see any change to the image; to make this change, we now need to apply our filter – for this, go ahead and insert the following code after the opening <svg> tag:
    <defs>
      <filter id="colorChange">
        <feColorMatrix type = "matrix" values="0 0 0 0 0 0 0.47 0 0 0 0 0 0.15 0 0 0 0 0 1 0 "/>
      </filter>
    </defs>
     
  4. 4.
    For our filter to work, we need to make one more change – go ahead and modify the code as indicated:
    y="0" filter = "url(#colorChange)"
     
  5. 5.

    Save the file – if we preview the results in a browser, we’ll see the results shown in Figure 5-5.

     
../images/461821_1_En_5_Chapter/461821_1_En_5_Fig5_HTML.jpg
Figure 5-5

The results of applying a feColorMatrix filter

Ouch – I know that a landscape picture will have a certain amount of green in it, but even this image takes it a bit too far! This aside, it illustrates how we can manipulate colors, without altering the base image. It’s an important technique to master, so let’s dive in and take a look in more detail.

Understanding Our Code

A quick look at our image should confirm that we’ve used far too much green – it’s clear to see that choosing colors must be done with care!

This aside, we’ve used similar principles in this demo, compared to the previous exercise; we specify our standard <svg> tags, into which we’ve defined our filter. We have a couple of differences though: the first is the introduction of the <defs> tag – this is to define a section where we set up properties (in this case, our new filter), ready for use.

The second comes in the form of our primitive – we’ve specified use of a feColorMatrix primitive , along with a string of numbers that form our color matrix. For space reasons, it’s displayed as one long string in our code; we could easily display it as a grid of 4 by 5 (as shown back in Figure 5-4). We then finish it by applying our filter inline, to the image specified in the <image> element, where we specify the filter attribute inline, using url() to specify our inline filter.

Our demo added a green tint to the entire image; this does raise a question though: How do we specify which color to use? Or a more pertinent question might be: How do we turn that color into our filter? It’s a good question: we could work it out manually, or a more sensible option might be to use the tool that forms part of our next exercise.

Calculating Colors to Use

When working with SVG filters, we have a few of options open to us – we can either change individual values using a certain amount of guesswork, use something created by others as a starting point, perform a few calculations, or use a generator.

I don’t know about you, but I think the last option is likely to be the most popular! Entering a number and having it produce our matrix automatically is a real timesaver – we can then copy the code straight into our development (although it may need a little tidying up, as it is a little out of date!).

However, there is something to be said for working through the calculations needed – they are not as difficult as we might think. In each instance, we work on the premise that a color’s channel value will be somewhere between 0 and 1. We take each RGB channel value in turn, then simply divide it by 255 to arrive at our feColorMatrix value. The number will need to be rounded down to 2–3 decimal places; there is no benefit in having anything longer. To prove this works, let’s put it to the test in a quick demo, and compare it against a RGBA to feColorMatrix application that is available online.

CONVERTING RGBA TO FECOLORMATRIX

Okay – let’s make a start:
  1. 1.

    Pick a color – it doesn’t matter which, but we need the RGBA value for it; for this, you can browse to a site such as ColorHexa ( https://www.colorhexa.com ). For my example, I will assume we’re using rgba(103, 117, 138, 1) – this equates to a shade of largely desaturated dark blue.

     
  2. 2.

    Next, fire up a calculator – for the first value, divide 103 by 255 – the value you get back will 0.4039, which we round down to 0.40. Repeat step 3 for the other two values – you should get 0.46 and 0.54 respectively, rounded down to 2 decimal places.

     
  3. 3.

    Now try entering the original RGBA values into RGBA to feColorMatrix generator, created by Andres Galante, at http://andresgalante.com/RGBAtoFeColorMatrix/ . You should see the result as indicated in Figure 5-6.

     
../images/461821_1_En_5_Chapter/461821_1_En_5_Fig6_HTML.jpg
Figure 5-6

Converting a color to feColorMatrix

Notice anything? The values we generated in step 3 (and 4) are an identical match for the ones shown in the RGBA to feColorMatrix generator. Granted, there may be some instances where this approach won’t work, but performing these calculations should result in a matrix that is somewhere in the region of where we want to be in our code. Of course we can always test the RGBA value in the generator to see how close we are, but then again – this would come as part of standard testing, right?

Okay – let’s move on: it’s time for a little fun! I’m sure you will have heard of Facebook’s Instagram; in this day and age, it’s hard not to see a site making reference to it in some form.

One of its unique selling points is the ability to apply a filter effect on any image we upload – a quick scout on the web will show dozens of examples where others have tried to replicate similar effects. This is a perfect opportunity to create something using SVG filters, so without further ado, let’s dive in and take a look at this in more detail.

Re-creating filters à la Instagram

Instagram – it’s hard to believe that a site now worth $1.5 billion dollars, came about through the simple principle of sharing and enhancing photos, and that its name makes reference to a technology invented back in 1832!

Anyone who has used Instagram will be familiar with some of the filters available for use – these include such exotic names as Mayfair, Sierra, or Ludwig. Even though each filter may sound exotic, they all serve a simple purpose: to adjust the color or appearance of a chosen image. To achieve this, we can apply filters; SVG filters lend themselves perfectly to this function!

To see what I mean, we’re going to create our own version of one of the Instagram filters – the Amaro filter. I should point out that this won’t be a direct copy of the original; it will be a close approximation. It will be enough to illustrate how we can apply a series of filters to achieve the final effect – we can of course use the shortcut names such as contrast(), but then we’d miss out on the fun of tweaking each filter to be…just perfect!

Anyway – let’s dive in and take a look at what is involved in creating an Instagram-style filter:

CREATING INSTAGRAM EFFECT FILTERS

Let’s make a start on creating our filter:
  1. 1.

    We’ll begin by downloading a copy of the changecolor folder – rename it as instagram, and save it at the root of our project folder.

     
  2. 2.

    Within the folder, rename the CSS style sheet as instagram.css and the markup file as instagram.html.

     
  3. 3.
    Go ahead and open up instagram.html – look for the opening <defs> tag, then replace the code as shown:
    <defs>
      <filter id="amaro">
        <!--- contrast -->
        <feComponentTransfer color-interpolation-filters="sRGB">
          <feFuncR type="linear" slope="0.9" intercept="0.049" />
          <feFuncG type="linear" slope="0.9" intercept="0.049" />
          <feFuncB type="linear" slope="0.9" intercept="0.049" />
        </feComponentTransfer>
        <!--- brightness -->
        <feComponentTransfer color-interpolation-filters="sRGB">
          <feFuncR type="linear" slope="1.1" />
          <feFuncG type="linear" slope="1.1" />
          <feFuncB type="linear" slope="1.1" />
        </feComponentTransfer>
        <!--- saturate -->
        <feColorMatrix type="matrix" color-interpolation-filters="sRGB" values="1.394 -0.358 -0.036 0 0 -0.107 1.1575 -0.036 0 0 -0.107 -0.357 1.464 0 0 0 0 0 1 0" />
        </filter>
      </defs>
     
  4. 4.
    Next, we need to apply our new filter to the image – for this, go ahead and amend the filter name, as shown:
    filter = "url(#amaro)"></image>
     
  5. 5.
    As a final touch, we should change the title of our image – for this, change the text between the <h2> tags, as indicated:
    <h2>Beginning SVG: Applying Filters à la Instagram</h2>
     
  6. 6.

    Save the file and preview the results in a browser – if all is well, we should see the same landscape image from the feColorMatrix exercise, but this time with added light, as shown in Figure 5-7.

     
../images/461821_1_En_5_Chapter/461821_1_En_5_Fig7_HTML.jpg
Figure 5-7

Applying filters à la Instagram

Adding a filter such as Amaro opens up a wealth of opportunities – limited only by our imagination! If we were to compare the image from Figure 5-7, one might be forgiven for thinking this shot was taken in the summer, whereas in reality it was taken in early autumn!

That aside, this demo has illustrated a useful technique we should master when working with SVG filters – how to apply multiple filters as one filter. There is an important distinction to make though, which applies to how the filters are applied; to understand more, let’s take a look at the code in more detail.

Understanding How It Works

Anyone who is a fan of using Instagram will be familiar with applying one of the many filters available within the application.

In reality, these filters are made up of composite elements – in the case of Amaro, we’re using contrast, brightness, and saturate filters to create our final effect. The first two use the <feComponentTransfer> filter primitive – this one handles the remapping of data for each pixel, and is designed for instances where we have to adjust light or contrast levels. This uses a linear equation to modify the color of each pixel in our image: the rate of change is controlled by the slope and / or intercept values provided in our code.

In comparison, the saturate filter is applied using the feColorMatrix primitive  – this takes a series of numbers in the form of a color matrix. Our code shows it as a single line of numbers, but it is better written as a grid of five by four numbers, as we saw back in Figure 5-4.

The key to making this demo work is how these filters are applied – in our example, the filters are applied sequentially instead of concurrently. In a sense, this means we’re making three changes to our image, before we see the final result – it works well but isn’t the most effective means!

To make it more effective, we can apply the filters concurrently – for this, we can make use of the <feMerge> attribute to store the results of each primitive, before applying it as one entity to our image. This requires a simple change to our code – let’s dive in and take a look in more detail.

Blending and Merging SVG Filters

When creating filters, we can always start with a single primitive – this serves a purpose, but will soon become somewhat limiting! In the words of that famous Charles Dickens book, “I want more…”

And more we shall have – to achieve this, we need to venture into the world of blending and merging filters. This might at first seem complicated, but in reality it isn’t as difficult as it looks – there are some key principles we should follow:
  • When defining filters, it is sensible to create a <defs> section at the start, as a place to store definitions for each filter; this will allow you to reuse them anywhere in that project.

  • Always specify a results attribute – this will store the results of applying the effect to your image or SVG graphic; we make use of this when merging the filters as the last step in our SVG.

  • The last step should always be the <feMerge> block – we use this to combine the filters into the final solution. The order of each <feMergeNode> is not critical, but the in reference must tie back to the result name of defined primitive.

The great thing about merging and blending is that we’ve already covered most of the principles involved; we create a <defs> area to store our filter primitives, specify one or more said filter primitives, and tie them together with a <feMerge> block.

Taking It Further in Watercolors

Our next demo takes creating SVG filters in a different direction – for this, we’re borrowing one of several effects created by the developer Bennett Feely, namely Watercolor. You can see the original at http://bennettfeely.com/image-effects/#watercolor ; for our demo, we will translate the existing shortcut values into SVG filter primitive equivalents. This gives us the perfect base for tweaking the overall effect at a more granular level.

Bennett’s original filter effect combines three shortcut filters – brightness(1.3), blur(2px), and contrast(2) – we can use this as a basis, but once the filter is in place, we can then tweak it to suit our needs.

APPLYING A WATERCOLOR EFFECT

Let’s take a look at what’s involved:
  1. 1.

    We’ll begin by downloading a copy of the watercolor folder from the code download that accompanies this book – this contains the necessary CSS styles, image, and font used to style the demo. Store this folder at the root of our project area.

     
  2. 2.
    Next, go ahead and open watercolor.html – it doesn’t contain a lot, but we will soon fix this! Start by adding these lines, immediately after the <h2> tags, to define our SVG element.
    <svg width="0" height="0" xmlns:="http://www.w3.org/2000/svg">
      <defs>
        <filter id="watercolor" width="200%" height="150%" x="0" y="0">
        </filter>
      </defs>
    </svg>
     
  3. 3.
    Within the <filter> tags, we can now add our primitive declarations – we’ll begin with the equivalent for brightness(1.3):
          <feComponentTransfer result="bright">
            <feFuncR type="linear" slope="1.3"/>
            <feFuncG type="linear" slope="1.3"/>
            <feFuncB type="linear" slope="1.3"/>
          </feComponentTransfer>
     
  4. 4.
    We have two more primitive declarations to add – go ahead and leave a blank line, then add this one in as our replacement for blur(2):
    <feGaussianBlur stdDeviation="2"  edgeMode="none" result="blur"/>
     
  5. 5.
    The last one to add in is our replacement for contrast(2); for this drop in the following code, leaving a blank line after our blur primitive declaration first:
          <feComponentTransfer result="contrast">
            <feFuncR type="linear" slope="2" intercept="-0.5"/>
            <feFuncG type="linear" slope="2" intercept="-0.5"/>
            <feFuncB type="linear" slope="2" intercept="-0.5"/>
          </feComponentTransfer>
     
  6. 6.
    Last but by no means least – we need to merge it all together! For this, go ahead and leave a line, then add in the following <feMerge> block:
          <feMerge>
            <feMergeNode in="bright"/>
            <feMergeNode in="blur" />
            <feMergeNode in="contrast" />
          </feMerge>
     
  7. 7.
    With our filter declaration in place, we can now add in our image – for this, add the following code immediately after the closing </svg> tag:
    <div class="preview watercolor-effect">
      <img src="img/orchids.jpg" alt="Image of orchids">
    </div>
     
  8. 8.

    Save the file – if we preview the results, we should see an abstract watercolor style image of an orchid, as shown in Figure 5-8.

     
../images/461821_1_En_5_Chapter/461821_1_En_5_Fig8_HTML.jpg
Figure 5-8

Our finished watercolor effect

It’s certainly an interesting effect, isn’t it? Although some may say it bears no resemblance to a true watercolor effect, it doesn’t matter – it’s a perfect example of what we can achieve with relatively little difficulty when merging multiple filters together.

Creating Our Filter – an Epilogue

At this point, I would strongly recommend having a good read through the style sheet for this demo – we’ve not touched on it in detail in our demo (for reasons of space), but there are nevertheless two interesting concepts of note:
  • Bennett has made good use of both :before and :after pseudo-selectors for this demo – it goes to show that we don’t have to just rely on filters to achieve our effect! The image is overlaid several times using these selectors but are slightly displaced – this is needed to set the base for our watercolor effect.

  • We’ve made use of <feMerge> within our SVG filter to create our filter effect, but we equally need to make use of background-blend-mode, background-position, and mix-blend-mode to create the final effect – simply creating and applying our filter isn’t always sufficient to achieve the final result.

You will also notice that the demo isn’t actually 100% complete – inasmuch as the .watercolor effect still uses three shortcut filter names! This is deliberate: it’s a useful exercise to learn how to convert these filter shortcuts to SVG equivalents. It takes a little trial and error, but two useful tips are the following:
  • If you search online, you will see a number of sites where the owners have created their own interpretation of well-known (or less well-known) filters such as Amaro. This is perfect for working out what the basic filter primitives of each filter should be, and which can act as a starting point for your own design.

  • Have a look at https://www.w3.org/TR/filter-effects-1/#ShorthandEquivalents initially; it makes for some dry reading, but gives all of the SVG filter equivalents for the shorthand properties such as blur() or grayscale().

  • If we use the brightness() filter that we used in our example but wanted to change the level, then we simply replace the [amount] value with the original value from the shorthand version. For example, if we wanted a slightly darker version, we might have specified brightness(0.9). Instead, we would translate this as indicated in the example below, where two out of the three <feFunc..> elements have been updated:
    <filter id="brightness">
      <feComponentTransfer>
          <feFuncR type="linear" slope="0.9"/>
          <feFuncG type="linear" slope="0.9"/>
          <feFuncB type="linear" slope="[amount]"/>
      </feComponentTransfer>
    </filter>

Have a go at making the change – the key to this is to not try to get an exact match, but use it as a basis for creating your own filter designs. Remember: there is no right or wrong answer – it’s all down to what you want to see as your final solution!

Okay – let’s move on: Many of our examples provide good visual interest, but they are somewhat…well…static? Fortunately it’s easy to fix: we can use CSS animation to add a transition effect, right? Well, yes – and perhaps not…before you ask, I’ve not lost the plot; there is a real sting in this tale. Before we find out what, let’s quickly knock up a demo that applies such a transition effect, so we can understand why this method isn’t the most effective one to use.

Animating Filter Effects

Animating any form of content can be a double-edged sword – add with care, and it can really take a site to the next level; add it without some forethought, and people are likely to vote with their feet! Unfortunately, it’s no different where SVG filters are concerned – for some, the temptation might be to use JavaScript in some form, while others may use CSS.

There are a whole host of options open to us to animate SVG content – we’ll explore this in more depth in Chapter 6, “Animating Content.” To give you a flavor of what is possible, we’re going to knock up a quick demo that transitions a picture of an orchid from gray to its more usual color of pink.

ANIMATING FILTERS

Let’s take a look at what is involved:
  1. 1.

    We’ll start by extracting a copy of the animate folder from the code download that accompanies this book – go ahead and store it at the root of our project folder.

     
  2. 2.
    Next, open up animate.html, and add the following lines of code immediately after the <h2> tags – we’ll start with defining our filter:
    <svg>
      <filter id="grayscale">
        <feColorMatrix type="matrix" values='0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0' />
      </filter>
    </svg>
     
  3. 3.
    We now need to apply it to our image – leave a line blank, then go ahead and add the following code:
    <div class="polaroid">
      <img class="grey" src="img/orchid.jpg" title="orchid" />
      <img class="color" src="img/orchid.jpg" title="orchid" />
      <span class="name">Phalaenopsis orchid</span>
    </div>
     
  4. 4.

    Save the file – if we preview the results, then hover over the image, we will see it transition from gray to pink. Figure 5-9 shows this in action.

     
../images/461821_1_En_5_Chapter/461821_1_En_5_Fig9_HTML.jpg
Figure 5-9

Animating an SVG

It’s a great effect, right? We’re not using any JavaScript, so the code is kept nice and light; our image fades from a gray to pink, which is perfect for browsing in a gallery. However, there is a sting in this tail – not everything is as rosy as it seems…

Is This the Right Solution?

We’ve just produced a great little simple demo of a close-up image of a Phalaenopsis (or “moth”) orchid – as anyone who has read my books will know, I love orchids! At face value, everything looks perfectly acceptable. Take a closer look at the code though – you will see not one but two images in our code. This clearly isn’t good, so what gives?

Well, the real issue lies in the fact that we can’t animate an SVG filter using CSS animation directly on an SVG filter (this doesn’t apply to CSS shorthand filters). It’s a real pain, as it means we would be limited to using JavaScript-based methods to animate, or we can implement a workaround by adding a copy of the image. We can then set one to have the grayscale filter applied by default, with the other remaining as-is, and transition between the two using a standard CSS transition, as indicated in Figure 5-10.
../images/461821_1_En_5_Chapter/461821_1_En_5_Fig10_HTML.jpg
Figure 5-10

Exploring our animation code

Clearly not an ideal solution – it works, but is not the most efficient! Fortunately there is a better way to animate SVG; one option is to make use of the <animate> tag, or one of the several SVG animation libraries available on the Internet.

We will revisit this, and more around animation, in more detail in Chapter 6, “Animating Content.”

For now, let’s park this concept, and turn our attention to something more practical – SVG filters can produce some really creative effects, but there are occasions where we might have to think in more practical terms.

Fortunately this isn’t an issue with SVG filters: What better than to use blur() as an example? We can use this to great effect as a background to a banner – to learn more, let’s dive in to our next example to see what is involved in creating our filter effect.

Creating a Practical Example

So far, we’ve learned about applying filters in a variety of different instances – from changing a single color, through to mixing multiple primitives to create some interesting effects. There is one more effect we should take a look at – in this instance, it includes using another…image?

Yes, you hear correctly – we’re going to apply an image! We’ll use an image mask to help create a blur effect as part of a hero banner. This effect is perfect for creating original banners for use on websites or even content management systems such as WordPress. We’ll use an image of a vintage camera (available from Flickr at https://flic.kr/p/pQ1wbF ) as a basis for this exercise – let’s dive in and take a look at what is involved.

APPLYING SVG FILTERS IN A PRACTICAL CONTEXT

Let’s make a start:
  1. 1.

    First, go ahead and download a copy of the practical folder from the code download that accompanies this book – save it in our project folder.

     
  2. 2.
    Next, open up practical.html in a text editor – go ahead and add the following lines; they will form the basis of our SVG filter:
    <svg xmlns:="http://www.w3.org/2000/svg">
        <defs>
          <filter id="blurlayer" width="110%" height="100%">
         </filter>
       </defs>
      </svg>
     
  3. 3.
    For this filter, we’re not going to just use the equivalent of the standard blur() – we’re going to mix in four primitives. The first makes use of feColorMatrix – add these lines immediately after the opening <filter id="blurlayer"...> statement:
    <feColorMatrix type="matrix" values=".7 0 0 0 0 0 .7  0 0 0 0 0 .7 0 0 0 0 0 1 0" />
     
  4. 4.
    The next primitive is the SVG equivalent of blur() – for this, add the following code straight after the <feColorMatrix> statement (around line 13):
    <feGaussianBlur stdDeviation="4" result="blur"/>
     
  5. 5.

    We need to make use of a mask, so that the blur effect is limited to the central band in our image – for now open up the mask.txt file from the code download, then copy the contents and paste in immediately after the <feGaussian> blur code line.

     
  6. 6.
    The last primitive we need to add in is <feComposite> - for this, go ahead and add the following line of code immediately after the mask from step 5.
    <feComposite in2="mask" in="blur"  operator="in" result="banner" />
     
  7. 7.
    We now need to merge the filters together: it’s time to revisit using <feMerge>! To achieve the right effect, go ahead and add in this code block before the closing </filter> tag:
    <feMerge result="merge">
      <feMergeNode in="SourceGraphic" />
      <feMergeNode in="banner" />
    </feMerge>
     
  8. 8.
    Last, but by no means least, we need to add in our banner – for this, go ahead and add the following code after the closing </svg> tag, on or around line 27:
    <section class="banner">
      <img src="img/camera.png"/>
      <div class="sitetitle">
        <h1 class="">Classic Cameras</h1>
          <p class="byline">Timeless pieces from yesteryear</p>
      </div>
    </section>
     
  9. 9.
    Save the file – if we preview the results, we will see a picture of an old camera, upon which is our “Classic Cameras” title on a suitably blurred background strip, as shown in Figure 5-11.
    ../images/461821_1_En_5_Chapter/461821_1_En_5_Fig11_HTML.jpg
    Figure 5-11

    Applying filters

     

A finished version of this code is available in the code download, as practical – finished example.html.

The combination of a classic camera, the soft black-and-white tones and blurred title has a real vintage appeal and is just one way of making use of SVG filters in a more practical context. This aside, this demo highlights some useful tips about merging filter primitives, so let’s pause for a moment to examine them in more detail.

Understanding What Is Happening

Throughout the course of this chapter, we’ve applied filters to a variety of different uses, from adjusting a single color, through to what can only be described as a unique watercolor effect! Our latest demo applies filters in a more practical use case, to create a striking blur layer within a hero banner.

If we take a look at the code in more detail, we have a standard SVG tag defined, inside of which is a definition block for our filter. Our first primitive, feColorMatrix, is used to darken the blur effect slightly; without it, the banner won’t have quite the same impact! The second primitive is self-explanatory – this one provides the blur effect; it is the equivalent of applying blur(4) in a rule within a style sheet.

The effect that starts to bring it all together is the mask – this is applied as a data URI. We’ve already talked about using data URIs (see back in Chapter 3, “Working with Images and Text”) – you will notice that we have used a base-64 URI in this instance. Where possible, the recommendation is not to use them; in this instance, as we are only using a single black mask, and not a complicated image, then we can get away with using it.

The last two primitives, <feComposite> and <feMerge> have the effect of merging our content together – the former takes the black mask and blur and creates a composite image of both (similar to the flatten process when working with applications such as Adobe Photoshop). The feMerge process then merges everything together to produce the final result.

The mask image used in this demo was created with the online Method Draw application, available at http://editor.method.ac/  – gone are the days when we have to download and install applications; Method Draw is perfect for creating all kinds of graphics with ease!

Summary

One of the key strengths of working with SVG as a format is the ability to customize images and graphics, without having to resort to image editors – working with filters is no exception! We’ve covered a lot of ideas around how we can change the appearance of any image using SVG filters, so let’s take a few moments to review what we’ve learned in this chapter.

We kicked off with an introduction into the benefits of using SVG filters, before reviewing what is currently available as CSS shorthand filters, and introducing the primitives that make up SVG filters.

Next up came some examples of how we can apply filters – we started with the SVG equivalent of the classic blur option as an example, before moving on to learn how to change the color hue of an image. We then took a look at creating our own variations of classic Instagram filters, as a way of mixing and matching multiple filter primitives, before exploring how to merge and blend such filters together into one final version.

We then rounded out the chapter with a look at a practical use-case example of creating filters, in the form of a blur effect in a hero banner; this illustrates how filters can be used in all manners of different instances, and that we are only limited by the extent of our imagination!

Okay – it’s time to move on. We briefly touched on one subject in this chapter: animation. The need to provide some form of animated content on any website (no matter how small or large an effect), is quickly becoming a must, if we want to give our projects an edge over other solutions. It’s time therefore to get a little animated (oops – sorry!), and explore how we can start moving SVG content in the next chapter…

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.188.190.175