You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(
originalImg,
websiteUrl = "https://www.example.com",
theme = "light",
backgroundColor = "#e0e5ec",
outerPadding = "50",
cornerRadius = "12"
) {
// Parse numeric inputs securely
outerPadding = parseInt(outerPadding, 10) || 0;
cornerRadius = parseInt(cornerRadius, 10) || 0;
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// Configuration for the browser top bar
const topBarHeight = 50;
const windowWidth = originalImg.width;
const windowHeight = originalImg.height + topBarHeight;
// Apply dimensions including outer background padding for the mockup presentation
canvas.width = windowWidth + outerPadding * 2;
canvas.height = windowHeight + outerPadding * 2;
// 1. Draw outer presentation background
if (backgroundColor && backgroundColor.toLowerCase() !== "transparent" && backgroundColor.toLowerCase() !== "none") {
ctx.fillStyle = backgroundColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
} else {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
// Helper function to draw rounded rectangles
function roundRect(x, y, w, h, r) {
if (w < 2 * r) r = w / 2;
if (h < 2 * r) r = h / 2;
ctx.beginPath();
ctx.moveTo(x + r, y);
ctx.arcTo(x + w, y, x + w, y + h, r);
ctx.arcTo(x + w, y + h, x, y + h, r);
ctx.arcTo(x, y + h, x, y, r);
ctx.arcTo(x, y, x + w, y, r);
ctx.closePath();
}
// 2. Set Theme Colors
const isDark = theme.toLowerCase() === "dark";
const topBarColor = isDark ? "#2d2d2d" : "#f6f6f6";
const addressBarColor = isDark ? "#1a1a1a" : "#ffffff";
const textColor = isDark ? "#cccccc" : "#333333";
const topBarBorderColor = isDark ? "#404040" : "#cbd5e1";
const winX = outerPadding;
const winY = outerPadding;
// 3. Draw Browser Window Shadow and Base
ctx.save();
roundRect(winX, winY, windowWidth, windowHeight, cornerRadius);
ctx.shadowColor = "rgba(0, 0, 0, 0.15)";
ctx.shadowBlur = 30;
ctx.shadowOffsetY = 15;
ctx.fillStyle = topBarColor;
ctx.fill();
ctx.restore();
// 4. Keep contents inside the rounded corners
ctx.save();
roundRect(winX, winY, windowWidth, windowHeight, cornerRadius);
ctx.clip();
// Draw top bar solid background (ensuring opacity)
ctx.fillStyle = topBarColor;
ctx.fillRect(winX, winY, windowWidth, topBarHeight);
// Draw subtle dividing line at bottom of the top bar
ctx.fillStyle = topBarBorderColor;
ctx.fillRect(winX, winY + topBarHeight - 1, windowWidth, 1);
// 5. Draw Window Controls (Traffic Lights like macOS)
const dotRadius = 6;
const dotSpacing = 8;
let dotX = winX + 16;
const dotY = winY + topBarHeight / 2;
if (windowWidth > 120) {
// Red dot (Close)
ctx.beginPath();
ctx.arc(dotX + dotRadius, dotY, dotRadius, 0, Math.PI * 2);
ctx.fillStyle = "#ff5f56";
ctx.fill();
// Yellow dot (Minimize)
dotX += dotRadius * 2 + dotSpacing;
ctx.beginPath();
ctx.arc(dotX + dotRadius, dotY, dotRadius, 0, Math.PI * 2);
ctx.fillStyle = "#ffbd2e";
ctx.fill();
// Green dot (Maximize)
dotX += dotRadius * 2 + dotSpacing;
ctx.beginPath();
ctx.arc(dotX + dotRadius, dotY, dotRadius, 0, Math.PI * 2);
ctx.fillStyle = "#27c93f";
ctx.fill();
}
// 6. Draw Address Bar
const controlsWidth = 16 + (dotRadius * 6) + (dotSpacing * 2) + 16;
const maxBarWidth = windowWidth - (controlsWidth * 2);
if (maxBarWidth > 60) {
let barWidth = Math.min(450, maxBarWidth);
let barHeight = 28;
let barX = winX + (windowWidth - barWidth) / 2;
let barY = winY + (topBarHeight - barHeight) / 2;
// Address bar background
ctx.fillStyle = addressBarColor;
roundRect(barX, barY, barWidth, barHeight, 6);
ctx.fill();
// Address bar subtle border
ctx.strokeStyle = topBarBorderColor;
ctx.lineWidth = 1;
ctx.stroke();
// 7. Draw URL Text String
ctx.fillStyle = textColor;
ctx.font = "13px -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
let displayUrl = websiteUrl || "";
let textWidth = ctx.measureText(displayUrl).width;
// Automatically hide or truncate URL if text overflows address bar
if (textWidth > barWidth - 50) {
while (textWidth > barWidth - 50 && displayUrl.length > 3) {
displayUrl = displayUrl.slice(0, -1);
textWidth = ctx.measureText(displayUrl + "...").width;
}
displayUrl += "...";
}
ctx.fillText(displayUrl, barX + barWidth / 2, barY + barHeight / 2 + 1);
// Draw standard Lock symbol indicating HTTPS
const textStartX = barX + barWidth / 2 - ctx.measureText(displayUrl).width / 2;
const lockX = textStartX - 14;
const lockY = barY + barHeight / 2;
ctx.save();
ctx.translate(lockX, lockY);
ctx.strokeStyle = textColor;
ctx.fillStyle = textColor;
ctx.lineWidth = 1.2;
// Lock body (Rectangle)
ctx.fillRect(-3.5, -0.5, 7, 5);
// Lock shackle (Arc)
ctx.beginPath();
ctx.arc(0, -0.5, 2.2, Math.PI, 0);
ctx.stroke();
ctx.restore();
}
// 8. Render the Original Inner Browser Content (Website Screen)
ctx.drawImage(originalImg, winX, winY + topBarHeight, originalImg.width, originalImg.height);
// End bounds clipping
ctx.restore();
return canvas;
}
Apply Changes