You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, projectTitle = "Новый проект", director = "Стивен Спилберг", date = "24.10.2023", scene = "1", take = "1") {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// Ensure minimum width so the text fields render gracefully
let w = originalImg.width;
let h = originalImg.height;
if (w < 400) {
h = h * (400 / w);
w = 400;
}
// Scale clapper height based on width for cinematic proportions
const clapperHeight = Math.max(150, w * 0.25);
canvas.width = w;
canvas.height = h + clapperHeight;
const clapperStickHeight = clapperHeight * 0.08;
const gapHeight = clapperStickHeight * 0.2;
// Fill full canvas to ensure sharp borders
ctx.fillStyle = '#111111';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Draw the original image underneath the clapperboard
ctx.drawImage(originalImg, 0, clapperHeight, w, h);
// Helper function to draw the black & white clapper sticks
const drawSticks = (yOffset) => {
// Base white stick
ctx.fillStyle = '#e8e8e8';
ctx.fillRect(0, yOffset, w, clapperStickHeight);
// Diagonal black stripes
ctx.fillStyle = '#111111';
const stripeWidth = clapperStickHeight * 1.2;
for (let x = -clapperStickHeight; x < w; x += stripeWidth * 2) {
ctx.beginPath();
ctx.moveTo(x, yOffset + clapperStickHeight); // Bottom left
ctx.lineTo(x + stripeWidth, yOffset + clapperStickHeight); // Bottom right
ctx.lineTo(x + stripeWidth + clapperStickHeight, yOffset); // Top right slant
ctx.lineTo(x + clapperStickHeight, yOffset); // Top left slant
ctx.fill();
}
// Add a hinge bracket on the left side
ctx.fillStyle = '#2b2b2b';
ctx.fillRect(0, yOffset, clapperStickHeight * 1.5, clapperStickHeight);
// Red distinct hinge pin
ctx.fillStyle = '#a12323';
ctx.beginPath();
ctx.arc(clapperStickHeight * 0.75, yOffset + clapperStickHeight / 2, clapperStickHeight * 0.25, 0, Math.PI * 2);
ctx.fill();
};
// Draw top stick, a gap, and the bottom stick
drawSticks(0);
ctx.fillStyle = '#050505';
ctx.fillRect(0, clapperStickHeight, w, gapHeight);
drawSticks(clapperStickHeight + gapHeight);
// Board surface setup
const boardY = clapperStickHeight * 2 + gapHeight;
const boardHeight = clapperHeight - boardY;
// Dark slate gray finish for the board body
ctx.fillStyle = '#1a1c1e';
ctx.fillRect(0, boardY, w, boardHeight);
// Setup for borders and partition lines on the board
ctx.strokeStyle = '#d6d6d6';
ctx.lineWidth = Math.max(2, boardHeight * 0.015);
const pad = Math.max(10, w * 0.04);
// Pre-calculate grid positions
const line1Y = boardY + boardHeight * 0.35;
const line2Y = boardY + boardHeight * 0.65;
const midSectionWidth = w - 2 * pad;
const col1X = pad + midSectionWidth * 0.333;
const col2X = pad + midSectionWidth * 0.666;
const bottomPartY = line2Y;
const bottomPartHeight = boardY + boardHeight - bottomPartY;
const dirW = midSectionWidth * 0.5;
const camW = midSectionWidth * 0.25;
const dateW = midSectionWidth * 0.25;
const dirX = pad;
const camX = pad + dirW;
const dateX = camX + camW;
const bottomPadding = Math.min(pad, boardHeight * 0.1);
// Draw all separation lines
ctx.beginPath();
ctx.moveTo(pad, line1Y);
ctx.lineTo(w - pad, line1Y); // Top horizontal
ctx.moveTo(pad, line2Y);
ctx.lineTo(w - pad, line2Y); // Bottom horizontal
ctx.moveTo(col1X, line1Y);
ctx.lineTo(col1X, line2Y); // Scene divider
ctx.moveTo(col2X, line1Y);
ctx.lineTo(col2X, line2Y); // Take divider
ctx.moveTo(camX, line2Y);
ctx.lineTo(camX, boardY + boardHeight - bottomPadding); // Camera divider
ctx.moveTo(dateX, line2Y);
ctx.lineTo(dateX, boardY + boardHeight - bottomPadding); // Date divider
ctx.stroke();
// Helper Text Function to write chalk-styled information values
const drawText = (title, value, x, y, width, height) => {
// Label title (e.g. "PROD.", "DIRECTOR")
ctx.fillStyle = '#ababab';
ctx.font = `bold ${Math.max(8, boardHeight * 0.06)}px sans-serif`;
ctx.textAlign = 'left';
ctx.textBaseline = 'top';
ctx.fillText(title, x + boardHeight * 0.03, y + boardHeight * 0.03);
// Field value (e.g. User provided param)
ctx.fillStyle = '#ffffff';
let valSize = Math.max(12, height * 0.45);
ctx.font = `normal ${valSize}px "Comic Sans MS", "Chalkboard SE", sans-serif`;
// Downscale font size if text exceeds designated box limits
let textM = ctx.measureText(value);
if (textM.width > width * 0.9) {
valSize = valSize * (width * 0.9 / textM.width);
ctx.font = `normal ${valSize}px "Comic Sans MS", "Chalkboard SE", sans-serif`;
}
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(value, x + width / 2, y + height / 2 + height * 0.05);
};
// Populate the board fields based on user inputs
drawText("ПРОЕКТ", projectTitle, pad, boardY, midSectionWidth * 0.65, line1Y - boardY);
drawText("КАДР", "1", pad, line1Y, col1X - pad, line2Y - line1Y);
drawText("СЦЕНА", scene, col1X, line1Y, col2X - col1X, line2Y - line1Y);
drawText("ДУБЛЬ", take, col2X, line1Y, w - pad - col2X, line2Y - line1Y);
drawText("РЕЖИССЕР", director, dirX, line2Y, dirW, bottomPartHeight);
drawText("КАМЕРА", "A", camX, line2Y, camW, bottomPartHeight);
drawText("ДАТА", date, dateX, line2Y, dateW, bottomPartHeight);
// Brand it with the Movie Studio Name in the top right space
ctx.fillStyle = '#ffffff';
ctx.font = `bold ${Math.max(12, boardHeight * 0.07)}px sans-serif`;
ctx.textAlign = 'right';
ctx.textBaseline = 'top';
ctx.fillText("КИНОСТУДИЯ", w - pad, boardY + boardHeight * 0.04);
ctx.font = `italic ${Math.max(10, boardHeight * 0.05)}px sans-serif`;
ctx.fillStyle = '#ffcc00'; // distinct yellow accent
ctx.fillText("БАЗА ДАННЫХ", w - pad, boardY + boardHeight * 0.12);
return canvas;
}
Apply Changes