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);