Quantcast
Channel: eleqtriq » Tutorial
Viewing all articles
Browse latest Browse all 5

SVG Partial Blur and iOS Style Translucency

$
0
0

Sorry, looks as if your Browser can't display SVG

We all know that SVG filters are the best thing since season 4 of "Breaking Bad", with their full potential still to to be discovered. In this article I will show how to create effects like true IOS translucency or tilt-shift/focus blur effects, apply them with one line of CSS and how to animate them.

What you will learn:

We will create an SVG filter that can be applied to any element with one line of CSS.This filter will be constructed in a way that it affects some areas stronger than others. We won't use complicated hacks like cloned elements or multiple versions of one image or any form of javascript trickery.

A masked CSS filter, the "good" way:

This is the recommended method which, unfortunately, doesn't work in Firefox. I will show how to cope with this bug later in the article, but for the moment better do not open these demos in Firefox. We start with a cute little SVG, containing some geometry:

unfiltered SVG

The unfiltered SVG graphic we are going to apply the partial blur to. Click to open.

...then add a filter and apply it to the graphic:

(SVG stuff happening here) ... <filter id="filter"> <feGaussianBlur stdDeviation="10" result="BLUR"/> <filter/> ... (More SVG stuff)
Filtered SVG

Same graphic, now a filter is applied. Click to open.

Right now the graphic is blurred completely. Our goal is to have only parts of the graphic inside a rectangular area blurred and leaving the parts outside unfiltered. We insert a rect into our SVG to use it as a mask for the blur:

... <defs> <rect id="rect" width="100%" height="100%" /> <filter id="filter"> ...

To be able to use this rect as a mask we must find a way to get it into our filter. The wise inventors of SVG gave us feImage for that: ... <filter id="filter"> <feGaussianBlur stdDeviation="10" result="BLUR"/> <feImage id="feimage" xlink:href='#mask' result="MASK" /> ...

With the rect element now being referenced from inside the filter we can start playing. We'll use feComposite to "cut off" the blurred parts outside of the rect: ... <feComposite in="blur" in2="mask" operator="in" result="COMP" /> ...

Filtered SVG

Filter is masked, but unfiltered elements are hidden. Click to open.

The filtered area now appears cropped, but how can we make our filter show the unfiltered parts of the graphic as well?

feMerge will help us to combine the unfiltered (the "sourceGraphic") and the filtered parts of the source element:

... <feMerge result="MERGE"> <feMergeNode in="SourceGraphic" /> <feMergeNode in="COMP" /> </feMerge> ...
Filtered and masked SVG

Unfiltered and filtered SVG merged together. No image duplication or javascript hackery involved. (Click to open).

This is quite a nice little trick to create iOS style translucency and of course the mask can be animated with CSS transitons and animations:

Animated SVG filter mask on hover.

Demo of an animated, masked filter. (Click to open).

<defs> <style> /* <![CDATA[ */ #mask{ animation: scaleme 2s ease-in-out infinite; }@keyframes scaleme { ... } /* ]]> */ </style> <rect id="mask" width="100%" height="100%" /> ... </defs>

What about Firefox?

The final result looks like what we had in mind firsthand. It works in every modern browser, except Firefox. Because of an old bug, firefox can't access internal SVG fragments within SVG filters. Let's find a workaround for this problem:

The most obvious solution for Firefox of course is to put the mask into an external SVG and reference it from the feImage primitive: ... <feImage id="feimage" xlink:href='/path/to/my.svg' result="MASK" /> ...

Alternatively we must find a way to create the mask within the filter. Michael Mullany found a brilliant way to create an alpha mask by "misusing" the feDiffuseLighting filter primitive and build a radial gradient mask, but most geometric forms like polygons or curves can't be made this way. An alternative way to circumvent Fox' current limitation is to use an xLinked dataURI as a mask:

... <feImage id="feimage" xlink:href='data:image/svg+xml;charset=utf-8,<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100" height="100"><rect width="100%" height="100%" /></svg>' x="192px" y="192px" width="16px" height="16px" result="mask" preserveAspectRatio="none"/>

(The data URI should be URL encoded as some browsers will not be able to read it otherwise.)

Unfortunately it is not possible to apply a CSS animation to the feImage primitive. This makes animating the blurred area slightly more difficult, as we must manipulate the filter feImage attribute directly. This is not possible with CSS, so with the help of GSAP Tweenlite we will apply a Javascript animation: ... <script> TweenLite.to(feimage, .8, {ease: Bounce.easeOut, attr:{x:"20", y:"20", width:"360", height:"360"}}); </script> ...

Universal demo: iOS like translucency working in every modern browser. (Click to open).

Applying the filter to HTML content

Some browsers allow us to reference SVG filters from an SVG and apply it to HTML content. Open the demo below and try to select and copy the text (Blink only):

Partial blur applied to HTML content (Click to open).

... .myHTML-element{ filter: url(#myfilter); -webkit-filter: url(#myfilter); } ...

IE and Edge will show the unfiltered content though. Safari will not display the filtered element at all, a very serious accessibility bug. Make sure you do have some Javascript workaround for Safari.

Creating sophistcated image filters

The techniques shown above can be used to create complex effects on images. Let's take a closer look how to create a tilt shift/focus filter by masking a blur filter.

Below you see the SVG that we will use as a mask. It contains two rectangles that are filled with a radial and a linear gradient from white to transparent:

Preview of the SVG mask (Click to open).

We will apply the masked filter to this image:

Here's the same image with a partial blurred svg filter applied:

The final version: An SVG containing a bitmap and a filter (Click to open).

Downloads & Links


Viewing all articles
Browse latest Browse all 5

Trending Articles