Marcar seus amigos nas fotos publicadas é um dos recursos mais populares do Facebook. Neste artigo você confere como implementar uma interface semelhante utilizando o plugin imgAreaSelect. Veremos apenas a parte client-side, sem armazenar as informações das tags, portanto, sem nenhuma programação server-side.
Nosso HTML/CSS
O primeiro passo é criar um HTML com a foto de exemplo. Começamos adicionando ao head chamadas para os scripts e as folhas de estilo.
<script type="text/javascript" src="js/jquery.min.js"> <script type="text/javascript" src="js/jquery-ui-1.8.13.custom.min.js"> <script type="text/javascript" src="js/jquery.imgareaselect-0.9.6/scripts/jquery.imgareaselect.min.js"> <link href="css/ui-lightness/jquery-ui-1.8.13.custom.css" rel="stylesheet" /> <link href="js/jquery.imgareaselect-0.9.6/css/imgareaselect-default.css" rel="stylesheet" />
Além do imgAreaSelect, também utilizamos a biblioteca de componentes para interface jQueryUI. Ela será responsável por mover (draggable) e redimensionar (resizable) as tags nas fotos.
A marcação HTML é bem simples, apenas com a imagem e um link para exibir/ocultar as tags. O formulário para adicionar uma tag será adicionado on the fly, após selecionarmos uma área. E como o formulário terá posição absoluta, é importante definir, no CSS, o atributo “position:relative” para o container da imagem, no nosso caso o elemento p.
<p><img src="img/ramones.jpg" /></p> <p><a href="#" class="toggle-tags">ocultar tags</a></p>
p{ position:relative } div.form-tag{ position:absolute; top:0; left:0; z-index:1000; } span.tag{ position:absolute; border:1px solid #df0d32; background-color:rgba(255, 255, 255, 0.2); display:inline-block; color:#df0d32; }
Selecionando áreas na foto
Passo a passo, esse será o fluxo da nossa interação:
- Com o mouse, o usuário seleciona uma área da foto para marcação;
- Feita a seleção, o script exibe uma caixa de texto para digitação do conteúdo da tag;
- Ao pressionar a tecla enter, o script cria, visualmente, a tag.
Abaixo temos a chamada para o plugin imgAreaSelect. Precisamos armazená-lo em uma variável global, chamada aqui de “ias”, porque posteriormente vamos alterar/limpar áreas de seleções de acordo com a interação do usuário (pressionado a tecla ESC). Por isso também utilizamos a opção “instance: true”.
ias = $('img#foto').imgAreaSelect({ handles: true, instance: true, onSelectEnd: formTag, onSelectStart: function(){ $('.form-tag').remove(); } });
O evento “onSelectEnd” representa o momento em que o usuário termina de marcar uma área – e é nele que executamos a função “formTag” para exibir o campo de texto para preenchimento. Já o “onSelectStart” representa o início do movimento de seleção e, nesse caso, precisamos eliminar qualquer outro form presente para evitar confusão.
Salvando as tags
Ok, hora de exibir o formulário para o usuário adicionar uma tag. Qualquer função no evento “onSelectEnd” pode (e deve) receber dois parâmetros: img e selection. O primeiro é um objeto que representa a imagem onde foi aplicada a seleção e o segundo contém todas as informações de tamanho e posicionamento. Os vértices X e Y, necessários para posicionar o formulário logo abaixo da marcação, são representados por selection.x1 e selection.y1, respectivamente.
var formTag = function(img, selection){ $('.form-tag').remove(); if(selection.width > 0 && selection.height > 0){ $('<div class="form-tag"><input type="text" size="20" class="tag-name" /></div>').insertAfter(img); $('.form-tag') .css({ top : (selection.y1 + selection.height), left : selection.x1 }) .find('input.tag-name') .focus() .data('selection', selection); } };
Notem que, antes de exibir o formulário verificamos com if(selection.width > 0 && selection.height > 0)
se de fato a seleção existe ou se o usuário apenas clicou na área da foto (acredito ser uma falha do plugin, já que nenhuma seleção foi criada). E, ao adicionar o formulário, jogamos o foco do cursor para o campo de texto e armazenamos as posições, para usarmos mais tarde, no atributo data do input.
Agora precisamos identificar quando o usuário pressionar enter ou ESC no input. Pressionando enter, nosso script deve salvar e exibir a tag na foto, enquanto a tecla ESC representa o cancelamento da ação, ou seja, remove o formulário. Utilizamos o evento keyup no input com uma função recebendo o parâmetro “e” (o próprio evento keyup). Os atributos “keyCode” e “which” equivalem à tecla pressionada pelo usuário, onde 13 é o enter e 27 ESC. Precisamos utilizar ambos porque alguns navegadores utilizam keyCode e outros which.
$('input.tag-name').live('keyup', function(e){ if(e.keyCode == 13 || e.which == 13){ // enter if($(this).val() != ""){ var selection = $(this).data('selection'); $('<span class="tag">'+$(this).val()+'</span>').appendTo($(this).parent().parent()); $('.tag:last') .css({ height: selection.height, width: selection.width, top: selection.y1, left:selection.x1 }) .draggable({ containment: '#foto' }) .resizable({ containment: '#foto', ghost: true }); limpaFormTag(); } }else if(e.keyCode == 27 || e.which == 27){ // esc limpaFormTag(); } });
Primeiro validamos o conteúdo do input – não pode ser vazio. Caso o usuário tenha informado o conteúdo da tag, adicionamos o elemento span com a classe tag ao parágrafo da imagem. Com a tag recém adicionada, buscamos as dimensões e posicionamento armazenadas no atributo data-selection do input e definimos o css do span. Para dar um toque especial à nossa interface, conforme mencionado anteriormente, a tag ainda recebe os efeitos draggable e resizable, da jQueryUI, permitindo assim mover ou alterar seu tamanho depois de criada.
A função “limpaFormTag” esconde o formulário e atualiza nossa instânce do plugin imgAreaSelect, removendo qualquer seleção em andamento.
var limpaFormTag = function(){ $('.form-tag').remove(); ias.setOptions({hide:true}); ias.update(); };
Com tudo pronto, falta definir a ação do link que exibe/oculta as tags. O método “toggle” automaticamente identifica se o seletor, nossas tags, estão visíveis ou não e executa a ação (exibir/ocultar) de acordo com o estado atual do elemento.
$('.toggle-tags').click(function(e){ $('.tag').toggle(); if($('.tag:visible').length > 0) { $(this).text('ocultar tags'); } else { $(this).text('exibir tags'); } e.preventDefault(); });
E agora, para onde ir?
É claro que, para essa interface de fato funcionar, seria necessário armazenar as informações das tags em banco de dados. No nosso exemplo, ao atualizar a página, todas as essas informações serão perdidas. Logo, um dos próximos passos seria um script server-side executado quando o usuário pressionar a tecla enter no input.
Também seria legal desenvolver opções para edição do conteúdo e exclusão das tags.
E que tal transformar tudo em um plugin? Só não esqueça de compartilhá-lo com a gente!