image_overlay/app.js

86 lines
2.0 KiB
JavaScript

// Minimal canvas compositor
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
let bgImg = null;
let fgImg = null;
// --- image loader ---
function loadImage(file, callback) {
if (!file) return;
const img = new Image();
img.onload = () => callback(img);
img.src = URL.createObjectURL(file);
}
// --- inputs ---
const bgInput = document.getElementById("bgInput");
const fgInput = document.getElementById("fgInput");
const scaleInput = document.getElementById("scale");
const offsetXInput = document.getElementById("offsetX");
const offsetYInput = document.getElementById("offsetY");
// --- event bindings ---
bgInput.onchange = (e) => {
loadImage(e.target.files[0], (img) => {
bgImg = img;
// canvas follows background resolution exactly
canvas.width = img.width;
canvas.height = img.height;
draw();
});
};
fgInput.onchange = (e) => {
loadImage(e.target.files[0], (img) => {
fgImg = img;
draw();
});
};
[scaleInput, offsetXInput, offsetYInput].forEach(el => {
el.oninput = draw;
});
// --- draw pipeline ---
function draw() {
if (!bgImg) return;
// clear + draw background
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(bgImg, 0, 0);
if (!fgImg) return;
const scale = parseFloat(scaleInput.value) / 100 || 0.2;
const offsetX = parseFloat(offsetXInput.value) || 0;
const offsetY = parseFloat(offsetYInput.value) || 0;
// scale based on background width
const targetWidth = bgImg.width * scale;
const aspect = fgImg.height / fgImg.width;
const targetHeight = targetWidth * aspect;
// centered + offsets
const x = (bgImg.width - targetWidth) / 2 + offsetX;
const y = (bgImg.height - targetHeight) / 2 + offsetY;
ctx.drawImage(fgImg, x, y, targetWidth, targetHeight);
}
// --- download ---
document.getElementById("downloadBtn").onclick = () => {
if (!bgImg) return;
const link = document.createElement("a");
link.download = "overlay_image.png";
link.href = canvas.toDataURL("image/png");
link.click();
};