You can edit the below JavaScript code to customize the image tool.
Apply Changes
async function processImage(originalImg, deviceColor = '#aaaaaa', backgroundColor = '#e0eafc,#cfdef3', scenePadding = 0.15) {
const V_WIDTH = 1200;
const V_HEIGHT = 800;
const canvas = document.createElement('canvas');
canvas.width = V_WIDTH;
canvas.height = V_HEIGHT;
const ctx = canvas.getContext('2d');
// 1. Draw Background
const bgColors = backgroundColor.split(',').map(c => c.trim());
const grad = ctx.createLinearGradient(0, 0, 0, V_HEIGHT);
grad.addColorStop(0, bgColors[0] || '#e0eafc');
grad.addColorStop(1, bgColors[1] || bgColors[0] || '#cfdef3');
ctx.fillStyle = grad;
ctx.fillRect(0, 0, V_WIDTH, V_HEIGHT);
// 2. Define Device (Laptop) dimensions
const contentWidth = V_WIDTH * (1 - scenePadding * 2);
const contentHeight = V_HEIGHT * (1 - scenePadding * 2);
// Let's model a modern laptop
const deviceAspectRatio = 16 / 10;
let deviceWidth, deviceHeight;
if (contentWidth / contentHeight > deviceAspectRatio) {
deviceHeight = contentHeight;
deviceWidth = deviceHeight * deviceAspectRatio;
} else {
deviceWidth = contentWidth;
deviceHeight = deviceWidth / deviceAspectRatio;
}
const deviceX = (V_WIDTH - deviceWidth) / 2;
const deviceY = (V_HEIGHT - deviceHeight) / 2;
const cornerRadius = deviceWidth * 0.02;
const bezel = deviceWidth * 0.025;
const baseHeight = deviceWidth * 0.01;
const hingeGap = baseHeight * 0.2;
const screenWidth = deviceWidth;
const screenHeight = deviceHeight - baseHeight;
// Helper function for rounded rectangles
const roundedRect = (x, y, width, height, radius) => {
ctx.beginPath();
ctx.moveTo(x + radius, y);
ctx.lineTo(x + width - radius, y);
ctx.arcTo(x + width, y, x + width, y + radius, radius);
ctx.lineTo(x + width, y + height - radius);
ctx.arcTo(x + width, y + height, x + width - radius, y + height, radius);
ctx.lineTo(x + radius, y + height);
ctx.arcTo(x, y + height, x, y + height - radius, radius);
ctx.lineTo(x, y + radius);
ctx.arcTo(x, y, x + radius, y, radius);
ctx.closePath();
};
// 3. Draw Device Shadow
ctx.save();
ctx.shadowColor = 'rgba(0,0,0,0.2)';
ctx.shadowBlur = 40;
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 20;
// 4. Draw Device Body
ctx.fillStyle = deviceColor;
// Lid
roundedRect(deviceX, deviceY, screenWidth, screenHeight, cornerRadius);
ctx.fill();
// Base
ctx.beginPath();
const baseTop = deviceY + screenHeight - hingeGap;
const baseCornerRadius = cornerRadius * 0.5;
ctx.moveTo(deviceX, baseTop);
ctx.lineTo(deviceX + deviceWidth, baseTop);
ctx.lineTo(deviceX + deviceWidth, baseTop + baseHeight - baseCornerRadius);
ctx.arcTo(deviceX + deviceWidth, baseTop + baseHeight, deviceX + deviceWidth - baseCornerRadius, baseTop + baseHeight, baseCornerRadius);
ctx.lineTo(deviceX + baseCornerRadius, baseTop + baseHeight);
ctx.arcTo(deviceX, baseTop + baseHeight, deviceX, baseTop + baseHeight - baseCornerRadius, baseCornerRadius);
ctx.closePath();
ctx.fill();
ctx.restore();
// 5. Place the user's image onto the screen
const screenInnerX = deviceX + bezel;
const screenInnerY = deviceY + bezel;
const screenInnerWidth = screenWidth - bezel * 2;
const screenInnerHeight = screenHeight - bezel * 2.5;
// Create a clipping path for the screen content
ctx.save();
roundedRect(screenInnerX, screenInnerY, screenInnerWidth, screenInnerHeight, cornerRadius * 0.5);
ctx.clip();
// Calculate aspect ratios to "cover" the screen area
const imgRatio = originalImg.width / originalImg.height;
const screenRatio = screenInnerWidth / screenInnerHeight;
let sx = 0,
sy = 0,
sWidth = originalImg.width,
sHeight = originalImg.height;
if (imgRatio > screenRatio) { // Image is wider than screen
sWidth = originalImg.height * screenRatio;
sx = (originalImg.width - sWidth) / 2;
} else { // Image is taller or same aspect ratio
sHeight = originalImg.width / screenRatio;
sy = (originalImg.height - sHeight) / 2;
}
ctx.drawImage(originalImg, sx, sy, sWidth, sHeight, screenInnerX, screenInnerY, screenInnerWidth, screenInnerHeight);
ctx.restore();
// 6. Draw Details
// Webcam
ctx.fillStyle = '#111111';
ctx.beginPath();
ctx.arc(deviceX + screenWidth / 2, deviceY + bezel / 2, bezel * 0.15, 0, Math.PI * 2);
ctx.fill();
// Notch on the base
const notchWidth = deviceWidth * 0.15;
const notchHeight = baseHeight * 0.2;
ctx.fillStyle = 'rgba(0,0,0,0.1)';
ctx.beginPath();
ctx.moveTo(deviceX + deviceWidth / 2 - notchWidth / 2, deviceY + screenHeight - hingeGap);
ctx.lineTo(deviceX + deviceWidth / 2 + notchWidth / 2, deviceY + screenHeight - hingeGap);
ctx.lineTo(deviceX + deviceWidth / 2 + notchWidth / 2, deviceY + screenHeight - hingeGap + notchHeight);
ctx.arcTo(
deviceX + deviceWidth / 2, deviceY + screenHeight,
deviceX + deviceWidth / 2 - notchWidth / 2, deviceY + screenHeight - hingeGap + notchHeight,
notchHeight
);
ctx.lineTo(deviceX + deviceWidth / 2 - notchWidth / 2, deviceY + screenHeight - hingeGap + notchHeight);
ctx.closePath();
ctx.fill();
return canvas;
}
Apply Changes