webrebel html css javascript laravel oop php mysql wordpress kurz

Achievement unlocked!

napísal , 25 Jan 2011 [ PHP Tutoriály ]

Awww, chudák náš úbohy blog, nejak sme ho v poslednej dobe ignorovali. Za to všetko môže evil škola! (a zajtra.sk ;) But we're back in business a povieme si ako v PHP spraviť nejakú riadnu sprostosť - napríklad achievement generator™.

Myšlienka za ním bola asi taká, že pokiaľ sa niekto zvykne velice chváliť nepodstatnými blbosťami a lezie s tým na nervy, pošlete mu takýto obrázok a možno to bude mať zaujímavý efekt. Pokiaľ ste za posledných pár rokov hrali nejakú novšiu hru, určite vašej pozornosti neuniklo, že vás zasypávajú kadejakými trofejami a achievementami pri každej príležitosti. (Niekoho to akože aj reálne teší? Podľa mňa je väčšina vývojárov dosť slabých psychológov, súdiac podľa toho aký majú achievementy na mňa efekt. :p)

Demo - brm achievement generator™!

Čo sa týka programovania, budeme chciet písať text na obrázok pomocou knižnice GD a odosielať ho ako PNG, plus využijeme nejaký ten URL shortener, aby vaša "obeť" nevidela čo jej to posielate. Všetko samozrejme pôjde cez AJAX.

Kód je natoľko jednoduchý, že môžeme všetko nechať v jednom súbore, ktorý bude mať takúto štruktúru:

<?php
if ($_GET['geturl'])
{
	// získame skrátenú url a vypíšeme (to pôjde cez AJAX)
	exit();
}

if ($_GET['t'])
{	
	// vygenerujeme obrázok podľa toho, čo je v "t" (akože title) a v "d" (akože description)
	exit();
}

// inak vypíšeme HTML s formulárom a potrebným javascriptom
?>
<!doctype html>
<html>
<!-- css + nejaké tie skripty -->
...

Generovanie obrázkov

Začneme tým najdôležitejším, čo je vygenerovanie obrázka. Na to a všeobecne na prácu s obrázkami, má PHP prakticky vo všetkých inštaláciách dostupnú knižnicu GD. Mimo kódu budeme ešte potrebovať obrázok, na ktorý chceme vykresliť text a nejaký font. Ja som použil Arial, keďže ten je kvázi free. Takýmto spôsobom môžte používať dokonca aj platené fonty, ktoré máte licencované, narozdiel od metódy s @font-face, keďže k samotnému fontu nemá navštevník stránky prístup. Samotná funkcia v PHP vyzerá takto:

if ($_GET['t'])
{	
	$title = substr($_GET['t'], 0, 100);
	$desc = substr($_GET['d'], 0, 200);
	
	$image = imagecreatefrompng("achievement_blank_shadow.png");

	if(!$image) exit();

	$light = imagecolorallocate($image, 209, 207, 205);
	$dark = imagecolorallocate($image, 166, 164, 161);

	imagettftext($image, 9, 0, 84, 36, $light, "arialbd.ttf", $title);
	imagettftext($image, 7, 0, 84, 52, $dark, "arial.ttf", $_GET['d']);

	header('Content-type: image/png');
	imagesavealpha($image, true);
	imagepng($image);
	imagedestroy($image);
	imagecolordeallocate($light);
	imagecolordeallocate($dark);

	exit();
}

Na začiatku iba skrátime stringy, aby neboli príliš dlhé a otvoríme obrázok. Ďalej treba alokovať farby.. ach, vidno, že v GD mali prsty C++ programátori, ktorí musia všetko manuálne alokovať, odalokovávať a robiť podobné chobotiny, ktoré zdravého človeka nemôžu baviť. Všimnite si, že farby sú ladené mierne do červena, čo zvykne minimálne podvedome ovela lepšie pôsobiť ako iba strohá šedá.

Imagettftext vykreslí na obrázok text podľa ttf fontu (zaujímavé, že ten netreba alokovať...) a má parametre obrázok, výška fontu, uhol otočenia, pozícia x, pozícia y, farba, cesta k fontu a text. Pozícia Y sa meria od baseline fontu, čiže ak by ste dali pozíciu 0, efekt by bol taký, že zhora by vytŕčali iba stopky p, q a podobných znakov. Zalamovanie riadkov sa, bohužiaľ, nedá nastaviť.

Teraz stačí obrázok už len poslať browseru - nastavíme správny content type do HTTP hlavičky, knižnici GD povieme, aby ukladala aj alpha kanál (zase raz neviem prečo to nerobí automaticky) a funkciou imagepng() pošleme samotné dáta. Z hľadiska rýchlosti sa obrázok sa zvykne vygenerovať za 6-7ms, čo je dosť fajn. Nasleduje odalokovávanie, na ktoré sa môžete teoreticky vykašlať, pokiaľ vám nebudú vadiť škaredé pohľady od ostatných programátorov. ;)

Skracovač URL

if ($_GET['geturl'])
{
	echo file_get_contents("http://is.gd/create.php?format=simple&url=".urlencode("http://8.brm.sk/a/?t=" . $_GET['t'] . "&d=" . $_GET['d']) );
	exit();
}

Áno, to je celé. Služba is.gd má mimoriadne dobré API, kde stačí dať ako parameter iba urlencode-nutú adresu a vráti skrátený link. Jednoduché a účinné. Pre porovnanie, napríklad goo.gl vyžaduje autentifikáciu s API kľúčom, ktorý si musíte vyžiadať, so yeah, fuck that. Niečo takéto jednoduché by sa dalo spraviť aj priamo z javascriptu, keby nemá medzi-stránkovú ochranu. AJAX requesty ale fungujú iba z domény, na ktorej sa nachádzate, takže dáta z is.gd treba načítavať cez PHP.

JS, HTML a iné drobnosti

function refreshPreview()
{
	$('#preview')[0].src = '?t=' + encodeURIComponent($('#title').val()) + '&d=' + encodeURIComponent($('#desc').val());
}

function getURL()
{
	$("#url").val("Loading...");
	$("#p_url").show();
	
	$.get("index.php", {geturl: "1", t: encodeURIComponent($('#title').val()), d: encodeURIComponent($('#desc').val()) }, function(data)
	{
		$("#url").val(data)[0].focus().select();
	});
}

V JS sa nedejú žiadne prevratné veci a funkcia refreshPreview() jednoducho zmení "src" atribút obrázku a getURL() cez AJAX získa skrátenú adresu pomocou vyššie rozoberanej funkcie v PHP. Ako bonus som použil odosielanie formuláru so SHIFT+ENTER z minulého tutoriálu od Yablka. EncodeURIComponent() je prakticky to isté, čo urlencode() v PHP, čiže pomení znaky, ktoré by robili neplechu™ v URL, tj. medzeru zmení na "+", "&" na "%26", "?" na "%3F", atď.

Vo formulári mimochodom musí byť <input type="submit">, inak by nefungoval enter na odosielanie formulára. So yeah, there you have it...

source.rar

napísal , 25 Jan 2011

čo ty na to?

komentuj