catozolala-card-canvas
Version:
Generate stylish welcome cards with Node.js and canvas
154 lines (136 loc) • 4.93 kB
JavaScript
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
}