UNPKG

catozolala-card-canvas

Version:

Generate stylish welcome cards with Node.js and canvas

154 lines (136 loc) 4.93 kB
const { createCanvas, loadImage } = require('canvas'); const fs = require('fs'); async function drawWelcomeCard({ username = 'Nekotina', tag = '#0608', avatarURL, backgroundURL, date = 'Mar 30, 2018', isOnline = true }) { const width = 1024; const height = 350; const canvas = createCanvas(width, height); const ctx = canvas.getContext('2d'); // 1. Background const background = await loadImage(backgroundURL); ctx.drawImage(background, 0, 0, width, height); // gambar latar belakang ctx.fillStyle = 'rgba(0, 0, 0, 0.3)'; // lapisan hitam semi-transparan ctx.fillRect(0, 0, width, height); // tutupi seluruh canvas // 2. Overlay pink semi-transparan ctx.fillStyle = 'rgba(255, 128, 128, 0.2)'; ctx.fillRect(0, 0, width, height); // 3. Rounded border pink tepi const borderColor = '#f78284'; ctx.strokeStyle = borderColor; ctx.lineWidth = 12; ctx.beginPath(); roundRect(ctx, 0 + ctx.lineWidth/2, 0 + ctx.lineWidth/2, width - ctx.lineWidth, height - ctx.lineWidth, 30); ctx.stroke(); // 4. Avatar (bulat) di kiri const avatar = await loadImage(avatarURL); const avatarSize = 220; const avatarX = 50; const avatarY = 60; ctx.save(); ctx.beginPath(); ctx.arc(avatarX + avatarSize/2, avatarY + avatarSize/2, avatarSize/2, 0, Math.PI*2); ctx.closePath(); ctx.clip(); ctx.drawImage(avatar, avatarX, avatarY, avatarSize, avatarSize); ctx.restore(); // 5. Status online (lingkaran hijau) di kanan-bawah avatar ctx.fillStyle = isOnline ? '#2ecc71' : '#e74c3c'; ctx.beginPath(); ctx.arc(avatarX + avatarSize - 30, avatarY + avatarSize - 20, 24, 0, Math.PI*2); ctx.fill(); // 6. Username dengan drop-shadow ctx.fillStyle = '#ffffff'; ctx.font = 'bold 72px Sans'; ctx.textBaseline = 'top'; ctx.shadowColor = 'rgba(0,0,0,0.6)'; ctx.shadowOffsetX = 4; ctx.shadowOffsetY = 4; ctx.shadowBlur = 8; const nameX = avatarX + avatarSize + 30; // sekitar 270 const nameY = avatarY + 50; // sekitar 60 ctx.fillText(username, nameX, nameY); // 7. BOT-badge (rounded + icon centang) ctx.shadowColor = 'transparent'; // matikan sementara shadow const textWidth = ctx.measureText(username).width; const badgeX = nameX + textWidth + 20; const badgeY = nameY + 10; // sedikit naik agar vertikal seimbang const badgeW = 140; const badgeH = 60; const badgeRadius = 15; ctx.fillStyle = '#2d88ff'; // biru badge roundRectFill(ctx, badgeX, badgeY, badgeW, badgeH, badgeRadius); // icon centang putih & kata "BOT" ctx.fillStyle = '#ffffff'; ctx.font = 'bold 32px Sans'; ctx.textBaseline = 'middle'; ctx.fillText('✔ BOT', badgeX + 15, badgeY + badgeH/2); // 8. Tag (misal "#0608") dengan bayangan ringan ctx.fillStyle = '#e0e0e0'; ctx.font = 'bold 60px Sans'; ctx.shadowColor = 'rgba(0,0,0,0.4)'; ctx.shadowOffsetX = 2; ctx.shadowOffsetY = 2; ctx.shadowBlur = 6; const tagX = nameX; const tagY = nameY + 115; // sekitar 140 ctx.fillText(tag, tagX, tagY); // 9. Hapus shadow teks ctx.shadowColor = 'transparent'; // 10. (Opsional) Tambah ikon di pojok kanan atas—jika Anda punya URL/Path ikon // const icon1 = await loadImage('path/ke/ikon-curly-braces.png'); // const icon2 = await loadImage('path/ke/ikon-face.png'); // ctx.drawImage(icon1, width - 180, 20, 64, 64); // ctx.drawImage(icon2, width - 100, 20, 64, 64); // 11. Kotak tanggal (rounded rect + teks putih) const dateBoxW = 200; const dateBoxH = 50; const dateBoxX = width - dateBoxW - 30; const dateBoxY = height - dateBoxH - 30; ctx.fillStyle = 'rgba(0,0,0,0.5)'; roundRectFill(ctx, dateBoxX, dateBoxY, dateBoxW, dateBoxH, 15); ctx.fillStyle = '#ffffff'; ctx.font = '26px Sans'; ctx.textBaseline = 'middle'; ctx.fillText(date, dateBoxX + 20, dateBoxY + dateBoxH/2); // 12. Matikan semua shadow sebelum return ctx.shadowColor = 'transparent'; return canvas.toBuffer(); // mengembalikan Buffer PNG } // Fungsi untuk menggambar stroke rounded-rect function roundRect(ctx, x, y, w, h, r) { ctx.beginPath(); ctx.moveTo(x + r, y); ctx.lineTo(x + w - r, y); ctx.quadraticCurveTo(x + w, y, x + w, y + r); ctx.lineTo(x + w, y + h - r); ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h); ctx.lineTo(x + r, y + h); ctx.quadraticCurveTo(x, y + h, x, y + h - r); ctx.lineTo(x, y + r); ctx.quadraticCurveTo(x, y, x + r, y); ctx.closePath(); } // Fungsi untuk menggambar fill rounded-rect function roundRectFill(ctx, x, y, w, h, r) { ctx.beginPath(); ctx.moveTo(x + r, y); ctx.lineTo(x + w - r, y); ctx.quadraticCurveTo(x + w, y, x + w, y + r); ctx.lineTo(x + w, y + h - r); ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h); ctx.lineTo(x + r, y + h); ctx.quadraticCurveTo(x, y + h, x, y + h - r); ctx.lineTo(x, y + r); ctx.quadraticCurveTo(x, y, x + r, y); ctx.closePath(); ctx.fill(); } module.exports = { drawWelcomeCard }