You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, frameColor = '#FF3366', frameThickness = '60', applyToyFilter = 'true', customText = 'Любимая игрушка') {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// Parse parameters robustly
const ft = parseInt(frameThickness, 10) || 60;
const isFilterActive = String(applyToyFilter).toLowerCase() === 'true' || applyToyFilter === '1' || applyToyFilter === 1;
const color = typeof frameColor === 'string' ? frameColor : '#FF3366';
const textLabel = typeof customText === 'string' ? customText : 'Любимая игрушка';
const w = originalImg.width;
const h = originalImg.height;
// Resize canvas to fit the image plus the toy frame
canvas.width = w + ft * 2;
canvas.height = h + ft * 2;
// --- 1. Draw Outer Plastic Frame ---
ctx.fillStyle = color;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Mitered 3D Bevel for the frame (Top & Left: Highlight)
ctx.fillStyle = 'rgba(255, 255, 255, 0.35)';
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(canvas.width, 0);
ctx.lineTo(canvas.width - ft, ft);
ctx.lineTo(ft, ft);
ctx.fill();
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(ft, ft);
ctx.lineTo(ft, canvas.height - ft);
ctx.lineTo(0, canvas.height);
ctx.fill();
// Mitered 3D Bevel for the frame (Bottom & Right: Shadow)
ctx.fillStyle = 'rgba(0, 0, 0, 0.25)';
ctx.beginPath();
ctx.moveTo(0, canvas.height);
ctx.lineTo(ft, canvas.height - ft);
ctx.lineTo(canvas.width - ft, canvas.height - ft);
ctx.lineTo(canvas.width, canvas.height);
ctx.fill();
ctx.beginPath();
ctx.moveTo(canvas.width, 0);
ctx.lineTo(canvas.width - ft, ft);
ctx.lineTo(canvas.width - ft, canvas.height - ft);
ctx.lineTo(canvas.width, canvas.height);
ctx.fill();
// --- 2. Draw the Image (with Toy Camera effect if desired) ---
ctx.save();
if (isFilterActive) {
// High contrast, high saturation, slight sepia for retro lomo aesthetics
ctx.filter = `contrast(130%) saturate(160%) sepia(30%) brightness(95%)`;
}
// Draw image inside the frame limits
ctx.drawImage(originalImg, ft, ft, w, h);
ctx.restore();
// --- 3. Toy Filter Overlay Effects (Vignette & Light Leak) ---
if (isFilterActive) {
// Lens Vignette
const centerX = ft + w / 2;
const centerY = ft + h / 2;
const radius = Math.sqrt((w / 2) ** 2 + (h / 2) ** 2);
const gradient = ctx.createRadialGradient(
centerX, centerY, radius * 0.4,
centerX, centerY, radius
);
gradient.addColorStop(0, 'rgba(0,0,0,0)');
gradient.addColorStop(1, 'rgba(0,0,0,0.85)');
ctx.fillStyle = gradient;
ctx.fillRect(ft, ft, w, h);
// Fake Light Leak Overlay
const leakGrad = ctx.createLinearGradient(ft, ft, ft + w * 0.4, ft + h * 0.5);
leakGrad.addColorStop(0, 'rgba(255, 60, 0, 0.45)');
leakGrad.addColorStop(0.5, 'rgba(255, 0, 150, 0.15)');
leakGrad.addColorStop(1, 'rgba(0, 0, 0, 0)');
ctx.globalCompositeOperation = 'screen';
ctx.fillStyle = leakGrad;
ctx.fillRect(ft, ft, w, h);
ctx.globalCompositeOperation = 'source-over';
}
// --- 4. Inner Bevel Cutout (Depth transition to the image) ---
const innerDepth = Math.max(2, ft * 0.1);
// Top & Left inner shadow
ctx.fillStyle = 'rgba(0, 0, 0, 0.6)';
ctx.fillRect(ft, ft, w, innerDepth); // Top
ctx.fillRect(ft, ft, innerDepth, h); // Left
// Bottom & Right inner highlight
ctx.fillStyle = 'rgba(255, 255, 255, 0.4)';
ctx.fillRect(ft, ft + h - innerDepth, w, innerDepth); // Bottom
ctx.fillRect(ft + w - innerDepth, ft, innerDepth, h); // Right
// --- 5. Frame Decorations (Screws and Text) ---
// Toy Screws in the 4 corners
const offset = ft / 2;
const screwRadius = Math.max(3, Math.min(ft * 0.15, 12));
const corners = [
[offset, offset],
[canvas.width - offset, offset],
[offset, canvas.height - offset],
[canvas.width - offset, canvas.height - offset]
];
corners.forEach(([cx, cy]) => {
ctx.fillStyle = 'rgba(0, 0, 0, 0.4)';
ctx.beginPath();
ctx.arc(cx, cy, screwRadius, 0, Math.PI * 2);
ctx.fill();
ctx.strokeStyle = 'rgba(0, 0, 0, 0.6)';
ctx.lineWidth = screwRadius * 0.4;
ctx.beginPath();
// Angled screw slot
ctx.moveTo(cx - screwRadius * 0.6, cy - screwRadius * 0.6);
ctx.lineTo(cx + screwRadius * 0.6, cy + screwRadius * 0.6);
ctx.stroke();
});
// "Favorite Toy" Text
if (textLabel.trim() !== '') {
const fontSize = Math.max(14, Math.min(ft * 0.5, canvas.width * 0.1));
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.font = `bold ${fontSize}px "Comic Sans MS", "Chalkboard SE", "Arial Rounded MT Bold", sans-serif`;
const textX = canvas.width / 2;
const textY = offset; // Place in the top section of the frame
// Engraved text effect
ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
ctx.fillText(textLabel, textX + 2, textY + 2); // Shadow
ctx.fillStyle = '#FFFFFF';
ctx.fillText(textLabel, textX, textY); // Light base
}
return canvas;
}
Apply Changes