|  |  | @@ -11,6 +11,8 @@ let softness = 25; | 
		
	
		
			
			|  |  |  | let width; | 
		
	
		
			
			|  |  |  | let height; | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | let paintMode = false; | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | let scale; | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | document.addEventListener("DOMContentLoaded", e => { | 
		
	
	
		
			
				|  |  | @@ -63,10 +65,30 @@ document.addEventListener("DOMContentLoaded", e => { | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | const overlay = document.querySelector("#overlay"); | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | document.addEventListener("mousedown", e => { | 
		
	
		
			
			|  |  |  | let x = e.clientX - e.target.getBoundingClientRect().x; | 
		
	
		
			
			|  |  |  | let y = e.clientY - e.target.getBoundingClientRect().y; | 
		
	
		
			
			|  |  |  | updateOverlay([[x,y]], e.buttons % 2 != 0); | 
		
	
		
			
			|  |  |  | }); | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | document.addEventListener("mousemove", e => { | 
		
	
		
			
			|  |  |  | let x = e.clientX - e.target.getBoundingClientRect().x; | 
		
	
		
			
			|  |  |  | let y = e.clientY - e.target.getBoundingClientRect().y; | 
		
	
		
			
			|  |  |  | updateOverlay([[x,y]]); | 
		
	
		
			
			|  |  |  | updateOverlay([[x,y]], e.buttons % 2 != 0); | 
		
	
		
			
			|  |  |  | }); | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | document.addEventListener("touchstart", 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, true); | 
		
	
		
			
			|  |  |  | }); | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | document.addEventListener("touchmove", e => { | 
		
	
	
		
			
				|  |  | @@ -80,7 +102,7 @@ document.addEventListener("DOMContentLoaded", e => { | 
		
	
		
			
			|  |  |  | let y = e.touches[i].clientY - offsetY; | 
		
	
		
			
			|  |  |  | touches.push([x,y]); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | updateOverlay(touches); | 
		
	
		
			
			|  |  |  | updateOverlay(touches, true); | 
		
	
		
			
			|  |  |  | }); | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | document.querySelector("#radius-slider").addEventListener("input", e => { | 
		
	
	
		
			
				|  |  | @@ -227,6 +249,10 @@ document.addEventListener("DOMContentLoaded", e => { | 
		
	
		
			
			|  |  |  | cancelFullScreen.call(doc); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | }); | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | document.querySelector("#paint-mode").addEventListener("change", e => { | 
		
	
		
			
			|  |  |  | paintMode = e.target.checked; | 
		
	
		
			
			|  |  |  | }); | 
		
	
		
			
			|  |  |  | }); | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | function load() { | 
		
	
	
		
			
				|  |  | @@ -305,7 +331,7 @@ function setup() { | 
		
	
		
			
			|  |  |  | console.log("Done"); | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | function updateOverlay(points) { | 
		
	
		
			
			|  |  |  | function updateOverlay(points, clicked) { | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | const overlay = document.querySelector("#overlay"); | 
		
	
		
			
			|  |  |  | const overlayResized = document.querySelector("#overlay-resized"); | 
		
	
	
		
			
				|  |  | @@ -322,20 +348,25 @@ function updateOverlay(points) { | 
		
	
		
			
			|  |  |  | 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 * scale, radius * scale, 0, 0, 2 * Math.PI); | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | const gradient = overlayCtx.createRadialGradient(x, y, 0, x, y, Math.floor(radius * scale)); | 
		
	
		
			
			|  |  |  | gradient.addColorStop((100-softness)/100, '#000000FF'); | 
		
	
		
			
			|  |  |  | gradient.addColorStop(1, '#00000000'); | 
		
	
		
			
			|  |  |  | overlayCtx.fillStyle = gradient; | 
		
	
		
			
			|  |  |  | if (!paintMode) | 
		
	
		
			
			|  |  |  | overlayCtx.clearRect(0, 0, w, h); | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | if (!paintMode || clicked) { | 
		
	
		
			
			|  |  |  | points.forEach(point => { | 
		
	
		
			
			|  |  |  | const [x,y] = point; | 
		
	
		
			
			|  |  |  | overlayCtx.beginPath(); | 
		
	
		
			
			|  |  |  | overlayCtx.ellipse(x, y, radius * scale, radius * scale, 0, 0, 2 * Math.PI); | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | const gradient = overlayCtx.createRadialGradient(x, y, 0, x, y, Math.floor(radius * scale)); | 
		
	
		
			
			|  |  |  | gradient.addColorStop((100-softness)/100, '#000000FF'); | 
		
	
		
			
			|  |  |  | gradient.addColorStop(1, '#00000000'); | 
		
	
		
			
			|  |  |  | overlayCtx.fillStyle = gradient; | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | overlayCtx.fill(); | 
		
	
		
			
			|  |  |  | }) | 
		
	
		
			
			|  |  |  | } | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | overlayCtx.fill(); | 
		
	
		
			
			|  |  |  | }) | 
		
	
		
			
			|  |  |  |  | 
		
	
		
			
			|  |  |  | 
 | 
		
	
		
			
			|  |  |  | overlayCtx.globalCompositeOperation = "source-in"; | 
		
	
	
		
			
				|  |  | 
 |