Tableless

Busca Menu

Habilitando tags em fotos com jQuery

Seja o primeiro a comentar por

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:

  1. Com o mouse, o usuário seleciona uma área da foto para marcação;
  2. Feita a seleção, o script exibe uma caixa de texto para digitação do conteúdo da tag;
  3. 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!

Downloads & referências

Publicado no dia