chester's blog

technology, travel, comics, books, math, web, software and random thoughts

tilewriter – desenhando ladrilhos em JavaScript

20 Jun 2010

Eu fiquei vidrado no layout de “ladrinhos” do logotipo do site do RHoK, que lembra os micros de 8 bits sem deixar de ser moderno, e pensei “taí, vou roubar me inspirar criar um trabalho artístico derivativo para o próximo update visual do meu blog”.

O chato é que não apenas sou um zero à esquerda em GIMP/PhotoShop, mas também queria algo que pesasse menos no carregamento. Solução: programar.

O canvas do HTML5 viria a calhar, mas o suporte dos browsers ainda está longe do ideal. Resolvi, então, criar uma biblioteca minimalista para fazer desenhos nesse estilo usando elementos de HTML. E ficou minimalista mesmo: basta incluir ela e o JQuery no

<head> da página, i.e.:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript"></script>
<script src=/tilewriter/tilewriter-0.2-min.js" type="text/javascript"></script>

Coloca-se na página um <div> (ou outro container HTML) no qual o “desenho” será montado, e aí é só brincar de JavaScript:

tilewriter.drawRow("#div_teste", "      X");
tilewriter.drawRow("#div_teste", " XX    ");
tilewriter.drawRow("#div_teste", "X  X  X");
tilewriter.drawRow("#div_teste", "X  X  X");
tilewriter.drawRow("#div_teste", " XX   X");

Isso produz o mosaico abaixo (que pode não aparecer num leitor RSS – o que é esperado, é só decoração – nesse caso, abra o post original):

Também é possível configurar a palheta de cores utilizada, o tamanho de cada “azulejo” e o espaçamento entre eles, o que permite várias possibilidades interessantes. Por exemplo, esse encanador familiar:

é produzido pelo script:

tilewriter.reset();
tilewriter.spacing = ;
tilewriter.size = 8;
tilewriter.colors = ["", "#EA590C", "#AC7C00", "#FFA440"];
tilewriter.drawRow("#div_mario", "   111111    ");
tilewriter.drawRow("#div_mario", "  1111111111 ");
tilewriter.drawRow("#div_mario", "  22233233   ");
tilewriter.drawRow("#div_mario", " 23233323333 ");
tilewriter.drawRow("#div_mario", " 232233323333");
tilewriter.drawRow("#div_mario", " 22333322222 ");
tilewriter.drawRow("#div_mario", "   33333333  ");
tilewriter.drawRow("#div_mario", "  2232222    ");
tilewriter.drawRow("#div_mario", " 22212212222 ");
tilewriter.drawRow("#div_mario", "2222111122222");
tilewriter.drawRow("#div_mario", "3321311312333");
tilewriter.drawRow("#div_mario", "3331111113333");
tilewriter.drawRow("#div_mario", "3311111111333");
tilewriter.drawRow("#div_mario", "  1111 1111  ");
tilewriter.drawRow("#div_mario", " 2222   2222 ");
tilewriter.drawRow("#div_mario", "22222   22222");

Para usar mais do que 10 cores, basta passar a palheta como um objeto do tipo {"caractere" : "cor"}, usando qualquer cor CSS válida. Espaços e caracteres não-mapeados ficam sem cor, i.e., com a cor do fundo.

Isso bastava para o que eu queria, mas me empolguei: já que a idéia é logotipos e afins, por que não automatizar a escrita de textos? Para isso bastava ter uma fonte bitmap que fosse compacta e legível – tal qual tínhamos nos micros de 8 bits – e aí veio o estalo: ao invés de criar uma fonte, era mais fácil pegar uma direto da ROM de um deles!

A escolhida foi a fonte do TK90x (ZX Spectrum), que não apenas está prontinha na ROM, mas tabmém é fácil de encontrar salva na web. Ela é 8×8, o que significa que se eu guardar como texto hexadecimal, cada “imagem” de caractere ocupa 16 bytes (mais o payload do JavaScript), e fica bem fácil de converter para binário.

O resultado é que pra escrever o “oi”, agora basta programar:

tilewriter.drawText("#div_teste_2","oi");

e temos:

Como de costume, dá pra melhorar bastante, e o código-fonte é livre para quem quiser brincar. O chato é que eu queimei o tempo que ia usar no update do layout com esse brinquedo, mas valeu a pena – a lib ficou com menos de 4K minificada (incluindo a fonte). Olha como dá pra se empolgar na nostalgia:

tilewriter.spacing = ;
tilewriter.size = 1;
tilewriter.drawText("#div_tk90x_cima", "TK90X - Color Computer");
tilewriter.spacing = ;
tilewriter.size = 8;
tilewriter.colors = ["white", "yellow", "cyan", "green", "magenta", "red", "blue", "black"];
tilewriter.drawRow("#div_tk90x_baixo", "000111222333444555666777");






Comments



Chester

Pois é! Na real, qualquer browser que tenha um JavaScript não muito jurássico e suporte a criação dinâmica de uma quantidade relativamente grande de elementos de bloco (um por pixel/azulejo) consegue renderizar.

Se um dia eu voltar a esse projeto, talvez tente reduzir a quantidade de elementos pra deixar mais leve (embora eu realmente espere que a tag canvas do HTML5 torne isso obsoleto).