Skip to main content
Latest
File
<html> <head> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <script type="importmap"> { "imports": { "@jsxImportSource": "https://esm.sh/preact@10.19.2", "preact": "https://esm.sh/preact@10.19.2", "preact/": "https://esm.sh/preact@10.19.2/" } } </script> <script type="module" src="https://esm.sh/run"></script> </head> <body> <script type="text/babel"> // https://github.com/youpy/yea import { amen } from "./main.js"; import { render } from "preact"; import { useState, useEffect } from "preact/hooks";
const createFn = (value) => { return ({ index, cumulativeIndex, numSlices }) => { const sliceIndex = Math.floor( (Math.sin(cumulativeIndex / value) * 0.5 + 0.5) * numSlices ); const duration = ((cumulativeIndex * sliceIndex) % 3) + 1;
return { sliceIndex, duration, length: 1 / duration, loop: { prob: 1, length: 1 / (((cumulativeIndex * index) % 2) + 1), }, }; }; };
const getValueFromHash = () => { const h = window.location.hash;
if (h.length > 1) { return h.substring(1) * 1; } };
const setValueToHash = (value) => { window.location.hash = `#${value}`; };
const App = () => { const [stop, setStop] = useState(null); const [setFn, setSetFn] = useState(null); const [value, setValue] = useState( getValueFromHash() || Math.floor(Math.random() * 1000) + 1 ); const [serveId, setServeId] = useState(null);
useEffect(() => { // for live reloading const intervalId = setInterval(async () => { const prevId = serveId; const res = await fetch("/_serve"); const id = await res.text();
if (prevId && id !== prevId) { location.reload(); } else { setServeId(id); } }, 1000);
const onKeyDown = (e) => { let newValue = value;
if (e.code == `ArrowUp`) { newValue = Math.min(1000, value + 1); } else if (e.code == `ArrowDown`) { newValue = Math.max(1, value - 1); } else if (e.code == `ArrowRight`) { newValue = Math.min(1000, value + 20); } else if (e.code == `ArrowLeft`) { newValue = Math.max(1, value - 20); }
setValueToHash(newValue);
if (setFn) { setFn.fn(createFn(newValue / 1000)); } }; const onHashChange = () => { const newValue = getValueFromHash();
if (newValue) { setValue(newValue);
if (setFn) { setFn.fn(createFn(newValue / 1000)); } } };
window.addEventListener("keydown", onKeyDown); window.addEventListener("hashchange", onHashChange);
return () => { clearInterval(intervalId); window.removeEventListener("keydown", onKeyDown); window.removeEventListener("hashchange", onHashChange); }; });
const toggle = () => { if (stop) { stop.fn();
setStop(null); setSetFn(null); } else { const [stop, setFn] = amen(createFn(value / 1000));
setStop({ fn: stop }); setSetFn({ fn: setFn }); } }; const change = (e) => { const v = e.target.value * 1;
setValueToHash(v);
if (setFn) { setFn.fn(createFn(v / 1000)); } };
return ( <> <p> <button onClick={() => toggle()}> {stop ? "stop" : "start"} </button> </p> <p> <input type="range" min="1" max="1000" value={value} step="1" onInput={change} /> </p> </> ); };
if (!getValueFromHash()) { setValueToHash(Math.floor(Math.random() * 1000) + 1); }
render(<App />, document.body); </script> </body></html>