You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, remoteColorStr = "#2c2c2c", buttonColorStr = "#4a4a4a", stepSizeStr = "25", zoomFactorStr = "1.2") {
const stepSize = parseFloat(stepSizeStr) || 25;
const zoomFactor = parseFloat(zoomFactorStr) || 1.2;
const container = document.createElement('div');
container.style.display = 'flex';
container.style.flexWrap = 'wrap';
container.style.alignItems = 'center';
container.style.justifyContent = 'center';
container.style.gap = '30px';
container.style.padding = '20px';
container.style.background = '#e9ecef';
container.style.fontFamily = 'Arial, sans-serif';
container.style.borderRadius = '10px';
const canvasContainer = document.createElement('div');
canvasContainer.style.border = '10px solid #111';
canvasContainer.style.background = '#000';
canvasContainer.style.borderRadius = '8px';
canvasContainer.style.boxShadow = '0 10px 30px rgba(0,0,0,0.5)';
canvasContainer.style.overflow = 'hidden';
canvasContainer.style.display = 'flex';
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// Calculate sensible canvas dimensions
const maxWidth = 800;
const maxHeight = 600;
let baseRatio = 1;
if (originalImg.width > maxWidth || originalImg.height > maxHeight) {
baseRatio = Math.min(maxWidth / originalImg.width, maxHeight / originalImg.height);
}
// Setting canvas size relative to the base ratio
canvas.width = originalImg.width * baseRatio;
canvas.height = originalImg.height * baseRatio;
canvasContainer.appendChild(canvas);
// Initial interactive state
let state = {
tx: 0,
ty: 0,
scale: baseRatio,
rotation: 0
};
let isPowerOn = true;
function draw() {
// Clear screen with black TV background
ctx.fillStyle = '#111';
ctx.fillRect(0, 0, canvas.width, canvas.height);
if (!isPowerOn) return;
ctx.save();
// Translate to the absolute pan position
ctx.translate(canvas.width / 2 + state.tx, canvas.height / 2 + state.ty);
// Apply zoom and rotation
ctx.scale(state.scale, state.scale);
ctx.rotate(state.rotation);
ctx.drawImage(
originalImg,
-originalImg.width / 2,
-originalImg.height / 2,
originalImg.width,
originalImg.height
);
ctx.restore();
}
// Remote Control "Пульт" UI construction
const remote = document.createElement('div');
remote.style.background = remoteColorStr;
remote.style.borderRadius = '20px';
remote.style.padding = '20px';
remote.style.display = 'flex';
remote.style.flexDirection = 'column';
remote.style.alignItems = 'center';
remote.style.gap = '20px';
remote.style.boxShadow = 'inset -2px -2px 10px rgba(0,0,0,0.5), inset 2px 2px 10px rgba(255,255,255,0.1), 0 15px 25px rgba(0,0,0,0.6)';
remote.style.width = '140px';
remote.style.userSelect = 'none';
// Power Button Row
const pwrContainer = document.createElement('div');
pwrContainer.style.width = '100%';
pwrContainer.style.display = 'flex';
pwrContainer.style.justifyContent = 'flex-end';
const powerBtn = document.createElement('button');
powerBtn.textContent = '⏻';
powerBtn.style.background = '#d9534f';
powerBtn.style.color = '#fff';
powerBtn.style.border = 'none';
powerBtn.style.cursor = 'pointer';
powerBtn.style.width = '30px';
powerBtn.style.height = '30px';
powerBtn.style.borderRadius = '50%';
powerBtn.style.boxShadow = '0 4px 6px rgba(0,0,0,0.3)';
powerBtn.style.transition = 'transform 0.1s';
powerBtn.onmousedown = () => powerBtn.style.transform = 'scale(0.9)';
powerBtn.onmouseup = () => powerBtn.style.transform = 'scale(1)';
powerBtn.onmouseleave = () => powerBtn.style.transform = 'scale(1)';
powerBtn.addEventListener('click', () => {
isPowerOn = !isPowerOn;
draw();
});
pwrContainer.appendChild(powerBtn);
remote.appendChild(pwrContainer);
// Title
const title = document.createElement('div');
title.textContent = 'ПУЛЬТ';
title.style.color = '#ccc';
title.style.fontWeight = 'bold';
title.style.letterSpacing = '3px';
title.style.fontSize = '14px';
title.style.textShadow = '1px 1px 2px rgba(0,0,0,0.8)';
remote.appendChild(title);
// Button Factory
function createBtn(text, onClick, isRound = true) {
const btn = document.createElement('button');
btn.textContent = text;
btn.style.background = buttonColorStr;
btn.style.color = '#fff';
btn.style.border = '1px solid rgba(0,0,0,0.3)';
btn.style.cursor = 'pointer';
btn.style.fontWeight = 'bold';
btn.style.fontSize = '14px';
btn.style.display = 'flex';
btn.style.justifyContent = 'center';
btn.style.alignItems = 'center';
btn.style.boxShadow = 'inset 1px 1px 2px rgba(255,255,255,0.1), 0 4px 6px rgba(0,0,0,0.5)';
btn.style.transition = 'transform 0.1s, box-shadow 0.1s';
if (isRound) {
btn.style.width = '40px';
btn.style.height = '40px';
btn.style.borderRadius = '50%';
} else {
btn.style.width = '100%';
btn.style.padding = '10px 0';
btn.style.borderRadius = '8px';
}
btn.onmousedown = () => {
btn.style.transform = 'translateY(2px) scale(0.95)';
btn.style.boxShadow = '0 2px 3px rgba(0,0,0,0.5)';
};
btn.onmouseup = () => {
btn.style.transform = 'translateY(0) scale(1)';
btn.style.boxShadow = 'inset 1px 1px 2px rgba(255,255,255,0.1), 0 4px 6px rgba(0,0,0,0.5)';
};
btn.onmouseleave = () => {
btn.style.transform = 'translateY(0) scale(1)';
btn.style.boxShadow = 'inset 1px 1px 2px rgba(255,255,255,0.1), 0 4px 6px rgba(0,0,0,0.5)';
};
btn.addEventListener('click', () => {
if (isPowerOn) {
onClick();
draw();
}
});
return btn;
}
// Directional Pad (D-Pad)
const dpad = document.createElement('div');
dpad.style.display = 'grid';
dpad.style.gridTemplateColumns = '40px 40px 40px';
dpad.style.gridTemplateRows = '40px 40px 40px';
dpad.style.gap = '5px';
const up = createBtn('▲', () => state.ty -= stepSize);
const down = createBtn('▼', () => state.ty += stepSize);
const left = createBtn('◀', () => state.tx -= stepSize);
const right = createBtn('▶', () => state.tx += stepSize);
// Center Reset button
const center = createBtn('●', () => {
state.tx = 0;
state.ty = 0;
state.scale = baseRatio;
state.rotation = 0;
});
center.style.background = '#888';
center.style.color = '#222';
up.style.gridColumn = '2'; up.style.gridRow = '1';
left.style.gridColumn = '1'; left.style.gridRow = '2';
center.style.gridColumn = '2'; center.style.gridRow = '2';
right.style.gridColumn = '3'; right.style.gridRow = '2';
down.style.gridColumn = '2'; down.style.gridRow = '3';
[up, left, center, right, down].forEach(b => dpad.appendChild(b));
remote.appendChild(dpad);
// Zoom & Rotate Buttons
const actionsRow1 = document.createElement('div');
actionsRow1.style.display = 'flex';
actionsRow1.style.justifyContent = 'space-between';
actionsRow1.style.width = '100%';
actionsRow1.style.gap = '10px';
const zoomIn = createBtn('+', () => state.scale *= zoomFactor, false);
const zoomOut = createBtn('-', () => state.scale /= zoomFactor, false);
actionsRow1.appendChild(zoomOut);
actionsRow1.appendChild(zoomIn);
remote.appendChild(actionsRow1);
const actionsRow2 = document.createElement('div');
actionsRow2.style.display = 'flex';
actionsRow2.style.justifyContent = 'space-between';
actionsRow2.style.width = '100%';
actionsRow2.style.gap = '10px';
const rotLeft = createBtn('↺', () => state.rotation -= Math.PI / 12, false);
const rotRight = createBtn('↻', () => state.rotation += Math.PI / 12, false);
actionsRow2.appendChild(rotLeft);
actionsRow2.appendChild(rotRight);
remote.appendChild(actionsRow2);
// Assemble components
container.appendChild(canvasContainer);
container.appendChild(remote);
// Render the initial state
draw();
return container;
}
Apply Changes