Você já se perguntou como sites criam aquelas imagens personalizadas a partir de textos que você digita? Hoje no Geek Codes, vamos abrir o capô desse código e ensinar você a criar um Emoji Status Creator.
Além de bonito, ele é funcional: você digita, escolhe o tema e baixa a imagem pronta para postar!
🧱 A Estrutura (HTML)
O HTML usa uma técnica interessante de contenteditable. Diferente de um campo de formulário comum (input), o contenteditable permite que qualquer div se torne editável, mantendo a estilização do CSS.
.content: É o nosso canvas. Tudo o que estiver dentro dela será capturado como imagem..emojis: Uma coleção de divs vazias que serão preenchidas via JavaScript.
🎨 O Design (CSS)
Aqui entra a mágica visual. Usamos Filtros de Desfoque (Blur) e Opacidade para criar profundidade.
- Blur & Opacidade: Os emojis de fundo têm
filter: blur(10px)eopacity: 0.2. Isso faz com que pareçam estar “longe” da câmera, focando o olhar do usuário no texto central. - Pseudo-elemento
:before: Usado para criar um “Placeholder” em elementos editáveis. Quando a div está vazia, o CSS injeta o texto “Escreva algo…”.
⚙️ A Lógica (JavaScript & jQuery)
Usamos o jQuery para facilitar a manipulação do DOM e a biblioteca html2canvas para a parte pesada.
- Troca Dinâmica: Quando você clica em um emoji da lista, o script percorre todas as 19 divs
.emojie muda o conteúdo interno delas instantaneamente usando.html(). - Captura de Tela: O
html2canvaslê o código HTML da sua div, entende o posicionamento do CSS e desenha tudo em um<canvas>do navegador, que depois exportamos como.png.
O Código Completo para Estudo
<!DOCTYPE html>
<html lang="pt-br">
<head>
<meta charset="UTF-8">
<title>Emoji Status Creator</title>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
<style>
body {
display: flex;
flex-direction: column;
background-color: #f0f2f5;
min-height: 100vh;
justify-content: center;
align-items: center;
margin: 0;
font-family: "Helvetica", Arial, sans-serif;
}
/* Container Principal do Status */
.content {
background: #FFFCF9;
width: 550px;
height: 412px;
border-radius: 10px;
overflow: hidden;
position: relative;
box-shadow: 0 10px 25px rgba(0,0,0,0.1);
margin: 20px auto;
}
.content .emojis {
position: relative;
pointer-events: none;
z-index: 1;
}
.content .emojis .emoji {
font-size: 4rem;
position: absolute;
left: -4rem;
}
/* Posicionamento dos Emojis (Mantido do original) */
.content .emojis .emoji:nth-child(1) { left: 150px; top: -28px; font-size: 3rem; filter: blur(10px); }
.content .emojis .emoji:nth-child(2) { left: 380px; top: -15px; font-size: 4.75rem; filter: blur(10px); opacity: 0.5; transform: rotate(10deg); }
.content .emojis .emoji:nth-child(3) { left: -20px; top: 100px; font-size: 3rem; filter: blur(10px); }
.content .emojis .emoji:nth-child(4) { left: 140px; top: 80px; font-size: 3.5rem; filter: blur(10px); opacity: 0.2; }
.content .emojis .emoji:nth-child(5) { left: 340px; top: 150px; font-size: 3.5rem; filter: blur(10px); opacity: 0.4; }
.content .emojis .emoji:nth-child(6) { left: 140px; top: 190px; font-size: 4rem; filter: blur(10px); opacity: 0.4; transform: rotate(20deg); }
.content .emojis .emoji:nth-child(7) { left: 390px; top: 280px; font-size: 3rem; filter: blur(10px); opacity: 0.6; }
.content .emojis .emoji:nth-child(8) { left: 30px; top: 330px; font-size: 4.5rem; filter: blur(10px); opacity: 0.4; transform: rotate(30deg); }
.content .emojis .emoji:nth-child(9) { left: 230px; top: 350px; font-size: 5rem; filter: blur(10px); opacity: 0.35; }
.content .emojis .emoji:nth-child(10) { left: 500px; top: 350px; font-size: 4rem; filter: blur(4px); transform: rotate(-20deg); opacity: 0.6; }
.content .emojis .emoji:nth-child(11) { left: 40px; top: 30px; font-size: 5rem; transform: rotate(-40deg); }
.content .emojis .emoji:nth-child(12) { left: 240px; top: 0; font-size: 5rem; }
.content .emojis .emoji:nth-child(13) { left: 505px; top: -5px; font-size: 3rem; transform: rotate(-10deg); }
.content .emojis .emoji:nth-child(14) { left: 440px; top: 120px; font-size: 3rem; transform: rotate(10deg); }
.content .emojis .emoji:nth-child(15) { left: -10px; top: 200px; font-size: 5rem; transform: rotate(10deg); }
.content .emojis .emoji:nth-child(16) { left: 460px; top: 240px; font-size: 4rem; transform: rotate(10deg); }
.content .emojis .emoji:nth-child(17) { left: 210px; top: 330px; font-size: 3rem; transform: rotate(-30deg); }
.content .emojis .emoji:nth-child(18) { left: 80px; top: 360px; font-size: 4rem; transform: rotate(-10deg); }
.content .emojis .emoji:nth-child(19) { left: 350px; top: 370px; font-size: 3rem; transform: rotate(10deg); }
.content .editor {
position: absolute;
text-align: center;
font-size: 2.2rem;
font-weight: 600;
width: 80%;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
z-index: 10;
outline: none;
color: #333;
}
[contenteditable=true]:empty:before {
content: attr(placeholder);
color: rgba(0, 0, 0, 0.2);
}
/* Seletor de Emojis */
.change {
display: flex;
justify-content: center;
font-size: 2.5rem;
margin-bottom: 10px;
}
.change .option {
margin: 0 10px;
cursor: pointer;
transition: transform 0.2s;
filter: grayscale(100%);
opacity: 0.5;
}
.change .option.active {
transform: scale(1.3);
filter: grayscale(0%);
opacity: 1;
}
/* Botão de Download */
.download-btn {
background-color: #007bff;
color: white;
border: none;
padding: 12px 30px;
border-radius: 25px;
font-size: 1rem;
font-weight: bold;
cursor: pointer;
transition: background 0.3s;
margin-top: 10px;
box-shadow: 0 4px 10px rgba(0,123,255,0.3);
}
.download-btn:hover {
background-color: #0056b3;
}
</style>
</head>
<body>
<div class="change">
<div data-emoji="😍" class="option">😍</div>
<div data-emoji="😜" class="option">😜</div>
<div data-emoji="🤔" class="option">🤔</div>
<div data-emoji="💩" class="option">💩</div>
<div data-emoji="💣" class="option">💣</div>
<div data-emoji="🍕" class="option">🍕</div>
</div>
<div class="content" id="capture">
<div class="emojis">
<div class="emoji"></div><div class="emoji"></div><div class="emoji"></div>
<div class="emoji"></div><div class="emoji"></div><div class="emoji"></div>
<div class="emoji"></div><div class="emoji"></div><div class="emoji"></div>
<div class="emoji"></div><div class="emoji"></div><div class="emoji"></div>
<div class="emoji"></div><div class="emoji"></div><div class="emoji"></div>
<div class="emoji"></div><div class="emoji"></div><div class="emoji"></div>
<div class="emoji"></div>
</div>
<div class="editor" contenteditable="true" placeholder="Escreva algo..."></div>
</div>
<button class="download-btn" id="download">Baixar Status</button>
<script>
$(document).ready(function () {
// Seleção de Emoji
$('[data-emoji]').click(function () {
$("[data-emoji]").removeClass("active");
$(this).addClass("active");
$(".emoji").html($(this).data("emoji"));
});
// Trigger inicial aleatório
const options = $('[data-emoji]');
$(options[Math.floor(Math.random() * options.length)]).trigger("click");
// Função de Download
$('#download').click(function() {
const btn = $(this);
btn.text('Gerando...');
// Captura a div .content como imagem
html2canvas(document.querySelector("#capture"), {
backgroundColor: null,
scale: 2 // Melhora a qualidade da imagem
}).then(canvas => {
const link = document.createElement('a');
link.download = 'meu-status.png';
link.href = canvas.toDataURL("image/png");
link.click();
btn.text('Baixar Status');
});
});
});
</script>
</body>
</html>
Deve ficar assim!

Que legal, adorei!