You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(
originalImg,
songTitle = "Imagine",
artistName = "Audio Artist",
currentTime = "1:23",
totalTime = "3:45",
progress = 0.33
) {
const canvas = document.createElement('canvas');
const width = 540;
const height = 960;
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
// Helper: Draw image with object-fit: cover properties
function drawCover(img, x, y, w, h) {
const imgRatio = img.width / img.height;
const canvasRatio = w / h;
let sW, sH, sX, sY;
if (imgRatio > canvasRatio) {
sH = img.height;
sW = sH * canvasRatio;
sX = (img.width - sW) / 2;
sY = 0;
} else {
sW = img.width;
sH = sW / canvasRatio;
sX = 0;
sY = (img.height - sH) / 2;
}
ctx.drawImage(img, sX, sY, sW, sH, x, y, w, h);
}
// Helper: Create a path for a rounded rectangle
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();
}
// 1. Draw Blurred Background using the album art
ctx.filter = 'blur(40px)';
// Draw larger than screen to hide blurred uncolored edges
drawCover(originalImg, -60, -60, width + 120, height + 120);
ctx.filter = 'none';
// 2. Apply a Dark Overlay to make the interface readable
ctx.fillStyle = 'rgba(20, 20, 20, 0.6)';
ctx.fillRect(0, 0, width, height);
// 3. Draw Top Header Label
ctx.fillStyle = 'rgba(255, 255, 255, 0.7)';
ctx.font = '600 13px sans-serif';
ctx.textAlign = 'center';
if ("letterSpacing" in ctx) {
ctx.letterSpacing = '3px';
}
ctx.fillText('N O W P L A Y I N G', width / 2, 70);
if ("letterSpacing" in ctx) {
ctx.letterSpacing = '0px';
}
// 4. Draw Main Album Art
const artSize = 380;
const artX = (width - artSize) / 2;
const artY = 130;
const artRadius = 24;
// Album shadow
ctx.shadowColor = 'rgba(0, 0, 0, 0.5)';
ctx.shadowBlur = 40;
ctx.shadowOffsetY = 15;
roundRect(ctx, artX, artY, artSize, artSize, artRadius);
ctx.fillStyle = '#000000';
ctx.fill();
ctx.shadowColor = 'transparent';
// Album art filling (Uses a clipping mask for corners)
ctx.save();
roundRect(ctx, artX, artY, artSize, artSize, artRadius);
ctx.clip();
drawCover(originalImg, artX, artY, artSize, artSize);
ctx.restore();
// 5. Draw Track Details (Song Title & Artist)
ctx.textAlign = 'center';
ctx.fillStyle = '#ffffff';
ctx.font = 'bold 32px sans-serif';
// Use an 80px horizontal text padding overall
ctx.fillText(songTitle, width / 2, 590, width - 80);
ctx.fillStyle = '#b3b3b3';
ctx.font = '100 20px sans-serif';
ctx.fillText(artistName, width / 2, 630, width - 80);
// 6. Draw Progress Bar
const barX = 50;
const barY = 720;
const barW = width - 100;
const barH = 6;
const safeProgress = Math.max(0, Math.min(1, parseFloat(progress)));
// Track Background Line
ctx.fillStyle = 'rgba(255, 255, 255, 0.2)';
roundRect(ctx, barX, barY, barW, barH, barH / 2);
ctx.fill();
// Track Foreground Line
ctx.fillStyle = '#ffffff';
roundRect(ctx, barX, barY, barW * safeProgress, barH, barH / 2);
ctx.fill();
// Timestamps
ctx.font = '500 13px sans-serif';
ctx.fillStyle = '#b3b3b3';
ctx.textAlign = 'left';
ctx.fillText(currentTime, barX, barY + 28);
ctx.textAlign = 'right';
ctx.fillText(totalTime, barX + barW, barY + 28);
// Dragger / Handle
ctx.beginPath();
ctx.arc(barX + barW * safeProgress, barY + barH / 2, 8, 0, Math.PI * 2);
ctx.fillStyle = '#ffffff';
ctx.fill();
// 7. Draw Playback Controls (Play/Pause, Prev, Next)
const cy = 840; // Control Center Y
// Play/Pause Base
ctx.beginPath();
ctx.arc(width / 2, cy, 38, 0, Math.PI * 2);
ctx.fillStyle = '#ffffff';
ctx.fill();
// Pause Icon Bars
ctx.fillStyle = '#000000';
roundRect(ctx, width / 2 - 12, cy - 14, 8, 28, 2);
ctx.fill();
roundRect(ctx, width / 2 + 4, cy - 14, 8, 28, 2);
ctx.fill();
// Previous Track Button
ctx.fillStyle = '#ffffff';
ctx.beginPath();
ctx.moveTo(160, cy - 12);
ctx.lineTo(160, cy + 12);
ctx.lineTo(135, cy);
ctx.fill();
ctx.beginPath();
ctx.moveTo(135, cy - 12);
ctx.lineTo(135, cy + 12);
ctx.lineTo(110, cy);
ctx.fill();
roundRect(ctx, 106, cy - 12, 4, 24, 2);
ctx.fill();
// Next Track Button
ctx.beginPath();
ctx.moveTo(380, cy - 12);
ctx.lineTo(380, cy + 12);
ctx.lineTo(405, cy);
ctx.fill();
ctx.beginPath();
ctx.moveTo(405, cy - 12);
ctx.lineTo(405, cy + 12);
ctx.lineTo(430, cy);
ctx.fill();
roundRect(ctx, 430, cy - 12, 4, 24, 2);
ctx.fill();
// Return the generated UI image on the canvas
return canvas;
}
Apply Changes