Tejüveg (frosted glass) effekt SVG-vel

img

A napokban elég sokat olvastam a különböző css effektekről. Sokszor van, hogy a grafikus speciális effekteket pakol egy-egy képre és ezeket meg kellene próbálni a lehető legélethűbb módon visszaadni. Ilyen effekt a mai tejüveg effekt vagy angolul a frosted glass effect.

GIMP alatt készítettem egy mintát, hogy körülbelül milyennek kellene lennie a a végső képünknek.

Frosted Glass Effect

Nekünk innen az 5 pixelnyi külső keret fog kelleni. Ez is egy olyan effekt, amit legtöbbször a kép túlvágásával érünk el, így ha módosul a háttér, változtatunk a környezeten, akkor a képet ismét körbe kell vágni, és ráadásul pngben kell elmentenünk, ami az átlátszóság miatt jóval nagyobb méretű lesz.

Tehát, most el kell dönteni, hogy mit használunk. Első körben teljesen CSS alapokon akartam megcsinálni blur filterrel és CSS maskkal, de a böngésző támogatottságunk még mindig nem teljes. Canvast is használhatnánk, de ahhoz javascript szükséges. Így marad az SVG, aminek a böngésző támogatottsága is jó.

A háttér és a kör kivágása

Első körben szükségünk lesz a háttérre, ezt a fenti képhez hasonlóan be állítjuk, majd a középső elemet beformázzuk. Mivel a középső elemünk is kép, így kell egy overflow:hidden; a kerekített elemre, hogy a kép ne lógjon ki a boxból.

HTML:

<div class="background">
    <img src="http://lorempixel.com/640/480/nature/5/">
    <div class="rounded-center">
        <img src="http://lorempixel.com/200/200/city/9/">
    </div>
</div>

CSS:

.background {
    position: relative;
}
.rounded-center {
    background: #fff;
    border-radius: 50%;
    height: 200px;;
    width: 200px;
    position: absolute;
    text-align: center;
    overflow:hidden;

    left: 220px;
    top: 140px
}
Néhány apróság

A külső divnek mindig meg kell kapnia a position: relative; css-t egyébként, ha egy oldal kódjába illesztjük be, az absolute pozicionált elemünk a bodyhoz fog pozicionálódni.

Így minden esetben a div.background közepére fog kerülni az elem.

És akkor jöhet a tejüveg effekt

Ez lesz a szórakoztatóbb, a fenti kódot szerintem bárki meg tudná csinálni, aki már készített weboldalt és kicsit beleásta magát a CSS-be.

Tehát most alakítjuk ki az SVG elemünket. Ehhez három dologra lesz szükségünk, magára a háttérre, a filterre és a maszkra. Kicsit ehhez szétbontom a htmlt, hogy könnyebb legyen értelmezni.

A háttér

<div class="background">
...
    <svg class="frosted-glass">
        <image id="background-image" width="640" height="480" xlink:href="http://lorempixel.com/640/480/nature/5/" />
    </svg>
...
</div>

Hozzá tartozó css

.frosted-glass {
    height: 100%;
    left: 0;
    position: absolute;
    top: 0;
    width: 100%;
}

Tehát az SVG hátterünket pozicionáljuk a bal felső sarokba és legyen ugyanakkora méretű, mint a háttérnek használt képünk.

A filter

<div class="background">
...
    <svg class="frosted-glass">
    ...
        <filter id="background-blur">
            <feGaussianBlur stdDeviation="10" />
        </filter>
    ...
    </svg>
...
</div>

Hozzá tartozó css

#background-image {
    filter:url(#background-blur);
}

Ezzel egy Gaussian-blur effektet hoztunk létre, mely 10 pixeles és CSS-sel engedélyezzük az SVG-ben létrehozott háttérképünkön.

Jöhet a végső lépés:

A maszk

<div class="background">
...
    <svg class="frosted-glass">
    ...
    ...
        <clipPath id="background-mask">
            <circle cx="320" cy="240" r="105" />
        </clipPath>
    ...
    </svg>
...
</div>

A clipPath elemünk fogja meghatározni a maszkunkat. Jelenleg, mivel a képünk 200 px széles középen, és a tervben 5 px a túlnyúlás, így 105 px a kör sugara (r), és az x, y koordináta természetesen az alap háttérkép közepére kerül.

Néhány apróság van már csak hátra. Kicsit ki kell bővítenünk a SVG hátterünket, hogy a maszkot használja:

Bővített háttér

<image id="background-image" width="640" height="480" xlink:href="http://lorempixel.com/640/480/nature/5/" clip-path="url(#background-mask)" />

Ha a hátterünk sok semleges részt tartalmaz, egyszínű részek, égbolt, hasonlók, akkor előfordul, hogy az elmosásunk beleolvad a hátterébe.

Erre egy egyszerű css trükköt alkalmazunk:

#background-image {
    filter:url(#background-blur);
    -webkit-transform: translate(-80px, -80px);
    transform: translate(-80px, -80px);
}
#background-mask {
    -webkit-transform: translate(80px, 80px);
    transform: translate(80px, 80px);
}

A háttérképet eltoljuk CSS-sel transformot használva, majd a maszkot ellensúlyozzuk egy ellentétes eltolással. Így már sokkal jobban néz ki.

Internet Explorer 9 és régebbi verziók

Azért választottuk ezt a megoldást, mert a böngészők jobban támogatják, mint a CSS filtereket. De az SVG támogatás csak az Internet Explorer 9-es verziójában került be, az SVG filterek pedig csak az Internet Explorer 10-től támogatott.

Tehát IE9 alatt nem működik majd az effektünk. De csak úgy nem hagyhatjuk, - bár szívem szerint azt tenném - így sajnos kompromisszumot kell kötnünk. Az effektünk nem ugyanazt fogja visszaadni IE9 alatt, de nem csak egy körülvágott képet, vagy egy kört mutatunk nekik.

A trükkhöz szükségünk van a modernizr-re, így meghatározhatjuk, hogy az adott böngésző támogatja-e az SVG filtereket. Ha nem tudjuk a filtert alkalmazni, akkor egy egyszerű rgba border készítünk az elemre. Tudom-tudom, nem épp a legjobb, de mint említettem, kompormisszumot kell kötnünk.

Tehát a css

.no-svgfilters #background-image {
    display: none;
}
.no-svgfilters .rounded-center {
    border: 5px solid rgba(255,255,255,.6);
    background-clip: padding-box;
}

Ezután Internet Explorerben ezt kapjuk:

Frosted Glass IE 9

Frosted Glass Modern Böngészőben

És persze nem maradhat el a szokásos DEMO oldal sem, ahol megnézheted a forrást is. A kész oldalra én még feltettem egy box-shadowt is, így még eléggé hasonlít az eredetileg megtervezett képre.