Fluted Glass
Optical ribs with three compositions: close reeds, diagonal prisms and a moving lens window.
Install the component, then paste your configured usage. Your settings are included in the code below.
Pro source comes with Arclen UI Pro. See plans
| Property | Type | Default |
|---|---|---|
choiceDesign Options: A (Reed), B (Prism), C (Lens window) | select | "A" |
sourceModeSource Options: video (Video), image (Image), procedural (Shader) | select | "video" |
imageSourceImage source Up to 2048 characters | image | "assets/city-portrait.webp" |
imageZoomImage zoom Image-only zoom in cover mode. Set to 1 for the full cover crop. 1–3Step 0.05 | number | 1.65 |
imagePositionYImage vertical position Image focal point from top (0) to bottom (1). Applies in cover mode. 0–1Step 0.01 | number | 0.26 |
accessibleNameMedia description Up to 240 characters | text | "Portrait photography, sculptural video and colored light seen through refracting glass." |
videoSourceVideo source Up to 2048 characters | text | "assets/ribbon-loop.mp4" |
posterSourceVideo poster Up to 2048 characters | image | "assets/ribbon-poster.webp" |
fluteCountFlute count Reed rib count. Omitted values follow Video 118, Image 70 and Shader 30; custom values remain shared across modes. Source buttons follow the new mode defaults while the previous mode defaults are unchanged. Prism uses 28% and Lens window 45% of the chosen count. 8–192Step 1 | number | 118 |
angleAngle offset -60–60Step 1 | number | 0 |
strengthDisplacement 0–2Step 0.05 | number | 1.25 |
lightingSeam light and shadow Optional seam lighting. Reed Video and Image default to 0; Shader, Prism and Lens window default to 0.55 when omitted. 0–1Step 0.05 | number | 0 |
windowWidthLens width 0.2–0.8Step 0.01 | number | 0.46 |
windowPositionLens position 0–1Step 0.01 | number | 0.5 |
fitSource fit Options: cover (Cover), contain (Contain) | select | "cover" |
paletteLight palette Options: copper (Copper / ice), cobalt (Cobalt / pearl), orchid (Orchid / amber) | select | "copper" |
speedMotion speed Zero freezes all motion. Video uses a minimum positive playback rate of 0.0625; procedural and lens motion use the exact setting. 0–2Step 0.05 | number | 1 |
pausedPause | boolean | false |
windowSweepSweep lens | boolean | true |
showSourceControlsSource controls | boolean | false |
showPauseControlShow pause button Optional separate pause button. Space toggles pause when the effect itself is focused. | boolean | false |
backgroundBackground | color | "#000000" |
sizingSizing Options: fill (Fill container), standalone (Standalone) | select | "fill" |
heightHeight 240–1100Step 1 | number | 620 |
Fluted Glass
Three original optical compositions share one source pipeline. **Reed** uses close cylindrical ribs. **Prism** uses wider ribs on a 35° diagonal. **Lens window** puts broad ribs inside a rounded window and leaves the surrounding image clear.
Choose Video, Image or Shader independently of the composition. Video is the default: an original metallic ribbon rotates on black with violet and ember illumination in a silent 5.5-second, 1920×1080 loop. Image uses a tightly framed head-and-shoulders portrait of a hooded figure among a blurred city crowd. Shader creates a moving broad cobalt/rust light field with three palettes; the API value remains sourceMode: 'procedural'. WebGL evaluates that field in the fragment shader, with a Canvas 2D geometric-light approximation when WebGL is unavailable.
React
import { FlutedGlass } from './fluted-glass/src/react';
<FlutedGlass choice="A" sourceMode="image" sizing="standalone" height={620} />React applies changed prop values individually. Source and pause choices made through the built-in buttons survive unrelated parent rerenders. Changing a supplied prop overrides that setting; removing it restores its resolved default.
Vanilla and HTML
import { mount } from './fluted-glass/src/core';
import './fluted-glass/src/styles.css';
const glass = mount(document.querySelector('#glass'), {
choice: 'C', sourceMode: 'video', sizing: 'standalone', height: 620
});
glass.update({ strength: 0.65 });
glass.pause();
glass.resume();
glass.destroy();render(settings, id?) supplies a static image and disabled controls for server-rendered HTML. mount(host, settings, id?) upgrades that host. update accepts partial settings. A second mount on the same host destroys its previous instance before creating the replacement. Destroying an old controller cannot affect the replacement. Invalid types, unknown settings and unsafe URLs throw before state changes. Import defaults and resolveSettings to use the manifest defaults without a renderer.
Reed defaults to cover framing for a larger, edge-cropped subject in portrait containers. Image cover framing defaults to imageZoom: 1.65 and imagePositionY: 0.26. These controls enlarge the subject and set its vertical focal point without changing the optical ribs. Set zoom to 1 for the normal cover crop. Set fit: 'contain' to keep the complete source visible; contain ignores image zoom and focal point. The Lens window preview retains contain framing; Prism remains full-frame procedural light. Explicit fit settings are honored for images and videos. Procedural mode always paints the full frame.
Fill sizing requires a parent with a definite height. The React receiving host uses height: 100% in fill mode unless style.height is supplied. Standalone mode leaves the receiving host height unforced. Use standalone sizing for normal document flow. Source selection lives in the host Tweaks panel by default. Pause with Space when the effect itself has keyboard focus, use the host inspector, or set showPauseControl: true for a separate visible button. Set showSourceControls: true to opt into source buttons inside an embedded effect. The catalogue Tweaks panel accepts local images and videos; local files remain in the browser and must be replaced with project asset URLs before export. The default accessibleName describes the bundled portrait, sculptural video and light generically, so it remains accurate when modes change. Set it to describe custom media; source changes preserve that override.
Controls
Reed's omitted fluteCount follows the source: Video 118, Image 70 and Shader 30. Shader retains its 20° tilt. Explicit counts are literal for Reed and remain shared across programmatic source changes. The source buttons use the mode-default behavior described below. Prism and Lens window retain default count 128, scaled to 28% and 45% respectively; their working previews use 84. angle offsets each design's orientation.
strength controls displaced source sampling. Reed Video and Image use cubic displacement in CSS pixels, normalized at strength 1.25, independently of viewport size and rib count. Both default to lighting: 0. Image converts composed source colors to linear-light values before texture resampling. Shader, Prism and Lens window use 0.55 lighting when omitted. Nonzero lighting adds seam highlights and trough shadows. Zero strength and zero lighting remove optical displacement and seam lighting; Reed Image retains its color transfer.
Omitted count and lighting values follow mode defaults when the source changes. During programmatic source updates, explicit values supplied to mount or update stay fixed across modes, including values supplied in a fully resolved settings snapshot. To resume inheritance, call update({ fluteCount: undefined, lighting: undefined }). React removes the corresponding override when its prop is removed.
Lens width and position apply to Lens window. windowSweep adds a bounded sweep around the chosen position. speed: 0 freezes all motion. Positive video speeds below 0.0625 play at 0.0625×, the supported browser floor. Procedural and lens animation use the exact positive speed setting. paused is the visible pause setting; controller pause() additionally suspends the instance without changing settings. Offscreen, hidden-page and reduced-motion states suspend playback and animation automatically. Reduced motion centers the authored sweep at the selected window position.
imageSource, videoSource and posterSource accept relative, HTTP(S) or browser-owned blob URLs. Cross-origin media must permit canvas access through CORS. Empty image values use the city portrait; a failed video uses the bundled ribbon poster. Failed custom images use the city portrait. Custom video poster appears while that video is loading in static HTML. Source changes preserve the last ready rendered frame until decoding succeeds. Updating posterSource updates the fallback and active or pending video poster without restarting playback. Browser autoplay restrictions leave a usable still; Pause then Resume retries playback. The component does not revoke caller-owned blob URLs.
Rendering and fallback
The renderer uses an original periodic image-space displacement, with narrow seam lighting conditioned on source luminance and local contrast. The black video field stays black. Reed Video defaults to 118 ribs and strength 1.25; the mapping is an authored image-space effect rather than a physical refractive-index model. WebGL context loss switches to a Canvas 2D strip-sampling renderer; that fallback still moves source coordinates. Without JavaScript, the bundled static still remains. This static fallback intentionally does not animate.
Canvas resolution is capped at 1440×1000 and DPR 1.5. The 2D fallback uses at most 1440 one-pixel columns for vertical Reed Video or Image, fewer than 1760 strips for angled Reed Video or Image, and approximately 900 strips for the other modes. Video shares pixel-center phase and CSS displacement math across WebGL and Canvas 2D; raster interpolation can differ between browser backends. Reed Image decodes through an 8-bit sRGB EOTF lookup after cover/contain composition, then resamples into a power-of-two texture and generates trilinear mipmaps. Static textures are cached until media identity, size, fit or background changes; optical controls reuse the texture. Texture dimensions respect the GPU limit. Canvas 2D uses the same color conversion and displacement with cached downsampled levels; vertical ribs choose the nearest mip level from the local displacement derivative, while angled ribs use an approximate common level. Its minification and interpolation can differ from WebGL, particularly at rib resets. Destroy and context loss release cached canvases and textures. These are work bounds, not performance claims. Run frame-time checks on the intended device and container.
Keep assets beside the component when copying the source. Bundled media imports are rewritten by the host bundler; the runtime does not call an external service. The generator is a development utility and is not imported by the component.
Source selection activates immediately. Source-pill backgrounds fade over 200ms; label colors change immediately. Reduced-motion preference removes these fades. Copper moves saturated illumination and color fields across the ribs. Cobalt and Orchid also vary overall exposure.
Source buttons follow each mode’s rib count and seam lighting while those values still match the previous mode’s defaults. Custom optical values carry across source changes. Programmatic update({sourceMode}) retains explicitly configured optical values; pass fluteCount: undefined and lighting: undefined to restore automatic mode defaults.
The preview runs the component’s own JavaScript. It respects reduced motion and pauses when off screen. The HTML bundle includes a poster fallback.
Every setting in this panel comes from the component manifest. Preview size, pause and replay stay in the inspector.