Gradient v CSS za pomoci PHP a mod_rewrite

To jsem jednou potřeboval udělat barevný přechod. Ale ne GIMPárnu na jedno použití, nóbrž přechod dynamický, něco jako že by se zavolal soubor a vono se to vygenerovalo a tvářilo jako obrázek. S PHP a knihovnou GD je věc snadná a přidá-li se i mod_rewrite, pak i velmi slušivá. Laťku jsem si nastavil zhruba do téhle výše:

  1. možnost prolnutí více než dvou barev v libovolných vzdálenostech
  2. výběr mezi vertikální a horizontální orientací
  3. ukládání obrázku do cache
  4. bezpečnost z hlediska zatížení serveru či přeplnění cache

Co se týče bodu 1, skript dostane seznam klíčových barev a velikosti mezer které má mezi nimi proložit pÅ™echodem. Jako oddÄ›lovač takového seznamu jsem zvolil znak + který asi nejlépe znázorňuje spojování. VaÅ¡e komentáře mÄ› pÅ™imÄ›ly zmÄ›nit oddÄ›lovač na spojovník "-" Klíčové barvy se zapisují Å¡esti velkými hexadecimálními číslicemi, mezery desítkovÄ›. Aby se mezera odliÅ¡ila od barvy, může mít maximálnÄ› pÄ›t cifer – v praxi se použijí nanejvýš čtyÅ™i. Zbývá jeÅ¡tÄ› rozliÅ¡it orientaci (bod 2). Tak co tÅ™eba jedním malým písmenem na začátku? A bude to buď x pro horizontálnÄ› se opakující pÅ™echod nebo y pro pÅ™echod s opakováním vertikálním.

Bod 3: Skript na konci, pokud je to možné, uloží výsledek do souboru. Název souboru má stejný tvar s jakým pracuje mod_rewrite, takže pÅ™i příštím požadavku už soubor fyzicky existuje a má pÅ™ednost. Když vím, že obrázek potÅ™ebuju jenom jednou a je zbytečné ho cachovat (tÅ™eba jako v testovacím rámečku níž), pÅ™idám na konec parametr ?tmp. Jelikož parametry nejsou součástí názvu souboru, mají cachované soubory opÄ›t pÅ™ednost. A proč je to cachování tak nechutnÄ› důmyslné? Protože pÅ™episování URL je nastaveno case-sensitive, takže v cache nevzniknou duplicity – každý pÅ™echod je jednoznačnÄ› identifikován. Nuže a bod 4 vyÅ™ešíme omezením délky celého pÅ™echodu – dejme tomu na 5000px?

Zápis gradientu

Jak je popsáno výše, na začátku musí být malé písmeno x/y, za nímž následují klíčové barvy a číselně vyjádřené mezery mezi nimi. Pokud mezi barvami prolnutí být nemá (tedy nulová mezera), pak se zapíše ihned další barva, např. yFF00FF-00FF00 jsou fialový a zelený pixel vedle sebe. Jednoduchý gradient pro svislé opakování (y) získáme třeba pod tímhle názvem:

Způsob zápisu gradientu

Délku celého pruhu spočítáme součtem klíčových barev (3) a mezer mezi nimi (5+2). Pruh je tedy dlouhý 10px.

Jak se to teda používá

  1. adresář gradient/ si zkopírujete kam je pohodlno
  2. má-li fungovat cachování, je třeba povolit do něj zápis
  3. teď už v adresáři najdete jakýkoli obrázek gradientu, např. gradient/y00FF00-300-0000FF.png je 302px dlouhý přechod od zelené k modré

Kdo náhodou nemá k dispozici mod_rewrite, může skript volat přímo: gradient/gradient.php?repeat=y&grad=00FF00-300-0000FF

A proč se pruh roztahuje na 5px

… když by stačil 1px? Tučňákům nestačí. A možná i tygrům, pÅ™iznám se, že jsem po tom příliÅ¡ nepátral. Problém je v hladkosti pÅ™echodu. Zatímco pod Windows je opakovaný pÅ™echod stejný pÅ™i jakékoli šířce pruhu, FF/Linux ukáže 1px proužek pÅ™i nižší barevné hloubce jako nekoukatelnÄ› ohyzdné čáry. ZjevnÄ› nejprve obrázek proloží a teprve potom ho opakuje. Je tedy jasné, že jednorozmÄ›rný pÅ™echod nemůže proložit nikterak rozmanitÄ›, ovÅ¡em dostane-li vÄ›tší plochu, stane se s ním pÅ™ibližnÄ› tohle:

Opakovaný černobílý přechod při 8-bitové hloubce (FF/Linux)
Opakovaný černobílý přechod při 8-bitové hloubce (FF/Linux)

K pÄ›ti pixelům jsem doÅ¡el po sáhodlouhém zkouÅ¡ení. VÅ¡e do 3px je bída, 4px začínají být pÅ™ijatelné a pÄ›t – bingo! Vyšší hodnoty samosebou pÅ™inášejí výsledek o Å¡petku lepší, ale to už je příliÅ¡ na úkor velikosti souboru (ačkoli nijak drasticky, PNG komprese se celkem vytáhla). A protože tÄ›ch 5px je krásná a vždy použitelná hodnota, dal jsem ji na pevno do hlavičky skriptu namísto do URL, které je tím jednodušší. PÅ™ipomínám, že fujtajblproužkový problém se týká jen nížších barevných hloubek (do 16 bitů).

Zkouška

gradient/.png

Předvolby: B/W B/W/B R/G/B Černý panel Aqua moje :-)

A proč je v nadpisu "CSS"?

body {
  background:url('gradient/x664477-600-CC99FF.png') left top repeat-x fixed #CC99FF;
}

Download

gradient.zip


Komentáře

[1] Martin Stiborský [web] – 2008-01-09, 10.33

A tohle je pěkné pane, to se mi líbí, to já si přebuším do Pythonu + PIL, to je šikovné, díky za inspiraci.

[2] Martin – 2008-01-09, 11.04 – Reakce: [4]

Znak "+" v názvu souboru je nehorázná prasárna.

[3] Dan [web] – 2008-01-09, 11.18 – Reakce: [4]

To plus mi tam vadi take, ale jinak je to velmi pekny napad. Dik!

[4] Honza Odvárko [web] – 2008-01-09, 14.12

[2] [3] Proč je to prasárna a proč tam vadí? Navrhněte jiný oddělovač a já ho třeba změním.

[5] sh [web] – 2008-01-09, 15.33

No, třeba pomlčka by byla rozhodně lepší, ne že by plus byl proti něčemu (tipuju až na dos...a nějakou jinou dnes už exotiku), ale proč se nedržet takřka standardního [a-z] -_. že...

[6] Honza Odvárko [web] – 2008-01-09, 16.05

Dobře, plus půjde pryč, zvažuju mezi spojovníkem a podtržítkem:

yFF0000-250-00FF00-250-0000FF.png
yFF0000_250_00FF00_250_0000FF.png

---------
Doplněno: Vítězem se stává spojovník.

[7] Rodriguez – 2008-01-20, 23.28 – Reakce: [8]

Pěkný řešení, kámen úrazu ale nastane když mám element který se natahuje podle obsahu a potřebuju tam gradient, tzn. že neznám jeho velikost.

[8] Honza Odvárko [web] – 2008-02-09, 14.40

[7] Na tohle je třeba vzít JavaScript a generovat pruh dlouhý offsetHeight či offsetWidth daného elementu. Bez použití JS můžeme prvku dát gradient vhodné univerzální délky, ten lze ostatně poskytnout i jako non-JS alternativu.

[9] Zemistr [web] – 2010-01-25, 21.22

Tak tohle je fakt nářez...
na googlu sem zadal:
php gd přechod

a bingo...hned na prvním místě sem našel tenhle script...
Super Práce Honzo ;-)

[10] tkdzes [web] – 2011-05-28, 17.51

Přidat komentář

Identifikace autora

(zobrazí se v antispam podobě)

Komentář

Nepoužívej HTML značky a piš pokud možno s diakritikou. Na ostatní komentáře se odkazuj např. [1]

Díky za tvůj názor!

Navigace

Hledání