Efeitos de Animação com Corações e Textos em Eventos do Mouse

Ao interagir com websties, é possível adicionar elementos visuais dinâmicos, como corações ou textos decorativos, que surgem durante o clique ou movimento do mouse. Este artigo apresenta exemplos práticos de como implementar esses efeitos usando JavaScript e CSS, mantendo a performence com requestAnimationFrame.

Animação de Corações ao Clicar ou Mover o Mouse

O efeito utiliza uma estrutura CSS para criar a forma do coração, composta por um quadrado e dois círculos posicionados. O JavaScript gerencia a criação dos elementos e suas animações de opacidade e escala.

.coracao {
  width: 12px;
  height: 12px;
  position: fixed;
  background-color: #ff0000;
  transform: rotate(45deg);
}
.coracao::after,
.coracao::before {
  content: '';
  width: inherit;
  height: inherit;
  background-color: inherit;
  border-radius: 50%;
  position: absolute;
}
.coracao::after {
  top: -6px;
}
.coracao::before {
  left: -6px;
}

(function(doc, win) {
  var elementosAnimados = [];
  var animFrame = win.requestAnimationFrame || function(callback) {
    setTimeout(callback, 16);
  };

  function inicializar() {
    adicionarEstilos();
    vincularEventos();
    iniciarLoopAnimacao();
  }

  function iniciarLoopAnimacao() {
    for (var i = 0; i < elementosAnimados.length; i++) {
      var item = elementosAnimados[i];
      if (item.opacidade <= 0) {
        doc.body.removeChild(item.elemento);
        elementosAnimados.splice(i, 1);
        continue;
      }
      item.posY -= 1;
      item.escala += 0.04;
      item.opacidade -= 0.013;
      item.elemento.style.cssText = 'left:' + item.posX + 'px;top:' + item.posY + 'px;opacity:' + item.opacidade + ';transform:scale(' + item.escala + ') rotate(45deg);background-color:' + item.cor;
    }
    animFrame(iniciarLoopAnimacao);
  }

  function vincularEventos() {
    var handlerCliqueAntigo = win.onclick;
    win.onclick = function(evt) {
      if (handlerCliqueAntigo) handlerCliqueAntigo();
      criarCoracao(evt);
    };

    var ultimaVezMov = Date.now();
    win.onmousemove = function(evt) {
      if (Date.now() - ultimaVezMov > 100) {
        ultimaVezMov = Date.now();
        criarCoracao(evt);
      }
    };
  }

  function criarCoracao(evt) {
    var el = doc.createElement('div');
    el.className = 'coracao';
    elementosAnimados.push({
      elemento: el,
      posX: evt.clientX - 6,
      posY: evt.clientY - 6,
      escala: 1,
      opacidade: 1,
      cor: corAleatoria()
    });
    doc.body.appendChild(el);
  }

  function adicionarEstilos() {
    var estilos = doc.createElement('style');
    estilos.textContent = '.coracao{width:12px;height:12px;position:fixed;background-color:#ff0000;transform:rotate(45deg)}.coracao::after,.coracao::before{content:"";width:inherit;height:inherit;background-color:inherit;border-radius:50%;position:absolute}.coracao::after{top:-6px}.coracao::before{left:-6px}';
    doc.head.appendChild(estilos);
  }

  function corAleatoria() {
    return 'rgb(' + Math.floor(Math.random() * 256) + ',' + Math.floor(Math.random() * 256) + ',' + Math.floor(Math.random() * 256) + ')';
  }

  inicializar();
})(document, window);

Exibição de Textos Decorativos em Evantos do Mouse

Nesta variação, em vez de corações, são exibidos textos ou emojis aleatórios. O código reutiliza a lógica de animação, mas adapta a criação de elementos para spans com conteúdo textual.

(function(doc, win) {
  var itensAnimados = [];
  var animFrame = win.requestAnimationFrame || function(cb) {
    setTimeout(cb, 16);
  };
  var listaTextos = ['(^_^)', '(T_T)', '(•‿•)', '♪♫', '(^o^)', '(*^*)', '(O_O)', '❤'];

  function inicializar() {
    adicionarEstilos();
    vincularEventos();
    iniciarLoopAnimacao();
  }

  function iniciarLoopAnimacao() {
    for (var i = 0; i < itensAnimados.length; i++) {
      var obj = itensAnimados[i];
      if (obj.transparencia <= 0) {
        doc.body.removeChild(obj.elemento);
        itensAnimados.splice(i, 1);
        continue;
      }
      obj.y -= 1;
      obj.escala += 0.004;
      obj.transparencia -= 0.013;
      obj.elemento.style.cssText = 'left:' + obj.x + 'px;top:' + obj.y + 'px;opacity:' + obj.transparencia + ';transform:scale(' + obj.escala + ');color:' + obj.cor;
    }
    animFrame(iniciarLoopAnimacao);
  }

  function vincularEventos() {
    var cliqueOriginal = win.onclick;
    win.onclick = function(evento) {
      if (cliqueOriginal) cliqueOriginal();
      gerarTexto(evento);
    };

    var tempoUltimoMov = Date.now();
    win.onmousemove = function(evento) {
      if (Date.now() - tempoUltimoMov > 100) {
        tempoUltimoMov = Date.now();
        gerarTexto(evento);
      }
    };
  }

  function gerarTexto(evento) {
    var span = doc.createElement('span');
    span.className = 'texto-animado';
    var indice = Math.floor(Math.random() * listaTextos.length);
    span.textContent = listaTextos[indice];
    itensAnimados.push({
      elemento: span,
      x: evento.clientX - 5,
      y: evento.clientY - 5,
      escala: 1,
      transparencia: 1,
      cor: corAleatoria()
    });
    doc.body.appendChild(span);
  }

  function adicionarEstilos() {
    var styleTag = doc.createElement('style');
    styleTag.textContent = '.texto-animado{position:fixed;font-size:14px;font-weight:bold}';
    doc.head.appendChild(styleTag);
  }

  function corAleatoria() {
    return 'rgb(' + Math.floor(Math.random() * 256) + ',' + Math.floor(Math.random() * 256) + ',' + Math.floor(Math.random() * 256) + ')';
  }

  inicializar();
})(document, window);

Tags: javascript CSS requestAnimationFrame DOM animation

Publicado em 6-17 19:38