Displays a base image and an "x-ray" view of a second image where the mouse is pointing
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 
 

246 lines
7.3 KiB

  1. "use strict";
  2. let overlayLoaded = false;
  3. let baseLoaded = false;
  4. let radius = 200;
  5. let softness = 25;
  6. document.addEventListener("DOMContentLoaded", e => {
  7. document.querySelector("#load-button").addEventListener("click", e => {
  8. console.log("Trying to load...");
  9. const baseInput = document.querySelector("#base-url").value;
  10. const overlayInput = document.querySelector("#overlay-url").value;
  11. try {
  12. let baseURL = new URL(baseInput)
  13. console.log(baseURL);
  14. } catch {
  15. document.querySelector("#base-url").value = "";
  16. document.querySelector("#base-url").placeholder = "Invalid URL...";
  17. }
  18. try {
  19. let overlayURL = new URL(overlayInput)
  20. console.log(overlayURL);
  21. } catch {
  22. document.querySelector("#overlay-url").value = "";
  23. document.querySelector("#overlay-url").placeholder = "Invalid URL...";
  24. }
  25. const overlayImg = document.querySelector("#overlay-img");
  26. const baseImg = document.querySelector("#base-img");
  27. overlayImg.src = overlayInput;
  28. baseImg.src = baseInput;
  29. load();
  30. try {
  31. localStorage.setItem("base", baseInput);
  32. localStorage.setItem("overlay", overlayInput);
  33. } catch {
  34. console.error("Couldn't set something in local storage :(")
  35. }
  36. });
  37. let url = new URL(window.location);
  38. const overlay = document.querySelector("#overlay");
  39. overlay.addEventListener("mousemove", e => {
  40. let x = e.clientX - e.target.getBoundingClientRect().x;
  41. let y = e.clientY - e.target.getBoundingClientRect().y;
  42. updateOverlay([[x,y]]);
  43. });
  44. overlay.addEventListener("touchmove", e => {
  45. let offsetX = e.target.getBoundingClientRect().x;
  46. let offsetY = e.target.getBoundingClientRect().y;
  47. let touches = [];
  48. for (let i=0; i < e.touches.length; i++) {
  49. let x = e.touches[i].clientX - offsetX;
  50. let y = e.touches[i].clientY - offsetY;
  51. touches.push([x,y]);
  52. }
  53. updateOverlay(touches);
  54. });
  55. document.querySelector("#radius").addEventListener("change", e => {
  56. try {
  57. radius = parseInt(e.target.value);
  58. } catch {
  59. console.warn("That wasn't a valid radius: " + e.target.value);
  60. }
  61. });
  62. document.querySelector("#softness").addEventListener("change", e => {
  63. try {
  64. softness = parseInt(e.target.value);
  65. } catch {
  66. console.warn("That wasn't a valid softness: " + e.target.value);
  67. }
  68. });
  69. // see if we have params already; if so, use them!
  70. const overlayImg = document.querySelector("#overlay-img");
  71. const baseImg = document.querySelector("#base-img");
  72. const baseInput = document.querySelector("#base-url");
  73. const overlayInput = document.querySelector("#overlay-url");
  74. if (url.searchParams.has("base") && url.searchParams.has("overlay")) {
  75. let baseURL = url.searchParams.get("base");
  76. let overlayURL = url.searchParams.get("overlay");
  77. baseImg.src = baseURL;
  78. overlayImg.src = overlayURL;
  79. baseInput.value = baseURL;
  80. overlayInput.value = overlayURL;
  81. load();
  82. } else {
  83. try {
  84. baseInput.value = localStorage.getItem("base");
  85. overlayInput.value = localStorage.getItem("overlay");
  86. } catch {
  87. console.error("Couldn't get something from local storage :(")
  88. }
  89. }
  90. if (url.searchParams.has("radius")) {
  91. try {
  92. radius = parseInt(url.searchParams.get("radius"));
  93. document.querySelector("#radius").value = radius;
  94. } catch {
  95. console.warn("That was a bogus radius...");
  96. }
  97. }
  98. if (url.searchParams.has("softness")) {
  99. try {
  100. softness = parseInt(url.searchParams.get("softness"));
  101. document.querySelector("#softness").value = softness;
  102. } catch {
  103. console.warn("That was a bogus softness...");
  104. }
  105. }
  106. document.querySelector("#share-button").addEventListener("click", e => {
  107. let shareURL = new URL(window.location);
  108. // for some reason, the parser gets confused by urlencoded urls...
  109. // so, to get rid of all parameters, we do this
  110. let keys = Array.from(shareURL.searchParams.keys());
  111. do {
  112. keys = Array.from(shareURL.searchParams.keys());
  113. keys.forEach(key => {
  114. shareURL.searchParams.delete(key);
  115. });
  116. } while (keys.length > 0)
  117. shareURL.searchParams.append("base", baseImg.src);
  118. shareURL.searchParams.append("overlay", overlayImg.src);
  119. shareURL.searchParams.append("radius", radius);
  120. shareURL.searchParams.append("softness", softness);
  121. console.log(shareURL);
  122. window.location = shareURL;
  123. });
  124. });
  125. function load() {
  126. document.querySelector("#menu").classList.remove("start");
  127. const overlayImg = document.querySelector("#overlay-img");
  128. const baseImg = document.querySelector("#base-img");
  129. overlayImg.addEventListener("load", function overlayLoad() {
  130. console.log("The overlay is loaded");
  131. overlayLoaded = true;
  132. if (overlayLoaded && baseLoaded) {
  133. setup();
  134. }
  135. overlayImg.removeEventListener("load", overlayLoad);
  136. })
  137. baseImg.addEventListener("load", function baseLoad() {
  138. console.log("The base is loaded");
  139. baseLoaded = true;
  140. if (overlayLoaded && baseLoaded) {
  141. setup();
  142. }
  143. baseImg.removeEventListener("load", baseLoad);
  144. })
  145. }
  146. function setup() {
  147. const overlay = document.querySelector("#overlay");
  148. const base = document.querySelector("#base");
  149. overlay.classList.remove("hidden");
  150. base.classList.remove("hidden");
  151. const overlayImg = document.querySelector("#overlay-img");
  152. const baseImg = document.querySelector("#base-img");
  153. /** @type {CanvasRenderingContext2D} */
  154. const overlayCtx = overlay.getContext("2d");
  155. /** @type {CanvasRenderingContext2D} */
  156. const baseCtx = base.getContext("2d");
  157. baseCtx.canvas.width = baseImg.width;
  158. baseCtx.canvas.height = baseImg.height;
  159. baseCtx.drawImage(baseImg, 0, 0);
  160. overlayCtx.canvas.width = overlayImg.width;
  161. overlayCtx.canvas.height = overlayImg.height;
  162. console.log("Done");
  163. }
  164. function updateOverlay(points) {
  165. /** @type {CanvasRenderingContext2D} */
  166. const overlayCtx = overlay.getContext("2d");
  167. const overlayImg = document.querySelector("#overlay-img");
  168. const w = overlayCtx.canvas.width;
  169. const h = overlayCtx.canvas.height;
  170. overlayCtx.save();
  171. overlayCtx.globalCompositeOperation = "source-over";
  172. overlayCtx.clearRect(0, 0, w, h);
  173. points.forEach(point => {
  174. const [x,y] = point;
  175. overlayCtx.beginPath();
  176. overlayCtx.ellipse(x, y, radius, radius, 0, 0, 2 * Math.PI);
  177. const gradient = overlayCtx.createRadialGradient(x, y, 0, x, y, radius);
  178. gradient.addColorStop((100-softness)/100, '#000000FF');
  179. gradient.addColorStop(1, '#00000000');
  180. overlayCtx.fillStyle = gradient;
  181. overlayCtx.fill();
  182. })
  183. overlayCtx.globalCompositeOperation = "source-in";
  184. overlayCtx.drawImage(overlayImg, 0, 0);
  185. overlayCtx.restore();
  186. }