Last week, we released our new WordPress ecommerce theme, and received a lot of questions about the masked blur effect used on the banner images. This is a live effect that can be applied to any image you give it.
I think it’s a nice treatment and more importantly, the general technique opens up lots of possibilities for crafty designers. I’m going to run you through what I’ve learned today.
In short, the above ‘masked blur effect’:
- uses as a single image
- is non-destructive (i.e. it doesn’t permanently alter your original JPEG or PNG)
- can be applied or removed with a line of text
- can be applied via a mask of practically any shape.
- is relatively well-supported in modern browsers – though mask positioning can be tricky.
First up, SVG is the key to this technique. While we all know SVG is a vector format –it says so on the box – the irony is, SVG has a bunch of pixel-based tricks that PNG and JPG can only dream about.
SVG Filters 101
Let’s start with the basics and the simplest of filters. Setting up a basic SVG filter is as easy as creating a set of filter tags and naming the filter with a reference ID – in our case we’ve called ours ‘myblurlayer’.
Adding the following SVG snippet to your page won’t render anything on screen, but it creates a new filter that you can then apply to any page element – images, text, panels, whatever. Increasing the stdDeviation
increases the blur.
<svg xmlns="http://ift.tt/nvqhV5" version="1.1" height="0"> <filter id="myblurfilter" width="110%" height="100%"> <feGaussianBlur stdDeviation="2" result="blur" /> </filter> </svg>
In this example, we’ve used a simple SVG blur effect (i.e. feGaussianBlur
), but there are dozens of other filter effects we could have used. Most commonly, we apply the filter using CSS.
.blurme { -webkikt-filter: url('#myblurfilter'); filter: url('#myblurfilter'); }
<img class='blurme' src='myimage.png' />
(Sidenote: Yes, I know there are simpler ways to blur, if that’s all you need)
Now, this CSS class approach works fine in most browsers for simple filter effects. Unfortunately, as your filters become more ambitious, bugs in Safari make this unreliable.
I’ve found you generally get more consistent results by placing your base image (JPG or PNG) inside their own SVG element – rather than a standard HTML IMG tag. So, your image looks something like this:
<svg xmlns="http://ift.tt/nvqhV5" xmlns:xlink="http://ift.tt/PGV9lw"> <image x="0" width="100%" height="100%" xlink:href="http://ift.tt/2oa0QhA"/> </svg>
In the browser, this shouldn’t look any different to your garden-variety IMG tag. Later we’ll apply our filter directly to that <image>
element.
Adding a Mask to the Filter
SVG offers a handy filter effect called <feImage>
that converts images into objects that SVG can then manipulate – in our case, to use as a mask. It looks like this.
<feImage id="feimage" xlink:href="our-mask-will-go-here" x="0" y="0" height="300px" result="mask" preserveAspectRatio="none"/>
Technically, our xlink:href
can accept a link to an external file (for instance, ‘mask.svg’), but I had trouble getting this to work consistently across browsers. Instead, we’re going to code our SVG mask directly into the filter.
Creating your Mask Shape
Before we write any more SVG, we need to create the mask we want to use. I’m going for a very simple rectangular ‘letterbox’ effect, but there’s nothing stopping you from using any vector shape you like – though I recommend keeping your mask relatively simple.
For this, I’m going to use a nice little online SVG editor called Method-Draw. It’s simple, free and should encourage you to keep your mask simple.
When you’ve created a simple black and white shape, click on ‘View’ -> ‘Source’, and copy the SVG markup to your clipboard.
To bring this mask into our filter, we’ll need to convert it to a ‘data URI’ – basically just an encoded version of our SVG markup that is easy for the browser to use but looks like complete gobbledygook to us.
Open this Data URI Converter in a new tab, click the ‘Provide text’ option and paste your SVG markup into the text field.
We’ll need to tell the converter we are giving it an SVG, so enter image/svg+xml
into the Enter Mime Type field. When you click ‘Generate Data URI’, you get a long string of mostly random-looking characters – that’s our converted mask.
Copy this to your clipboard, switch back to your SVG filter code and paste it into the xlink:href=
section of our <feImage>
.
Currently we our filter should look something like this:
<svg xmlns="http://ift.tt/nvqhV5" xmlns:xlink="http://ift.tt/PGV9lw"> <defs> <filter id="blurlayer" width="110%" height="100%"> <feGaussianBlur stdDeviation="4" result="blur"/> <feImage id="feimage" xlink:href="data:image/svg+xml;charset=utf-8;base64,PHN2ZyB3aWR0aD0iMTAyNCIgaGVpZ2h0PSIzMDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+DQogPGc+DQogIDx0aXRsZT5iYWNrZ3JvdW5kPC90aXRsZT4NCiAgPHJlY3QgZmlsbD0ibm9uZSIgaWQ9ImNhbnZhc19iYWNrZ3JvdW5kIiBoZWlnaHQ9IjMwMiIgd2lkdGg9IjEwMjYiIHk9Ii0xIiB4PSItMSIvPg0KIDwvZz4NCg0KIDxnPg0KICA8dGl0bGU+TGF5ZXIgMTwvdGl0bGU+DQogIDxyZWN0IGlkPSJzdmdfMSIgaGVpZ2h0PSIxMzMiIHdpZHRoPSIxMDI0IiB5PSI4NC41IiB4PSIwIiBmaWxsLW9wYWNpdHk9Im51bGwiIHN0cm9rZS1vcGFjaXR5PSJudWxsIiBzdHJva2Utd2lkdGg9IjEuNSIgc3Ryb2tlPSJudWxsIiBmaWxsPSIjMDAwMDAwIi8+DQogPC9nPg0KPC9zdmc+" x="0" y="0" height="300px" result="mask" /> ... <!--more to come here --> </filter> </defs> </svg>
Still with me?
SVG Sandwiches
One of the cool SVG features is the ability to ‘sandwich together’ multiple effects into a single image treatment. The first thing we need to do is combine our mask and the blur filter into a single entity.
It’s a little like plugging different inputs into your TV. We use <feComposite>
for this.
``
As you can see, we’re taking the output from our mask (result="mask"
) and the output from our blur filter (result="blur"
) and them using (in2="mask"
) and (in="blur"
) to combine them. We’re calling the result ‘comp’.
Combining the Filter and the Image Source
Now we just to tell the filter what to do with this masked blur – which is apply it to any image we give it. For this, we can use <feMerge>
to merge our masked blur effect with whatever image it gets. Happily, SVG understands the concept of a ‘SourceGraphic’, so we can just tell it merge ‘SourceGraphic’ with ‘comp’.
It looks like this.
<feMerge result="merge"> <feMergeNode in="SourceGraphic" /> <feMergeNode in="comp" /> </feMerge>
Our filter is ready. We just have to apply it to an image.
I’ve put my source graphic – a JPG – in a separate SVG element and applied the filter with filter="url(#blurlayer)"
<svg xmlns="http://ift.tt/nvqhV5" xmlns:xlink="http://ift.tt/PGV9lw"> <image filter="url(#blurlayer)" x="0" y="0" width="100%" height="300px" xlink:href="http://ift.tt/2oa0QhA"/> </svg>
Putting the whole thing together, here’s a simplified demo:
One more thing
As we’ve learned, SVG filters allow us to layer effects on top of one another. This means we can get even trickier by adjusting the color of the masked area with the <feColormatrix>
filter effect.
Adding the following to the top of our filter code will darken the masked area and increase the text contrast.
<feColorMatrix type="matrix" values=".7 0 0 0 0 0 .7 0 0 0 0 0 .7 0 0 0 0 0 1 0 " />
I’m not going to explain the subtleties of feColorMatrix here as Una Kravets has already covered it beautifully here.
There’s also a nice push-button tool here shows you how different matrices effect the color of an image. Often playing with a live demo is the fastest way to learn.
And here’s the final demo with the tweaked colors.
Stepping it up
To keep things easy to follow, I deliberately went with the simplest of mask shapes – a rectangle. But we can do more interesting things.
Here’s a more complex geometric mask combined with a more intense color effect.
Continue reading %Design Tricks with SVG Filters: A Masked Blur Effect%
by Alex Walker via SitePoint
No comments:
Post a Comment