motionary 6.9.0 → 7.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +30 -0
- package/README.md +2 -2
- package/README_ja.md +2 -2
- package/README_zh.md +2 -2
- package/dist/chunks/audio-DcPvT2Kh.js +333 -0
- package/dist/chunks/audio-DcPvT2Kh.js.map +1 -0
- package/dist/chunks/audio-EXUoijsG.cjs +342 -0
- package/dist/chunks/audio-EXUoijsG.cjs.map +1 -0
- package/dist/chunks/{base-D5MHqeDd.js → base-2-yYc93C.js} +2 -2
- package/dist/chunks/{base-D5MHqeDd.js.map → base-2-yYc93C.js.map} +1 -1
- package/dist/chunks/{core-DyJu5r5a.js → core-D5rU0CV6.js} +2 -2
- package/dist/chunks/{core-DyJu5r5a.js.map → core-D5rU0CV6.js.map} +1 -1
- package/dist/chunks/{core-ZGo4hOEk.js → core-DuO-AVXL.js} +2 -2
- package/dist/chunks/{core-ZGo4hOEk.js.map → core-DuO-AVXL.js.map} +1 -1
- package/dist/chunks/{fx-DlGRMJ-Z.js → fx-CMxWNwH8.js} +2 -2
- package/dist/chunks/{fx-DlGRMJ-Z.js.map → fx-CMxWNwH8.js.map} +1 -1
- package/dist/chunks/{gpu-DPhMkJq6.js → gpu-DLPghVWr.js} +183 -11
- package/dist/chunks/gpu-DLPghVWr.js.map +1 -0
- package/dist/chunks/{gpu-C2D4T9Q-.cjs → gpu-Dx0H875w.cjs} +185 -9
- package/dist/chunks/gpu-Dx0H875w.cjs.map +1 -0
- package/dist/chunks/{index-tags-wv0R_vkO.cjs → index-tags-BTMwrfgV.cjs} +3 -3
- package/dist/chunks/index-tags-BTMwrfgV.cjs.map +1 -0
- package/dist/chunks/{index-tags-DucKMQr_.js → index-tags-C04JP8g4.js} +3 -3
- package/dist/chunks/index-tags-C04JP8g4.js.map +1 -0
- package/dist/chunks/{player-DH3TIz-t.js → player-DxvCYo7Q.js} +4 -4
- package/dist/chunks/{player-DH3TIz-t.js.map → player-DxvCYo7Q.js.map} +1 -1
- package/dist/chunks/{registry-CTLWeg-J.js → registry-CyKExAmE.js} +2 -2
- package/dist/chunks/{registry-CTLWeg-J.js.map → registry-CyKExAmE.js.map} +1 -1
- package/dist/chunks/{spring-B-9MZOrW.js → spring-BK8DiezC.js} +2 -2
- package/dist/chunks/{spring-B-9MZOrW.js.map → spring-BK8DiezC.js.map} +1 -1
- package/dist/chunks/{variants-CoZn3k_5.js → variants-BQ6bhzn4.js} +2 -2
- package/dist/chunks/{variants-CoZn3k_5.js.map → variants-BQ6bhzn4.js.map} +1 -1
- package/dist/components/a11y.cjs +1 -1
- package/dist/components/a11y.d.cts +2 -2
- package/dist/components/a11y.d.ts +2 -2
- package/dist/components/a11y.js +3 -3
- package/dist/components/angular.cjs +2 -2
- package/dist/components/angular.cjs.map +1 -1
- package/dist/components/angular.d.cts +5 -36
- package/dist/components/angular.d.ts +5 -36
- package/dist/components/angular.js +9 -9
- package/dist/components/angular.js.map +1 -1
- package/dist/components/background.js +2 -2
- package/dist/components/bridge.js +1 -1
- package/dist/components/cards.js +2 -2
- package/dist/components/click.js +3 -3
- package/dist/components/depth.js +3 -3
- package/dist/components/effects.cjs +11 -336
- package/dist/components/effects.cjs.map +1 -1
- package/dist/components/effects.js +9 -333
- package/dist/components/effects.js.map +1 -1
- package/dist/components/feedback.js +1 -1
- package/dist/components/fx-3d.cjs +1 -7
- package/dist/components/fx-3d.cjs.map +1 -1
- package/dist/components/fx-3d.d.cts +1 -3
- package/dist/components/fx-3d.d.ts +1 -3
- package/dist/components/fx-3d.js +3 -8
- package/dist/components/fx-3d.js.map +1 -1
- package/dist/components/fx-focus.js +2 -2
- package/dist/components/fx-gpu.cjs +2 -3
- package/dist/components/fx-gpu.cjs.map +1 -1
- package/dist/components/fx-gpu.d.cts +1 -3
- package/dist/components/fx-gpu.d.ts +1 -3
- package/dist/components/fx-gpu.js +3 -3
- package/dist/components/fx-light.cjs +1 -7
- package/dist/components/fx-light.cjs.map +1 -1
- package/dist/components/fx-light.d.cts +1 -3
- package/dist/components/fx-light.d.ts +1 -3
- package/dist/components/fx-light.js +3 -8
- package/dist/components/fx-light.js.map +1 -1
- package/dist/components/fx-morph.cjs +1 -7
- package/dist/components/fx-morph.cjs.map +1 -1
- package/dist/components/fx-morph.d.cts +1 -3
- package/dist/components/fx-morph.d.ts +1 -3
- package/dist/components/fx-morph.js +3 -8
- package/dist/components/fx-morph.js.map +1 -1
- package/dist/components/fx-music.cjs +179 -0
- package/dist/components/fx-music.cjs.map +1 -0
- package/dist/components/fx-music.d.cts +102 -0
- package/dist/components/fx-music.d.ts +102 -0
- package/dist/components/fx-music.js +174 -0
- package/dist/components/fx-music.js.map +1 -0
- package/dist/components/fx-physics.cjs +1 -7
- package/dist/components/fx-physics.cjs.map +1 -1
- package/dist/components/fx-physics.d.cts +1 -3
- package/dist/components/fx-physics.d.ts +1 -3
- package/dist/components/fx-physics.js +3 -8
- package/dist/components/fx-physics.js.map +1 -1
- package/dist/components/fx-text.cjs +1 -7
- package/dist/components/fx-text.cjs.map +1 -1
- package/dist/components/fx-text.d.cts +1 -3
- package/dist/components/fx-text.d.ts +1 -3
- package/dist/components/fx-text.js +3 -8
- package/dist/components/fx-text.js.map +1 -1
- package/dist/components/fx-transitions.cjs +1 -7
- package/dist/components/fx-transitions.cjs.map +1 -1
- package/dist/components/fx-transitions.d.cts +1 -3
- package/dist/components/fx-transitions.d.ts +1 -3
- package/dist/components/fx-transitions.js +4 -9
- package/dist/components/fx-transitions.js.map +1 -1
- package/dist/components/fx-weather.cjs +1 -7
- package/dist/components/fx-weather.cjs.map +1 -1
- package/dist/components/fx-weather.d.cts +1 -3
- package/dist/components/fx-weather.d.ts +1 -3
- package/dist/components/fx-weather.js +3 -8
- package/dist/components/fx-weather.js.map +1 -1
- package/dist/components/fx.js +5 -5
- package/dist/components/fx2.cjs +15 -19
- package/dist/components/fx2.cjs.map +1 -1
- package/dist/components/fx2.d.cts +97 -22
- package/dist/components/fx2.d.ts +97 -22
- package/dist/components/fx2.js +16 -19
- package/dist/components/fx2.js.map +1 -1
- package/dist/components/gesture.js +4 -4
- package/dist/components/interaction.cjs +11 -95
- package/dist/components/interaction.cjs.map +1 -1
- package/dist/components/interaction.css +0 -1
- package/dist/components/interaction.d.cts +3 -21
- package/dist/components/interaction.d.ts +3 -21
- package/dist/components/interaction.js +13 -96
- package/dist/components/interaction.js.map +1 -1
- package/dist/components/jsx.d.cts +2 -2
- package/dist/components/jsx.d.ts +2 -2
- package/dist/components/layout.js +1 -1
- package/dist/components/lazy.cjs +1 -1
- package/dist/components/lazy.d.cts +2 -2
- package/dist/components/lazy.d.ts +2 -2
- package/dist/components/lazy.js +1 -1
- package/dist/components/lite.cjs +115 -258
- package/dist/components/lite.cjs.map +1 -1
- package/dist/components/lite.js +116 -257
- package/dist/components/lite.js.map +1 -1
- package/dist/components/marketplace.js +2 -2
- package/dist/components/packs.js +1 -1
- package/dist/components/page.js +3 -3
- package/dist/components/perf.cjs +1 -1
- package/dist/components/perf.d.cts +2 -2
- package/dist/components/perf.d.ts +2 -2
- package/dist/components/perf.js +3 -3
- package/dist/components/physics.js +3 -3
- package/dist/components/react.cjs +2 -2
- package/dist/components/react.cjs.map +1 -1
- package/dist/components/react.js +2 -2
- package/dist/components/react.js.map +1 -1
- package/dist/components/reveal.js +1 -1
- package/dist/components/solid.cjs +2 -2
- package/dist/components/solid.cjs.map +1 -1
- package/dist/components/solid.d.cts +4 -35
- package/dist/components/solid.d.ts +4 -35
- package/dist/components/solid.js +9 -9
- package/dist/components/solid.js.map +1 -1
- package/dist/components/svelte.cjs +2 -2
- package/dist/components/svelte.cjs.map +1 -1
- package/dist/components/svelte.d.cts +5 -36
- package/dist/components/svelte.d.ts +5 -36
- package/dist/components/svelte.js +9 -9
- package/dist/components/svelte.js.map +1 -1
- package/dist/components/svg.js +1 -1
- package/dist/components/text.js +2 -2
- package/dist/components/timeline.js +3 -3
- package/dist/components/transitions.js +1 -1
- package/dist/components/ui.cjs +16 -75
- package/dist/components/ui.cjs.map +1 -1
- package/dist/components/ui.css +0 -1
- package/dist/components/ui.d.cts +3 -18
- package/dist/components/ui.d.ts +3 -18
- package/dist/components/ui.js +21 -79
- package/dist/components/ui.js.map +1 -1
- package/dist/components/vue.cjs +2 -2
- package/dist/components/vue.cjs.map +1 -1
- package/dist/components/vue.d.cts +5 -36
- package/dist/components/vue.d.ts +5 -36
- package/dist/components/vue.js +9 -9
- package/dist/components/vue.js.map +1 -1
- package/dist/components/webgl.js +1 -1
- package/dist/components/widgets.cjs +542 -61
- package/dist/components/widgets.cjs.map +1 -1
- package/dist/components/widgets.d.cts +79 -2
- package/dist/components/widgets.d.ts +79 -2
- package/dist/components/widgets.js +542 -67
- package/dist/components/widgets.js.map +1 -1
- package/dist/components.cjs +1 -3
- package/dist/components.cjs.map +1 -1
- package/dist/components.css +0 -2
- package/dist/components.d.cts +6 -39
- package/dist/components.d.ts +6 -39
- package/dist/components.js +12 -12
- package/dist/components.umd.js +2 -2
- package/dist/components.umd.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/widgets.umd.js +1 -1
- package/dist/widgets.umd.js.map +1 -1
- package/docs/ROADMAP.md +12 -12
- package/docs/accessibility.md +2 -2
- package/docs/components.md +38 -2
- package/docs/frameworks-ssr.md +4 -4
- package/docs/hybrid-apps.md +2 -2
- package/docs/upgrading-7.md +11 -1
- package/docs/windows-apps.md +1 -1
- package/package.json +131 -1
- package/dist/chunks/gpu-C2D4T9Q-.cjs.map +0 -1
- package/dist/chunks/gpu-DPhMkJq6.js.map +0 -1
- package/dist/chunks/index-tags-DucKMQr_.js.map +0 -1
- package/dist/chunks/index-tags-wv0R_vkO.cjs.map +0 -1
|
@@ -4,6 +4,7 @@ var components_fx = require('./fx.cjs');
|
|
|
4
4
|
var shared = require('../chunks/shared-jkgRH-Hx.cjs');
|
|
5
5
|
var player = require('../chunks/player-PS6_FzNw.cjs');
|
|
6
6
|
var generative = require('../chunks/generative-BHIj-NU0.cjs');
|
|
7
|
+
var audio = require('../chunks/audio-EXUoijsG.cjs');
|
|
7
8
|
var registry = require('../chunks/registry-DehBVRDV.cjs');
|
|
8
9
|
var base = require('../chunks/base-BaQV-2ha.cjs');
|
|
9
10
|
var components_tokens = require('./tokens.cjs');
|
|
@@ -575,332 +576,6 @@ const PAGE_FX = [
|
|
|
575
576
|
},
|
|
576
577
|
];
|
|
577
578
|
|
|
578
|
-
let actx = null;
|
|
579
|
-
let current = null;
|
|
580
|
-
const mediaSources = new WeakMap();
|
|
581
|
-
/** The running analyser, if `enableAudio()` was called. */
|
|
582
|
-
const getAudio = () => current;
|
|
583
|
-
function audioContext() {
|
|
584
|
-
const AC = globalThis.AudioContext || globalThis.webkitAudioContext;
|
|
585
|
-
if (!AC)
|
|
586
|
-
throw new Error('[motionary] Web Audio is not available');
|
|
587
|
-
if (!actx || actx.state === 'closed')
|
|
588
|
-
actx = new AC();
|
|
589
|
-
return actx;
|
|
590
|
-
}
|
|
591
|
-
/**
|
|
592
|
-
* Start analysing `input` and make it the source of every sound-reactive
|
|
593
|
-
* effect. Call from a user gesture. Replaces a previous source.
|
|
594
|
-
*/
|
|
595
|
-
async function enableAudio(input = 'mic', opts = {}) {
|
|
596
|
-
current?.stop();
|
|
597
|
-
const ac = audioContext();
|
|
598
|
-
if (ac.state === 'suspended')
|
|
599
|
-
await ac.resume().catch(() => undefined);
|
|
600
|
-
const analyser = ac.createAnalyser();
|
|
601
|
-
analyser.fftSize = opts.fftSize || 512;
|
|
602
|
-
analyser.smoothingTimeConstant = opts.smoothing ?? 0.8;
|
|
603
|
-
let src;
|
|
604
|
-
let release = () => { };
|
|
605
|
-
const media = typeof input === 'string' && input !== 'mic' ? document.querySelector(input) : input;
|
|
606
|
-
if (media === 'mic') {
|
|
607
|
-
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
608
|
-
src = ac.createMediaStreamSource(stream);
|
|
609
|
-
src.connect(analyser); // never to the speakers: no feedback
|
|
610
|
-
release = () => stream.getTracks().forEach((t) => t.stop());
|
|
611
|
-
}
|
|
612
|
-
else if (media && typeof media.play === 'function') {
|
|
613
|
-
const m = media;
|
|
614
|
-
let node = mediaSources.get(m);
|
|
615
|
-
if (!node)
|
|
616
|
-
mediaSources.set(m, (node = ac.createMediaElementSource(m)));
|
|
617
|
-
try {
|
|
618
|
-
node.disconnect();
|
|
619
|
-
}
|
|
620
|
-
catch {
|
|
621
|
-
/* not connected */
|
|
622
|
-
}
|
|
623
|
-
src = node;
|
|
624
|
-
src.connect(analyser);
|
|
625
|
-
analyser.connect(ac.destination);
|
|
626
|
-
release = () => {
|
|
627
|
-
try {
|
|
628
|
-
node.disconnect();
|
|
629
|
-
}
|
|
630
|
-
catch {
|
|
631
|
-
/* already */
|
|
632
|
-
}
|
|
633
|
-
node.connect(ac.destination); // keep the media audible
|
|
634
|
-
};
|
|
635
|
-
if (m.paused)
|
|
636
|
-
await m.play()?.catch?.(() => undefined);
|
|
637
|
-
}
|
|
638
|
-
else if (media && typeof media.getTracks === 'function') {
|
|
639
|
-
src = ac.createMediaStreamSource(media);
|
|
640
|
-
src.connect(analyser);
|
|
641
|
-
}
|
|
642
|
-
else
|
|
643
|
-
throw new Error(`[motionary] enableAudio: no audio source for ${String(input)}`);
|
|
644
|
-
const freq = new Uint8Array(analyser.frequencyBinCount);
|
|
645
|
-
const wave = new Uint8Array(analyser.fftSize);
|
|
646
|
-
const self = {
|
|
647
|
-
context: ac,
|
|
648
|
-
analyser,
|
|
649
|
-
sample: () => {
|
|
650
|
-
analyser.getByteFrequencyData(freq);
|
|
651
|
-
analyser.getByteTimeDomainData(wave);
|
|
652
|
-
let sq = 0;
|
|
653
|
-
for (let i = 0; i < wave.length; i++)
|
|
654
|
-
sq += ((wave[i] - 128) / 128) ** 2;
|
|
655
|
-
const n = Math.max(1, Math.round(freq.length * 0.08));
|
|
656
|
-
let b = 0;
|
|
657
|
-
for (let i = 0; i < n; i++)
|
|
658
|
-
b += freq[i];
|
|
659
|
-
return { level: Math.min(1, Math.sqrt(sq / wave.length) * 2), bass: b / n / 255, freq, wave };
|
|
660
|
-
},
|
|
661
|
-
stop: () => {
|
|
662
|
-
if (current === self) {
|
|
663
|
-
current = null;
|
|
664
|
-
if (raf && typeof cancelAnimationFrame === 'function')
|
|
665
|
-
cancelAnimationFrame(raf);
|
|
666
|
-
raf = 0;
|
|
667
|
-
}
|
|
668
|
-
try {
|
|
669
|
-
src.disconnect();
|
|
670
|
-
analyser.disconnect();
|
|
671
|
-
}
|
|
672
|
-
catch {
|
|
673
|
-
/* already */
|
|
674
|
-
}
|
|
675
|
-
release();
|
|
676
|
-
setVars(0, 0);
|
|
677
|
-
},
|
|
678
|
-
};
|
|
679
|
-
current = self;
|
|
680
|
-
kick();
|
|
681
|
-
return self;
|
|
682
|
-
}
|
|
683
|
-
/** Stop the current audio source (if any). */
|
|
684
|
-
function disableAudio() {
|
|
685
|
-
current?.stop();
|
|
686
|
-
}
|
|
687
|
-
/** A pure beat detector: feed it energy (0–1) and a timestamp per frame; it answers "beat?". */
|
|
688
|
-
function createBeatDetector(o = {}) {
|
|
689
|
-
const { threshold = 1.35, cooldown = 250, history = 43, floor = 0.08 } = o;
|
|
690
|
-
const hist = [];
|
|
691
|
-
let last = -Infinity;
|
|
692
|
-
return (energy, now) => {
|
|
693
|
-
const avg = hist.length ? hist.reduce((a, b) => a + b, 0) / hist.length : energy;
|
|
694
|
-
const ready = hist.length >= 8;
|
|
695
|
-
hist.push(energy);
|
|
696
|
-
if (hist.length > history)
|
|
697
|
-
hist.shift();
|
|
698
|
-
if (ready && energy > floor && energy > avg * threshold && now - last >= cooldown) {
|
|
699
|
-
last = now;
|
|
700
|
-
return true;
|
|
701
|
-
}
|
|
702
|
-
return false;
|
|
703
|
-
};
|
|
704
|
-
}
|
|
705
|
-
const listeners = new Set();
|
|
706
|
-
let raf = 0;
|
|
707
|
-
function setVars(level, bass) {
|
|
708
|
-
if (typeof document === 'undefined')
|
|
709
|
-
return;
|
|
710
|
-
const s = document.documentElement.style;
|
|
711
|
-
s.setProperty('--usa-audio-level', level.toFixed(3));
|
|
712
|
-
s.setProperty('--usa-audio-bass', bass.toFixed(3));
|
|
713
|
-
}
|
|
714
|
-
function loop(now) {
|
|
715
|
-
raf = 0;
|
|
716
|
-
if (!current)
|
|
717
|
-
return;
|
|
718
|
-
const { level, bass } = current.sample();
|
|
719
|
-
const reduced = base.prefersReducedMotion();
|
|
720
|
-
setVars(reduced ? 0 : level, reduced ? 0 : bass);
|
|
721
|
-
for (const l of Array.from(listeners))
|
|
722
|
-
if (l.detect(bass, now))
|
|
723
|
-
l.cb({ energy: bass, time: now });
|
|
724
|
-
kick();
|
|
725
|
-
}
|
|
726
|
-
function kick() {
|
|
727
|
-
if (!raf && current && typeof requestAnimationFrame === 'function')
|
|
728
|
-
raf = requestAnimationFrame(loop);
|
|
729
|
-
}
|
|
730
|
-
/** Call `cb` on every detected beat of the current audio source. Returns an unsubscribe. */
|
|
731
|
-
function onBeat(cb, o = {}) {
|
|
732
|
-
const l = { detect: createBeatDetector(o), cb };
|
|
733
|
-
listeners.add(l);
|
|
734
|
-
kick();
|
|
735
|
-
return () => void listeners.delete(l);
|
|
736
|
-
}
|
|
737
|
-
/** Play the registered effect `name` on `el` at every beat (not under reduced motion). Returns an unbind. */
|
|
738
|
-
function bindBeat(el, name, options = {}) {
|
|
739
|
-
const { threshold, cooldown, history, floor, ...fx } = options;
|
|
740
|
-
return onBeat(() => {
|
|
741
|
-
if (!base.prefersReducedMotion())
|
|
742
|
-
registry.playEffect(el, name, fx).catch(() => undefined);
|
|
743
|
-
}, { threshold, cooldown, history, floor });
|
|
744
|
-
}
|
|
745
|
-
// --- visual effects ----------------------------------------------------------
|
|
746
|
-
/** The current sample, or a gentle synthetic one while no audio is enabled. */
|
|
747
|
-
function read(t, bins) {
|
|
748
|
-
if (current)
|
|
749
|
-
return { ...current.sample(), idle: false };
|
|
750
|
-
const freq = new Uint8Array(bins);
|
|
751
|
-
const wave = new Uint8Array(bins * 2);
|
|
752
|
-
for (let i = 0; i < bins; i++)
|
|
753
|
-
freq[i] = 70 + 50 * Math.sin(t * 2 + i * 0.35) * Math.cos(t * 0.7 + i * 0.11) * (1 - i / bins);
|
|
754
|
-
for (let i = 0; i < wave.length; i++)
|
|
755
|
-
wave[i] = 128 + 22 * Math.sin(t * 3 + i * 0.12);
|
|
756
|
-
return { level: 0.25 + 0.1 * Math.sin(t * 2), bass: 0.35 + 0.2 * Math.sin(t * 2.4), freq, wave, idle: true };
|
|
757
|
-
}
|
|
758
|
-
const audioFx = (name, description, defaults, spec) => ({
|
|
759
|
-
name,
|
|
760
|
-
kind: 'background',
|
|
761
|
-
description,
|
|
762
|
-
reduced: 'skip',
|
|
763
|
-
defaults: { colors: shared.PALETTE, background: '#0b0d12', speed: 1, quality: 1, ...defaults },
|
|
764
|
-
run: (el, o, ctx) => generative.canvasBackground(el, ctx, spec, o),
|
|
765
|
-
});
|
|
766
|
-
const AUDIO_FX = [
|
|
767
|
-
audioFx('spectrum-bars', 'Frequency bars dance to the audio (mirror them with `mirror: true`).', { bars: 48, gap: 2, mirror: false }, {
|
|
768
|
-
draw: ({ ctx, w, h, t, o }) => {
|
|
769
|
-
ctx.fillStyle = o.background;
|
|
770
|
-
ctx.fillRect(0, 0, w, h);
|
|
771
|
-
const s = read(t, o.bars);
|
|
772
|
-
const per = Math.max(1, Math.floor((s.freq.length * 0.7) / o.bars));
|
|
773
|
-
const bw = w / o.bars;
|
|
774
|
-
for (let i = 0; i < o.bars; i++) {
|
|
775
|
-
let v = 0;
|
|
776
|
-
for (let k = 0; k < per; k++)
|
|
777
|
-
v += s.freq[Math.min(s.freq.length - 1, i * per + k)];
|
|
778
|
-
const bh = (v / per / 255) * h * (o.mirror ? 0.5 : 0.9);
|
|
779
|
-
ctx.fillStyle = o.colors[i % o.colors.length];
|
|
780
|
-
ctx.fillRect(i * bw + o.gap / 2, o.mirror ? h / 2 - bh : h - bh, Math.max(1, bw - o.gap), o.mirror ? bh * 2 : bh);
|
|
781
|
-
}
|
|
782
|
-
},
|
|
783
|
-
}),
|
|
784
|
-
audioFx('pulse-ring', 'Glowing rings pulse with the bass.', { rings: 3, color: '#7c5cff' }, {
|
|
785
|
-
draw: ({ ctx, w, h, t, o }) => {
|
|
786
|
-
ctx.fillStyle = o.background;
|
|
787
|
-
ctx.fillRect(0, 0, w, h);
|
|
788
|
-
const s = read(t, 32);
|
|
789
|
-
const [r, g, b] = generative.hexRgb(o.color);
|
|
790
|
-
const base = Math.min(w, h) * 0.18;
|
|
791
|
-
for (let i = 0; i < o.rings; i++) {
|
|
792
|
-
const rad = base * (1 + i * 0.55) * (1 + s.bass * 0.6);
|
|
793
|
-
ctx.strokeStyle = `rgba(${r},${g},${b},${(0.9 - i * 0.25) * (0.4 + s.level)})`;
|
|
794
|
-
ctx.lineWidth = 3 + s.bass * 10 - i;
|
|
795
|
-
ctx.beginPath();
|
|
796
|
-
ctx.arc(w / 2, h / 2, rad, 0, Math.PI * 2);
|
|
797
|
-
ctx.stroke();
|
|
798
|
-
}
|
|
799
|
-
},
|
|
800
|
-
}),
|
|
801
|
-
audioFx('wave-ring', 'The live waveform wrapped into a circle.', { color: '#22d3ee', amplitude: 0.35 }, {
|
|
802
|
-
draw: ({ ctx, w, h, t, o }) => {
|
|
803
|
-
ctx.fillStyle = o.background;
|
|
804
|
-
ctx.fillRect(0, 0, w, h);
|
|
805
|
-
const s = read(t, 64);
|
|
806
|
-
const n = s.wave.length;
|
|
807
|
-
const base = Math.min(w, h) * 0.28;
|
|
808
|
-
ctx.strokeStyle = o.color;
|
|
809
|
-
ctx.lineWidth = 2;
|
|
810
|
-
ctx.beginPath();
|
|
811
|
-
for (let i = 0; i <= n; i++) {
|
|
812
|
-
const a = (i / n) * Math.PI * 2;
|
|
813
|
-
const rad = base * (1 + ((s.wave[i % n] - 128) / 128) * o.amplitude * 2);
|
|
814
|
-
const x = w / 2 + Math.cos(a) * rad;
|
|
815
|
-
const y = h / 2 + Math.sin(a) * rad;
|
|
816
|
-
if (i)
|
|
817
|
-
ctx.lineTo(x, y);
|
|
818
|
-
else
|
|
819
|
-
ctx.moveTo(x, y);
|
|
820
|
-
}
|
|
821
|
-
ctx.closePath();
|
|
822
|
-
ctx.stroke();
|
|
823
|
-
},
|
|
824
|
-
}),
|
|
825
|
-
];
|
|
826
|
-
/**
|
|
827
|
-
* `<usa-audio source="#track | mic" label="…">` — a toggle button (yours, as
|
|
828
|
-
* `[data-audio-toggle]`, or one it renders) that enables the audio source on
|
|
829
|
-
* click; children with `data-usa-beat="effect"` play that effect on every
|
|
830
|
-
* beat (`data-usa-beat-options` JSON; `threshold` / `cooldown` attributes).
|
|
831
|
-
* Emits `usa-beat` and `usa-audio-error`.
|
|
832
|
-
*/
|
|
833
|
-
function defineAudio(tag = 'usa-audio') {
|
|
834
|
-
return base.defineElement(tag, (Base) => class UsaAudio extends Base {
|
|
835
|
-
constructor() {
|
|
836
|
-
super(...arguments);
|
|
837
|
-
this.active = false;
|
|
838
|
-
this.audio = null;
|
|
839
|
-
this.off = null;
|
|
840
|
-
}
|
|
841
|
-
static get observedAttributes() {
|
|
842
|
-
return ['source'];
|
|
843
|
-
}
|
|
844
|
-
button() {
|
|
845
|
-
let b = this.querySelector('[data-audio-toggle]');
|
|
846
|
-
if (!b) {
|
|
847
|
-
b = document.createElement('button');
|
|
848
|
-
b.type = 'button';
|
|
849
|
-
b.setAttribute('data-audio-toggle', '');
|
|
850
|
-
b.textContent = this.str('label', '🔊 Enable sound-reactive effects');
|
|
851
|
-
this.prepend(b);
|
|
852
|
-
this.onCleanup(() => b.remove());
|
|
853
|
-
}
|
|
854
|
-
return b;
|
|
855
|
-
}
|
|
856
|
-
async toggle() {
|
|
857
|
-
const b = this.button();
|
|
858
|
-
if (this.active)
|
|
859
|
-
return this.stop();
|
|
860
|
-
try {
|
|
861
|
-
this.audio = await enableAudio(this.str('source', 'mic'));
|
|
862
|
-
this.active = true;
|
|
863
|
-
this.removeAttribute('data-audio-error');
|
|
864
|
-
b.setAttribute('aria-pressed', 'true');
|
|
865
|
-
this.off = onBeat((d) => {
|
|
866
|
-
this.dispatchEvent(new CustomEvent('usa-beat', { detail: d, bubbles: true }));
|
|
867
|
-
if (base.prefersReducedMotion())
|
|
868
|
-
return;
|
|
869
|
-
this.querySelectorAll('[data-usa-beat]').forEach((el) => {
|
|
870
|
-
let opts = {};
|
|
871
|
-
try {
|
|
872
|
-
opts = JSON.parse(el.dataset.usaBeatOptions || '{}') || {};
|
|
873
|
-
}
|
|
874
|
-
catch {
|
|
875
|
-
/* ignore bad JSON */
|
|
876
|
-
}
|
|
877
|
-
registry.playEffect(el, el.dataset.usaBeat || 'pulse', opts).catch(() => undefined);
|
|
878
|
-
});
|
|
879
|
-
}, { threshold: this.num('threshold', 1.35), cooldown: this.num('cooldown', 250) });
|
|
880
|
-
}
|
|
881
|
-
catch (err) {
|
|
882
|
-
this.setAttribute('data-audio-error', '');
|
|
883
|
-
this.dispatchEvent(new CustomEvent('usa-audio-error', { detail: { error: err }, bubbles: true }));
|
|
884
|
-
}
|
|
885
|
-
}
|
|
886
|
-
stop() {
|
|
887
|
-
this.off?.();
|
|
888
|
-
this.off = null;
|
|
889
|
-
if (this.audio && current === this.audio)
|
|
890
|
-
this.audio.stop();
|
|
891
|
-
this.audio = null;
|
|
892
|
-
this.active = false;
|
|
893
|
-
this.querySelector('[data-audio-toggle]')?.setAttribute('aria-pressed', 'false');
|
|
894
|
-
}
|
|
895
|
-
mount() {
|
|
896
|
-
const b = this.button();
|
|
897
|
-
b.setAttribute('aria-pressed', 'false');
|
|
898
|
-
this.listen(b, 'click', () => void this.toggle());
|
|
899
|
-
this.onCleanup(() => this.stop());
|
|
900
|
-
}
|
|
901
|
-
}, { id: 'usa-audio', text: 'usa-audio{display:block}usa-audio[data-audio-error] [data-audio-toggle]{outline:2px solid #ff5c8a}' });
|
|
902
|
-
}
|
|
903
|
-
|
|
904
579
|
const touchOk = (e, o) => o.touch || e.pointerType !== 'touch';
|
|
905
580
|
/** A fixed, viewport-sized canvas in the fx layer, redrawn while `draw` returns true. */
|
|
906
581
|
function overlayCanvas(draw) {
|
|
@@ -1640,7 +1315,7 @@ const EFFECT_PACKS = {
|
|
|
1640
1315
|
physics: PHYSICS_FX,
|
|
1641
1316
|
page: PAGE_FX,
|
|
1642
1317
|
generative: generative.GENERATIVE_FX,
|
|
1643
|
-
audio: AUDIO_FX,
|
|
1318
|
+
audio: audio.AUDIO_FX,
|
|
1644
1319
|
cursor: CURSOR_FX,
|
|
1645
1320
|
micro: MICRO_FX,
|
|
1646
1321
|
themes: THEME_FX,
|
|
@@ -1677,7 +1352,7 @@ function registerMicroEffects() {
|
|
|
1677
1352
|
/** Define the 5.x elements of this entry (`<usa-story>`, …) under their default tags. */
|
|
1678
1353
|
function defineEffectElements() {
|
|
1679
1354
|
player.defineStory();
|
|
1680
|
-
defineAudio();
|
|
1355
|
+
audio.defineAudio();
|
|
1681
1356
|
defineGestureFx();
|
|
1682
1357
|
defineTheme();
|
|
1683
1358
|
player.definePlayer();
|
|
@@ -1702,7 +1377,14 @@ exports.GENERATIVE_FX = generative.GENERATIVE_FX;
|
|
|
1702
1377
|
exports.canvasBackground = generative.canvasBackground;
|
|
1703
1378
|
exports.hexRgb = generative.hexRgb;
|
|
1704
1379
|
exports.noise2 = generative.noise2;
|
|
1705
|
-
exports.AUDIO_FX = AUDIO_FX;
|
|
1380
|
+
exports.AUDIO_FX = audio.AUDIO_FX;
|
|
1381
|
+
exports.bindBeat = audio.bindBeat;
|
|
1382
|
+
exports.createBeatDetector = audio.createBeatDetector;
|
|
1383
|
+
exports.defineAudio = audio.defineAudio;
|
|
1384
|
+
exports.disableAudio = audio.disableAudio;
|
|
1385
|
+
exports.enableAudio = audio.enableAudio;
|
|
1386
|
+
exports.getAudio = audio.getAudio;
|
|
1387
|
+
exports.onBeat = audio.onBeat;
|
|
1706
1388
|
exports.CARD_FX = CARD_FX;
|
|
1707
1389
|
exports.CLICK_FX = CLICK_FX;
|
|
1708
1390
|
exports.CURSOR_FX = CURSOR_FX;
|
|
@@ -1717,20 +1399,13 @@ exports.THEME_NAMES = THEME_NAMES;
|
|
|
1717
1399
|
exports.THEME_ROLES = THEME_ROLES;
|
|
1718
1400
|
exports.angleDelta = angleDelta;
|
|
1719
1401
|
exports.applyTheme = applyTheme;
|
|
1720
|
-
exports.bindBeat = bindBeat;
|
|
1721
1402
|
exports.bindGesture = bindGesture;
|
|
1722
1403
|
exports.bounceKeyframes = bounceKeyframes;
|
|
1723
1404
|
exports.bumpCount = bumpCount;
|
|
1724
|
-
exports.createBeatDetector = createBeatDetector;
|
|
1725
|
-
exports.defineAudio = defineAudio;
|
|
1726
1405
|
exports.defineEffectElements = defineEffectElements;
|
|
1727
1406
|
exports.defineGestureFx = defineGestureFx;
|
|
1728
1407
|
exports.defineTheme = defineTheme;
|
|
1729
|
-
exports.disableAudio = disableAudio;
|
|
1730
|
-
exports.enableAudio = enableAudio;
|
|
1731
1408
|
exports.flingVelocity = flingVelocity;
|
|
1732
|
-
exports.getAudio = getAudio;
|
|
1733
|
-
exports.onBeat = onBeat;
|
|
1734
1409
|
exports.playThemeEffect = playThemeEffect;
|
|
1735
1410
|
exports.registerAllEffects = registerAllEffects;
|
|
1736
1411
|
exports.registerAudioEffects = registerAudioEffects;
|