"use strict"; let overlayLoaded = false; let baseLoaded = false; let radius = 200; let softness = 25; document.addEventListener("DOMContentLoaded", e => { document.querySelector("#load-button").addEventListener("click", e => { console.log("Trying to load..."); const baseInput = document.querySelector("#base-url").value; const overlayInput = document.querySelector("#overlay-url").value; let success = true; try { let baseURL = new URL(baseInput) console.log(baseURL); } catch { document.querySelector("#base-url").value = ""; document.querySelector("#base-url").placeholder = "Invalid URL..."; success = false; } try { let overlayURL = new URL(overlayInput) console.log(overlayURL); } catch { document.querySelector("#overlay-url").value = ""; document.querySelector("#overlay-url").placeholder = "Invalid URL..."; success = false; } if (!success) { return; } const overlayImg = document.querySelector("#overlay-img"); const baseImg = document.querySelector("#base-img"); overlayImg.src = overlayInput; baseImg.src = baseInput; load(); try { localStorage.setItem("base", baseInput); localStorage.setItem("overlay", overlayInput); } catch { console.error("Couldn't set something in local storage :(") } }); let url = new URL(window.location); const overlay = document.querySelector("#overlay"); overlay.addEventListener("mousemove", e => { let x = e.clientX - e.target.getBoundingClientRect().x; let y = e.clientY - e.target.getBoundingClientRect().y; updateOverlay([[x,y]]); }); overlay.addEventListener("touchmove", e => { let offsetX = e.target.getBoundingClientRect().x; let offsetY = e.target.getBoundingClientRect().y; let touches = []; for (let i=0; i < e.touches.length; i++) { let x = e.touches[i].clientX - offsetX; let y = e.touches[i].clientY - offsetY; touches.push([x,y]); } updateOverlay(touches); }); document.querySelector("#radius").addEventListener("change", e => { try { radius = parseInt(e.target.value); } catch { console.warn("That wasn't a valid radius: " + e.target.value); } }); document.querySelector("#softness").addEventListener("change", e => { try { softness = parseInt(e.target.value); } catch { console.warn("That wasn't a valid softness: " + e.target.value); } }); // see if we have params already; if so, use them! const overlayImg = document.querySelector("#overlay-img"); const baseImg = document.querySelector("#base-img"); const baseInput = document.querySelector("#base-url"); const overlayInput = document.querySelector("#overlay-url"); if (url.searchParams.has("base") && url.searchParams.has("overlay")) { let baseURL = url.searchParams.get("base"); let overlayURL = url.searchParams.get("overlay"); baseImg.src = baseURL; overlayImg.src = overlayURL; baseInput.value = baseURL; overlayInput.value = overlayURL; load(); } else { try { baseInput.value = localStorage.getItem("base"); overlayInput.value = localStorage.getItem("overlay"); } catch { console.error("Couldn't get something from local storage :(") } } if (url.searchParams.has("radius")) { try { radius = parseInt(url.searchParams.get("radius")); document.querySelector("#radius").value = radius; } catch { console.warn("That was a bogus radius..."); } } if (url.searchParams.has("softness")) { try { softness = parseInt(url.searchParams.get("softness")); document.querySelector("#softness").value = softness; } catch { console.warn("That was a bogus softness..."); } } document.querySelector("#share-button").addEventListener("click", e => { let shareURL = new URL(window.location); // for some reason, the parser gets confused by urlencoded urls... // so, to get rid of all parameters, we do this let keys = Array.from(shareURL.searchParams.keys()); do { keys = Array.from(shareURL.searchParams.keys()); keys.forEach(key => { shareURL.searchParams.delete(key); }); } while (keys.length > 0) shareURL.searchParams.append("base", baseImg.src); shareURL.searchParams.append("overlay", overlayImg.src); shareURL.searchParams.append("radius", radius); shareURL.searchParams.append("softness", softness); console.log(shareURL); window.location = shareURL; }); }); function load() { document.querySelector("#menu").classList.remove("start"); const overlayImg = document.querySelector("#overlay-img"); const baseImg = document.querySelector("#base-img"); overlayImg.addEventListener("load", function overlayLoad() { console.log("The overlay is loaded"); overlayLoaded = true; if (overlayLoaded && baseLoaded) { setup(); } overlayImg.removeEventListener("load", overlayLoad); }) baseImg.addEventListener("load", function baseLoad() { console.log("The base is loaded"); baseLoaded = true; if (overlayLoaded && baseLoaded) { setup(); } baseImg.removeEventListener("load", baseLoad); }) } function setup() { const overlay = document.querySelector("#overlay"); const base = document.querySelector("#base"); overlay.classList.remove("hidden"); base.classList.remove("hidden"); const overlayImg = document.querySelector("#overlay-img"); const baseImg = document.querySelector("#base-img"); /** @type {CanvasRenderingContext2D} */ const overlayCtx = overlay.getContext("2d"); /** @type {CanvasRenderingContext2D} */ const baseCtx = base.getContext("2d"); baseCtx.canvas.width = baseImg.width; baseCtx.canvas.height = baseImg.height; baseCtx.drawImage(baseImg, 0, 0); overlayCtx.canvas.width = overlayImg.width; overlayCtx.canvas.height = overlayImg.height; console.log("Done"); } function updateOverlay(points) { /** @type {CanvasRenderingContext2D} */ const overlayCtx = overlay.getContext("2d"); const overlayImg = document.querySelector("#overlay-img"); const w = overlayCtx.canvas.width; const h = overlayCtx.canvas.height; overlayCtx.save(); overlayCtx.globalCompositeOperation = "source-over"; overlayCtx.clearRect(0, 0, w, h); points.forEach(point => { const [x,y] = point; overlayCtx.beginPath(); overlayCtx.ellipse(x, y, radius, radius, 0, 0, 2 * Math.PI); const gradient = overlayCtx.createRadialGradient(x, y, 0, x, y, radius); gradient.addColorStop((100-softness)/100, '#000000FF'); gradient.addColorStop(1, '#00000000'); overlayCtx.fillStyle = gradient; overlayCtx.fill(); }) overlayCtx.globalCompositeOperation = "source-in"; overlayCtx.drawImage(overlayImg, 0, 0); overlayCtx.restore(); }