You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, bibNumber = "42195", eventName = "МАРАФОН", runnerName = "БЕГУН", themeColor = "#D32F2F") {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// Set canvas dimensions to match the original image
canvas.width = originalImg.width;
canvas.height = originalImg.height;
// Draw the original image as background
ctx.drawImage(originalImg, 0, 0);
// Calculate dimensions for the Marathon Bib (Runners' race number)
const bibWidth = Math.min(canvas.width * 0.7, 800);
const bibHeight = bibWidth * 0.7; // Standard bib proportion
const bibX = (canvas.width - bibWidth) / 2;
// Place bib at the bottom with standard padding
const bibY = canvas.height - bibHeight - (canvas.height * 0.05);
const cornerRadius = bibWidth * 0.03;
// Helper function to draw rounded rectangles
function drawRoundRect(x, y, w, h, r, isFill) {
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();
if (isFill) {
ctx.fill();
} else {
ctx.stroke();
}
}
// 1. Draw Bib Shadow
ctx.shadowColor = 'rgba(0, 0, 0, 0.6)';
ctx.shadowBlur = bibWidth * 0.03;
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = bibWidth * 0.01;
// 2. Draw Bib Background (White card)
ctx.fillStyle = '#ffffff';
drawRoundRect(bibX, bibY, bibWidth, bibHeight, cornerRadius, true);
// Reset shadow for the rest of the drawing
ctx.shadowColor = 'transparent';
// 3. Draw Colored Header / Inner Border
const margin = bibWidth * 0.04;
// Colored header block at the top of the bib
ctx.fillStyle = themeColor;
const headerHeight = bibHeight * 0.25;
ctx.beginPath();
ctx.moveTo(bibX + cornerRadius, bibY);
ctx.lineTo(bibX + bibWidth - cornerRadius, bibY);
ctx.quadraticCurveTo(bibX + bibWidth, bibY, bibX + bibWidth, bibY + cornerRadius);
ctx.lineTo(bibX + bibWidth, bibY + headerHeight);
ctx.lineTo(bibX, bibY + headerHeight);
ctx.lineTo(bibX, bibY + cornerRadius);
ctx.quadraticCurveTo(bibX, bibY, bibX + cornerRadius, bibY);
ctx.closePath();
ctx.fill();
// Bottom barcode decoration
ctx.fillStyle = '#000000';
const barCodeWidth = bibWidth - (2 * margin);
const barCodeY = bibY + bibHeight - margin - (bibHeight * 0.08);
for(let i = 0; i < 40; i++) {
const barW = (Math.random() * 0.02 + 0.005) * bibWidth;
const barX = bibX + margin + (i / 40) * barCodeWidth;
if(barX + barW < bibX + bibWidth - margin) {
ctx.fillRect(barX, barCodeY, barW, bibHeight * 0.06);
}
}
// Outer border ring line
ctx.strokeStyle = '#e0e0e0';
ctx.lineWidth = bibWidth * 0.005;
drawRoundRect(bibX + margin / 2, bibY + margin / 2, bibWidth - margin, bibHeight - margin, cornerRadius * 0.5, false);
// 4. Draw Safety Pin Holes
ctx.fillStyle = '#333333';
const holeRadius = bibWidth * 0.015;
function drawHole(x, y) {
// Inner hole
ctx.beginPath();
ctx.arc(x, y, holeRadius, 0, Math.PI * 2);
ctx.fillStyle = '#000000';
ctx.fill();
// Pin ring reflection
ctx.beginPath();
ctx.arc(x, y, holeRadius * 1.5, 0, Math.PI * 2);
ctx.strokeStyle = '#aaaaaa';
ctx.lineWidth = holeRadius * 0.4;
ctx.stroke();
}
const hMargin = margin;
drawHole(bibX + hMargin, bibY + hMargin);
drawHole(bibX + bibWidth - hMargin, bibY + hMargin);
drawHole(bibX + hMargin, bibY + bibHeight - hMargin);
drawHole(bibX + bibWidth - hMargin, bibY + bibHeight - hMargin);
// 5. Draw Text Information
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
// Event Name (Header)
ctx.fillStyle = '#ffffff';
ctx.font = `900 ${bibHeight * 0.15}px "Impact", "Arial Black", sans-serif`;
ctx.fillText(eventName.toUpperCase(), canvas.width / 2, bibY + (headerHeight / 2));
// Bib Number (Center)
ctx.fillStyle = '#111111';
ctx.font = `bold ${bibHeight * 0.4}px "Impact", "Arial Black", sans-serif`;
ctx.fillText(bibNumber, canvas.width / 2, bibY + (bibHeight * 0.55));
// Runner Name (Bottom)
ctx.fillStyle = '#555555';
ctx.font = `bold ${bibHeight * 0.1}px Arial, sans-serif`;
ctx.fillText(runnerName.toUpperCase(), canvas.width / 2, bibY + bibHeight - margin - (bibHeight * 0.15));
return canvas;
}
Apply Changes