You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(
originalImg,
userText = "Почему вы вымерли?",
dinoText = "Метеорит. И мы не делали бэкапы.",
bgColor = "#f4f4f5",
bubbleColor = "#ffffff",
textColor = "#1f2937",
dinoEmoji = "🦖"
) {
const canvas = document.createElement('canvas');
canvas.width = 800;
canvas.height = 600;
const ctx = canvas.getContext('2d');
// Draw background
ctx.fillStyle = bgColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Helper: Draw speech bubble
const drawBubble = (text, startX, startY, maxWidth, tailX, tailY) => {
ctx.font = "22px Arial, sans-serif";
const words = (text || "").split(' ');
let line = '';
const lines = [];
// Simple word wrap
for (let n = 0; n < words.length; n++) {
const testLine = line + words[n] + ' ';
const metrics = ctx.measureText(testLine);
if (metrics.width > maxWidth - 40 && n > 0) {
lines.push(line);
line = words[n] + ' ';
} else {
line = testLine;
}
}
lines.push(line);
const lineHeight = 30;
const bubbleHeight = lines.length * lineHeight + 40;
const r = 20; // border radius
const w = maxWidth;
const h = bubbleHeight;
const x = startX;
const y = startY;
// Draw bubble tail and shadow
ctx.shadowColor = "rgba(0,0,0,0.1)";
ctx.shadowBlur = 10;
ctx.shadowOffsetY = 4;
ctx.fillStyle = bubbleColor;
ctx.strokeStyle = "#cbd5e1";
ctx.lineWidth = 2;
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);
// Tail pointing to character
const tailBaseLeft = x + w / 2 - 15;
const tailBaseRight = x + w / 2 + 15;
ctx.lineTo(tailBaseRight, y + h);
ctx.lineTo(tailX, tailY);
ctx.lineTo(tailBaseLeft, 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();
ctx.shadowColor = "transparent"; // Reset shadow for stroke
ctx.stroke();
// Draw text
ctx.fillStyle = textColor;
ctx.textAlign = "center";
ctx.textBaseline = "middle";
const textStartY = y + (h / 2) - ((lines.length - 1) * lineHeight / 2);
for (let i = 0; i < lines.length; i++) {
ctx.fillText(lines[i].trim(), x + w / 2, textStartY + (i * lineHeight));
}
};
// Left Side: Original Image scaling (User) - Center X = 200, Y = 450
const maxImgDim = 260;
const imgRatio = Math.min(maxImgDim / originalImg.width, maxImgDim / originalImg.height);
const imgW = originalImg.width * imgRatio;
const imgH = originalImg.height * imgRatio;
// Add border to original image
ctx.fillStyle = "#ffffff";
ctx.shadowColor = "rgba(0,0,0,0.15)";
ctx.shadowBlur = 8;
ctx.fillRect(200 - imgW / 2 - 10, 450 - imgH / 2 - 10, imgW + 20, imgH + 20);
ctx.shadowColor = "transparent";
ctx.drawImage(originalImg, 200 - imgW / 2, 450 - imgH / 2, imgW, imgH);
// Right Side: Dinosaur Emoji - Center X = 600, Y = 450
ctx.font = "200px 'Segoe UI Emoji', 'Apple Color Emoji', 'Noto Color Emoji', sans-serif";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText(dinoEmoji, 600, 450);
// Draw Speech Bubbles
// User bubble pointing dynamically to the top-center of the uploaded image
drawBubble(userText, 50, 60, 300, 200, 450 - imgH / 2 - 30);
// Dinosaur bubble pointing to the dinosaur emoji
drawBubble(dinoText, 450, 60, 300, 600, 330);
return canvas;
}
Apply Changes