color-synth

a synth that generates colors instead of sounds
Log | Files | Refs | README

NumberSelector.svelte (2882B)


      1 <script lang="ts">
      2 	import { clamp } from '$lib/types';
      3 	export let value: number;
      4 	export let updateValue: (n: number) => void;
      5 
      6 	let pos:
      7 		| {
      8 				start: { x: number; y: number };
      9 				delta: { x: number; y: number };
     10 				mouse: { x: number; y: number };
     11 		  }
     12 		| undefined;
     13 	let el: HTMLDivElement | undefined;
     14 
     15 	const handleMove = (evt: MouseEvent) => {
     16 		if (!pos) return;
     17 		pos.delta.x += evt.movementX;
     18 		//pos.delta.y += evt.movementY;
     19 		let mouseX = (pos.start.x + pos.delta.x / 2) % window.innerWidth;
     20 
     21 		if (mouseX < 0) {
     22 			mouseX += window.innerWidth;
     23 		}
     24 		pos.mouse.x = mouseX;
     25 
     26 		//let mouseY = (pos.start.y + pos.delta.y) % window.innerHeight;
     27 		//if (mouseY < 0) {
     28 		//	mouseY += window.innerHeight;
     29 		//}
     30 		//pos.mouse.y = mouseY;
     31 	};
     32 
     33 	type Ticker = { start: () => void; stop: () => void };
     34 	const Ticker = (): Ticker => {
     35 		let c = 0;
     36 		let tDelta: number | undefined;
     37 		let cont = true;
     38 		const run = (ts: number) => {
     39 			if (!cont || !pos || !pos.delta) {
     40 				return;
     41 			}
     42 			if (tDelta === undefined) {
     43 				tDelta = ts;
     44 			} else {
     45 				tDelta = ts - tDelta;
     46 				const rate = Math.pow(pos.delta.x / 200, 3);
     47 				c = c + rate * tDelta;
     48 				if (Math.abs(c) > 10000) {
     49 					let n = Math.floor(c / 10000);
     50 					c -= n * 10000;
     51 					const truncValue = clamp(value + n, { min: -500_000, max: 500_000 });
     52 					updateValue(truncValue);
     53 				}
     54 			}
     55 			requestAnimationFrame(run);
     56 		};
     57 		const stop = () => {
     58 			cont = false;
     59 		};
     60 		const start = () => {
     61 			cont = true;
     62 			requestAnimationFrame(run);
     63 		};
     64 		return { start, stop };
     65 	};
     66 
     67 	let ticker: Ticker | undefined;
     68 
     69 	const handleMouseDown = async (evt: MouseEvent) => {
     70 		//@ts-ignore TODO figure out if this is true cuz mdn says to do this.
     71 		await el?.requestPointerLock();
     72 		pos = {
     73 			start: {
     74 				x: evt.pageX,
     75 				y: evt.pageY
     76 			},
     77 			delta: {
     78 				x: 0,
     79 				y: 0
     80 			},
     81 			mouse: {
     82 				x: evt.pageX,
     83 				y: evt.pageY
     84 			}
     85 		};
     86 		ticker = Ticker();
     87 		ticker.start();
     88 		document.addEventListener('mousemove', handleMove);
     89 		document.addEventListener('mouseup', handleMouseUp);
     90 	};
     91 
     92 	const handleMouseUp = () => {
     93 		ticker?.stop();
     94 		ticker = undefined;
     95 		pos = undefined;
     96 		document.exitPointerLock();
     97 		document.removeEventListener('mousemove', handleMove);
     98 		document.removeEventListener('mouseup', handleMouseUp);
     99 	};
    100 
    101 	const handleDbl = () => {
    102 		updateValue(0);
    103 	};
    104 
    105 	$: if (el) {
    106 		el.removeEventListener('dblclick', handleDbl);
    107 		el.addEventListener('dblclick', handleDbl);
    108 		el.removeEventListener('mousedown', handleMouseDown);
    109 		//el.addEventListener('mousedown', handleMouseDown);
    110 	}
    111 </script>
    112 
    113 <div bind:this={el} class="sel">{value} {pos?.delta.x}</div>
    114 {#if pos}
    115 	<div class="tmp-pointer" style={`top:${pos.mouse.y}px; left:${pos.mouse.x}px`} />
    116 {/if}
    117 
    118 <style>
    119 	.sel {
    120 		font-family: monospace;
    121 	}
    122 	.tmp-pointer {
    123 		position: fixed;
    124 		height: 10px;
    125 		width: 10px;
    126 		background: red;
    127 	}
    128 </style>