Text → flashy WebGPU / WebGL magic circle loader
Rendered on the GPU: a central pentagram/star, two dense rune bands, an inner sawtooth ring, a summoning draw-on, neon glow, and a shockwave burst on completion. Active backend: …
Animations honor prefers-reduced-motion: enable “Reduce motion” in your OS to see the calm, static fallback.
Same text always produces the same magic circle. Different text = different circle.
Add the indeterminate attribute (or omit value) for a looping pulse when total progress is unknown.
By default, colors are derived from the text hash. Override with CSS custom properties for brand-consistent colors — they drive the shader live.
magic-loading {
--ml-color-primary: #ff6b6b;
--ml-color-secondary: #ffd93d;
--ml-color-glow: #ff6b6b;
}
npm install @yeonseong/magic-loading
<script type="module">
import '@yeonseong/magic-loading';
</script>
<!-- Determinate: value 0..max (max defaults to 1) -->
<magic-loading text="Uploading..." value="0.5" size="160"></magic-loading>
<!-- Indeterminate spinner -->
<magic-loading text="Loading..." indeterminate size="160"></magic-loading>
The element is the instance — use standard DOM properties & events.
import { create } from '@yeonseong/magic-loading';
const el = create(document.getElementById('container'), {
text: 'Loading...', size: 160, value: 0,
});
el.value = 0.5; // update progress (reflects to attribute)
el.indeterminate = true; // spinner mode
el.text = 'Almost done'; // regenerate the circle
el.addEventListener('complete', () => console.log('done!'));
await el.complete(); // play burst, then fire `complete`
el.remove(); // teardown
<script src="https://unpkg.com/@yeonseong/magic-loading/dist/index.global.js"></script>
<script>
const el = MagicLoading.create(
document.getElementById('loader'),
{ text: 'Hello', size: 160 }
);
</script>
All attributes reflect to JS properties (e.g. el.value = 0.6).
| Attribute | Type | Default | Description |
|---|---|---|---|
text | string | — | Text hashed into a unique magic circle (required) |
value | number | 0 | Progress, 0..max (aligns with native <progress>) |
max | number | 1 | Progress upper bound |
indeterminate | boolean | false | Spinner mode (also implied when value is omitted) |
size | number | 120 | Width & height in pixels |
label | string | text | Accessible name (exposed via ARIA progressbar) |
renderer | auto·webgpu·webgl | auto | Force a backend (auto picks WebGPU, falls back to WebGL) |
ready — fires when a GPU backend mounts (detail.renderer). complete — fires after the burst.
progress attribute, and setProgress()/setText()/destroy() methods — prefer value/indeterminate, el.text, el.remove().