You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, bgColor = "#2d2d2d", overlayText = "🐿️ Белка Image Viewer") {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// Set maximum dimensions for the viewer
const MAX_WIDTH = 1024;
const MAX_HEIGHT = 800;
// Calculate canvas size based on original image, capped at max dimensions
canvas.width = Math.min(originalImg.width, MAX_WIDTH);
canvas.height = Math.min(originalImg.height, MAX_HEIGHT);
// Ensure the initial view fits the entire image neatly within the canvas
const initialScale = Math.min(canvas.width / originalImg.width, canvas.height / originalImg.height);
let scale = initialScale;
let posX = (canvas.width - originalImg.width * scale) / 2;
let posY = (canvas.height - originalImg.height * scale) / 2;
let isDragging = false;
let startX = 0;
let startY = 0;
function draw() {
// Clear and draw background
ctx.fillStyle = bgColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Save context state, apply panning and zooming, draw image
ctx.save();
ctx.translate(posX, posY);
ctx.scale(scale, scale);
// Smoothing for when it's zoomed in or out
ctx.imageSmoothingEnabled = true;
ctx.imageSmoothingQuality = 'high';
ctx.drawImage(originalImg, 0, 0);
ctx.restore();
// Draw Viewer UI Overlay
ctx.fillStyle = "rgba(0, 0, 0, 0.6)";
ctx.fillRect(0, 0, canvas.width, 60);
ctx.fillStyle = "#ffffff";
ctx.font = "bold 22px 'Segoe UI', Arial, sans-serif";
ctx.fillText(overlayText, 15, 30);
ctx.fillStyle = "#cccccc";
ctx.font = "14px 'Segoe UI', Arial, sans-serif";
ctx.fillText("Scroll to zoom • Click & Drag to pan • Double-click to reset", 15, 50);
// Draw zoom percentage in top right
const zoomPercent = Math.round((scale / initialScale) * 100) + "%";
ctx.textAlign = "right";
ctx.fillStyle = "#ffffff";
ctx.font = "bold 16px 'Segoe UI', Arial, sans-serif";
ctx.fillText(zoomPercent, canvas.width - 20, 35);
ctx.textAlign = "left"; // reset alignment
}
// Zooming functionality using mouse wheel
canvas.addEventListener('wheel', (e) => {
e.preventDefault();
const zoomIntensity = 0.1;
const wheel = e.deltaY < 0 ? 1 : -1;
// Calculate the zoom factor
const zoomFactor = Math.exp(wheel * zoomIntensity);
// Get mouse coordinates relative to the canvas
const rect = canvas.getBoundingClientRect();
const mouseX = e.clientX - rect.left;
const mouseY = e.clientY - rect.top;
// Adjust position so the zoom centers on the mouse cursor
posX = mouseX - (mouseX - posX) * zoomFactor;
posY = mouseY - (mouseY - posY) * zoomFactor;
scale *= zoomFactor;
// Prevent zooming out too far or zooming in too much
const minScale = initialScale * 0.1;
const maxScale = initialScale * 20;
if (scale < minScale) {
scale = minScale;
// Recalculate position adjustment limit when hit boundary
posX = mouseX - (mouseX - posX) * (minScale / (scale / zoomFactor));
posY = mouseY - (mouseY - posY) * (minScale / (scale / zoomFactor));
} else if (scale > maxScale) {
scale = maxScale;
posX = mouseX - (mouseX - posX) * (maxScale / (scale / zoomFactor));
posY = mouseY - (mouseY - posY) * (maxScale / (scale / zoomFactor));
}
requestAnimationFrame(draw);
}, { passive: false }); // passive: false required to allow e.preventDefault()
// Panning functionality
canvas.addEventListener('mousedown', (e) => {
isDragging = true;
// Get start coordinates relative to current pan position
const rect = canvas.getBoundingClientRect();
startX = (e.clientX - rect.left) - posX;
startY = (e.clientY - rect.top) - posY;
canvas.style.cursor = 'grabbing';
});
canvas.addEventListener('mousemove', (e) => {
if (!isDragging) return;
// Update pan position based on mouse movement
const rect = canvas.getBoundingClientRect();
posX = (e.clientX - rect.left) - startX;
posY = (e.clientY - rect.top) - startY;
requestAnimationFrame(draw);
});
const stopDragging = () => {
isDragging = false;
canvas.style.cursor = 'grab';
};
canvas.addEventListener('mouseup', stopDragging);
canvas.addEventListener('mouseleave', stopDragging);
// Reset view on double click
canvas.addEventListener('dblclick', () => {
scale = initialScale;
posX = (canvas.width - originalImg.width * scale) / 2;
posY = (canvas.height - originalImg.height * scale) / 2;
requestAnimationFrame(draw);
});
// Set initial cursor style
canvas.style.cursor = 'grab';
// Disable text selection during drag interactions
canvas.style.userSelect = 'none';
// Perform initial draw
draw();
return canvas;
}
Apply Changes