Image Image Image Image Image
Scroll to Top

Topo

copiar

13

jan
2011

Um Comentário

Em Blog

Por Vinicius AC

Carrinho de compras com drag and drop

Em 13, jan 2011 | Um Comentário | Em Blog | Por Vinicius AC

O mercado de e-commerce não para de crescer e este crescimento vem acompanhando de diversas novidades e melhorias nas interfaces das lojas virtuais. Uma delas é opção de arrastar e soltar produtos no carrinho de compras e é isso que você aprende neste artigo.

Se você comprou alguma coisa recentemente no Submarino deve ter notado uma nova opção na interface do site: agora é possível arrastar os produtos exibidos na página para o seu carrinho, que fica exibido de forma permanente no topo do site.

De uma forma simples, vou tentar mostrar pra vocês como implementar uma solução parecida utilizando jQuery e sua biblioteca para interfaces, a jQuery UI – é nela que encontramos os plugins draggable() e droppable(), responsáveis, como os nomes sugerem, por toda nossa operação de arrastar e soltar produtos.

Também veremos um pouco sobre o vasto universo de animações com jQuery através do método animate(). Diferente do Submarino, onde a barra superior é um novo elemento e não o próprio carrinho original, a nossa irá acompanhar de forma fluida o movimento do usuário na página.

Estrutura básica

Vamos começar com um pouco de HTML/CSS para apresentar nossa loja. A página terá os seguintes elementos:

  • Barra localizada no topo (#carrinho-top) – essa barra, no carregamento inicial, estará relativa ao corpo do site. Assim que o usuário mover o mouse abaixo da metade da altura da barra, ela será “fixada” e acompanhará a navegação.
  • Box do mini-carrinho (#carrinho-container) – ficará dentro da barra no topo e é a área onde o usuário pode “soltar” os produtos.
  • Lista de produtos (#produtos) – a listagem de produtos, contendo os elementos que podem ser arrastados para o carrinho.
  1. <div>
  2. <div>
  3. <p>Arraste produtos para esta área</p>
  4. </div>
  5. <div>
  6. <ul>
  7. <li class=”adicione”>Arraste produtos para esta área</li>
  8. </ul>
  9. </div>
  10. </div>
  11. <ul>
  12. <li class=”produto-dd”><h3>Livro 1</h3><p><img src=’_img/twa.jpg’ width=’75’ height=’90’ /></p><p class=’preco-de’>De: R$31,00</p><p class=’preco-por’>Por: R$13,00</p></li>
  13. </ul>
  1. div#carrinho-top{background-color:#C92D21;width:960px;color:#fff;border-bottom:1px dashed #fff;opacity:.8;position:relative;}
  2. div#carrinho-info{padding:10px;}
  3. div#carrinho-container{height:240px;position:absolute;width:240px;background-color:#fff;border:2px solid #c92d21;display:none;}
  4. div#carrinho-container ul{overflow:auto;height:200px;list-style:none;margin:10px;}
  5. div#carrinho-container ul li{color:#333;font-size:12px;border-bottom:1px dotted #ccc;text-align:center;margin:10px;}
  6. ul#produtos li{float:left;background-color:#fff;-moz-box-shadow:5px 5px 5px #ccc;-webkit-box-shadow:5px 5px 5px #ccc;box-shadow:5px 5px 5px #ccc;width:270px;text-align:center;margin:15px;padding:10px;}

Animando a barra superior

O primeiro passo da nossa implementação é fazer com que a barra superior acompanhe os movimentos do usuário, fazendo com que a área de drop dos produtos fique sempre visível. Para tornar isso possível associaremos uma função ao evento scroll da janela (window).

Toda vez que a a distância do scroll para o topo for maior do que a metade da altura da barra, o CSS será alterado para que a barra fique sempre visível e uma leve animação levará a barra para onde for o scroll.

  1. // associando uma função ao evento scroll da janela
  2. $(window).scroll(function(){
  3. // valor do scroll – distância entre a barrinha menor e o início do scroll
  4. var wtop   = $(this).scrollTop();
  5. // objeto da barra superior
  6. var carrinho  = $(‘#carrinho-top’);
  7. // objeto container do site
  8. var container = $(‘#container’);
  9. // altura do carrinho
  10. var cheight  = $(carrinho).height();
  11. // distância do scroll é maior do que a altura da barra / 2 ?
  12. if( wtop &gt; ( cheight / 2 ) )
  13. {
  14. // adiciona uma margem ao container para evitar quebra do lay-out
  15. $(container).css(‘margin-top’, cheight+‘px’);
  16. // transforma a position da barra em absolute
  17. $(carrinho)
  18. .css({
  19. position: ‘absolute’
  20. })
  21. // anima utilizando a propriedade marginTop, com velocidade de 100ms
  22. .animate({
  23. marginTop: ( wtop – cheight ) + ‘px’
  24. }, 100);
  25. }
  26. });

O funcionamento básico do método animate() segue o formato acima. O primeiro parâmetro é composto por um ou vários atributos CSS que farão a animação do elemento. No nosso caso, a barra será animada do valor original da sua margem superior até a especificada na função (a distância do scroll subtraída da altura da barra). Já o segundo parâmetro recebe um valor em milissegundos para efetuar a transição.

Precisamos agora de uma outra condição: quando o usuário voltar para o topo da página, nossa barra precisa recuperar o estado inicial, “fixado” no corpo:

  1. // distância do scroll é menor do que a metade da altura da barra
  2. else
  3. {
  4. $(container).css(‘margin-top’, 0);
  5. $(carrinho)
  6. .stop(true, true)
  7. .css({
  8. position: ‘relative’,
  9. marginTop: 0
  10. });
  11. }

Definindo as áreas de drag and drop

Utilizando a biblioteca jQuery UI vamos definir os elementos que podem ser arrastados (qualquer li dentro da lista #produtos) e a área que vai recebê-los, no nosso caso o div #carrinho-container.

  1. $(‘#produtos li’).draggable({
  2. helper: ‘clone’,
  3. start: function()
  4. {
  5. $(‘#carrinho-container’).show();
  6. }
  7. });

Os produtos, que podem ser arrastados, recebem o método draggable. Já ao box do carrinho é aplicado o método droppable. A chamada dos ítens recebe apenas o parâmetro helper e o evento start. O parâmetro helper pode receber os valores ‘original’, ‘clone’ ou uma função. Utilizaremos ‘clone’ que, como o nome sugere, clona o elemento original na ação de arrastar.

Já evento start acontece assim que o elemento começa a ser arrastado. Quando um produto sofre a ação de arrastar, precisamos exibir o carrinho, que é nossa área de drop.

  1. $(‘#carrinho-produtos’).droppable({
  2. hoverClass: ‘ui-state-hover’,
  3. drop: function( event, ui )
  4. {
  5. // remove a marcação “arraste produtos para esta área”
  6. $(this).find(‘.adicione’).remove();
  7. // busca o ID do produto no campo hidden
  8. var cod = ui.draggable.find(‘.produto-id’).val();
  9. // verifica se o produto existe
  10. if( $(this).find(‘#clone-‘+cod).length == 0 )
  11. {
  12. // adiciona o elemento li à lista de produtos do carrinho
  13. $(‘<li></li>’).html(ui.draggable.html()).prependTo( this );
  14. // animação para indicar que o produto foi adicionado
  15. $(this).find(‘li:first’).slideDown();
  16. // atualiza total de produtos do carrinho
  17. var total_produtos = $(this).find(‘li’).length;
  18. $(‘#carrinho-info’).html(‘<p>’ + total_produtos + ‘ produto’ + ( total_produtos &gt; 1 ? ‘s’ : ) + ‘</p>’ );
  19. }
  20. }
  21. });

No método droppable utilizaremos também um parâmetro e um evento. O parâmetro é o hoverClass, que especifica uma classe que será aplicada a àrea de drop quando um ítem estiver sendo arrastado (vamos utilizar o padrão da jQuery UI). E o evento drop é acionado toda vez que um elemento for “solto” no carrinho. Nossa função primeiro verifica se o produto já existe no carrinho. Caso não exista, cria um novo elemento li na lista com os dados do produto.

Para uma lista completa dos parâmetros e eventos visite jqueryui.com/demos/draggable e jqueryui.com/demos/droppable

Melhorando a exibição do carrinho

O código mostrado até agora tem um problema básico. Toda vez que o produto é adicionado o carrinho “some”. Seria legal que ele ficasse visível por uma certa quantidade detempo e só depois de um período de inatividade fosse escondido. Para isso vamos implementar um timer global na variável timerCarrinho.

Toda vez que o mouse estiver sobre o carrinho o timer é zerado. E, quando o mouse deixar a área, depois de 5 segundos, o carrinho é escondido.

  1. var timerCarrinho = ;
  2. $(‘#produtos li’).draggable({
  3. helper: ‘clone’,
  4. start: function()
  5. {
  6. clearTimeout( timerCarrinho );
  7. $(‘#carrinho-container’).show();
  8. }
  9. });
  10. $(‘#carrinho-container’).mouseenter(function(){
  11. clearTimeout( timerCarrinho );
  12. });
  13. $(‘#carrinho-container’).mouseleave(function(){
  14. var carrinho = $(this);
  15. timerCarrinho = setTimeout( function(){
  16. $(carrinho).slideUp();
  17. }, 5000 );
  18. });

Dever de casa

Essa é uma versão básica de um carrinho drag and drop que pode sofrer diversas melhorias. Segue abaixo uma lista de implementações e funcionalidades novas pra vocês praticarem um pouco:

  • Remover animação da barra, fazendo todo o posicionamento via CSS;
  • Ao adicionar um produto que já exista no carrinho, aumentar a quantidade ao invés de ignorar;
  • Adicionar funcionalidade para excluir produtos do carrinho;
  • Salvar em cookie o carrinho do usuário, ou via AJAX, ou com o plugin de cookies do jQuery.

Por Davi Ferreira

Fonte: Tableless

Tags | , , , , , ,