JavaScript Documentation

Setup, media, settings and API reference for Filmstrip Photo & Video Slider.

Getting started

Filmstrip Photo & Video Slider displays a draggable 3D ribbon. A frame opens a category of photos and looping videos. Categories stay inside the same Three.js canvas, with their own navigation, captions and optional category selector.

  • Serve the page over HTTP or HTTPS. Opening an HTML file directly with file:// will not load the model and textures correctly.
  • Use a browser with WebGL support. The gallery creates a WebGL canvas for its media and HTML controls for navigation.
  • Use native JavaScript booleans such as true and false. Do not quote them.
  • All public duration and delay settings use seconds. For example, 0.65 means 650 milliseconds.
  • Scene dimensions, CSS pixel values and progress fractions have different units. Each setting below states which unit it uses.

Installation

Start with start.html, the complete customer reference. It contains the current settings and the gallery HTML for the supplied photo and video collections. Keep it beside the src, content and media folders.

Open start.html

Path beside start.htmlPurpose
start.htmlEditable customer page with the visible gallery host, hidden category markup and constructor settings.
src/FWDFPAVS.jsCompiled script that exposes the FWDFPAVS constructor. Three.js and the model decoder are bundled with it.
content/global.cssGallery controls, dropdown, preloader and error styles.
content/Keep the complete folder, including the textures used by optional effects.
media/models/film_frame.glbSupplied film holder model.
media/images/ and media/videos/Sample photos, videos and posters. Replace these and update the HTML paths.

Upload the page and its folders to your server, then open start.html over HTTP or HTTPS. A customer using the compiled files does not need Node.js or a build step. Keep filename capitalization unchanged on servers with case-sensitive paths.

Load the stylesheet in the document head and the script before calling the constructor. Create the visible host and hidden data markup first. Load your chosen fonts before initialization so film labels and captions use the correct measurements.

<link rel="stylesheet" href="content/global.css">
<script src="src/FWDFPAVS.js"></script>

In the source project, edit public/start.html and run npm run build. The command refreshes public/src/FWDFPAVS.js, then copies the reference and its assets to build/start.html. Publish the contents of build. Do not make permanent edits only in the generated build folder.

The marketing demos use a separate layout with js/filmstrip-gallery.js, content/filmstrip.css and media/gallery/. Those paths are for the demo pages. Use the paths in start.html for the customer reference and do not load both bundles or both stylesheets.

Keep the supplied model unless you have adapted a replacement to the expected holder and photo geometry. Pointing the setting at an arbitrary GLB is not enough to make it a compatible film frame.

Editing start.html

Use this file as your first integration reference. It includes landscape and portrait images, video covers, mixed photo and video categories, and optional captions.

  • The visible div id="myDiv" is the gallery host. The page uses displayType: 'afterparent', so the CSS height of this host controls the gallery height. Change its height to fit your layout.
  • The hidden div id="carouselData" holds one article per category. Edit the cover, title, film code and media figures there. Keep at least two ribbon articles and give each a unique category ID.
  • The settings are grouped at the bottom of the file. Change those values before initialization. Use native booleans and seconds for durations. Keep parentId and carouselDataId matched to the HTML IDs.
  • The final script loads src/FWDFPAVS.js, waits for Roboto, and calls new FWDFPAVS(...) once. It stores the controller as window.gallery for API calls.
  • Replace each photo, video and poster path with your own media. Update width and height to the real dimensions. Remove caption attributes from items that should have no caption.
  • For a bounded gallery inside a scrolling page, remove the full-page overflow rule and give the host your desired height. Alternatively use responsive mode with maxHeight and autoScale as described below.
gallery.getState()
gallery.openCategory(0)
gallery.destroy()

The customer reference and the source development page index.html are separate editable pages. A build preserves your edits to public/start.html while refreshing its compiled script.

Compact demo example

For a shorter illustration, this separate example uses two categories and the marketing demo asset paths. Save it beside the demo index page. For customer installation, start with start.html and the paths listed above.

Open the compact demo example

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Filmstrip quick start</title>
    <link rel="stylesheet" href="content/filmstrip.css">
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;600;700&display=swap">
    <style>
        body { margin: 0; background: #fff; font-family: Roboto, sans-serif; }
        #gallery-holder { width: 100%; height: 100vh; height: 100dvh; }
    </style>
</head>
<body>
    <div id="gallery-holder"></div>
    <div id="gallery-data" hidden>
        <article data-gallery-id="mountains" data-title="ALPINE LIGHT" data-film-code="01 / 02">
            <div data-src="media/gallery/videos/138276.mp4" data-poster="media/gallery/videos/138276.webp" data-width="1280" data-height="720"></div>
            <template data-gallery>
                <h2 data-gallery-title>Alpine Light</h2>
                <p data-gallery-category>Alpine Light</p>
                <figure data-gallery-media>
                    <video data-gallery-src="media/gallery/videos/138276.mp4" poster="media/gallery/videos/138276.webp" width="1280" height="720" aria-label="Clouds drifting over a sunlit alpine mountain valley." data-caption-title="Alpine Air" data-caption-description="Clouds move across the ridgeline." muted loop playsinline preload="none"></video>
                </figure>
<figure data-gallery-image>
                    <img data-gallery-src="media/gallery/images/collections/mountains/8195019.webp" data-caption-title="A Clear Reflection" data-caption-description="Blue sky, still water and a mountain reflected." width="1280" height="853" alt="The Matterhorn reflected in a bright blue alpine lake beside rocks and green grass.">
                </figure>
            </template>
        </article>
        <article data-gallery-id="waterfalls" data-title="FALLING WATER" data-film-code="02 / 02">
            <div data-src="media/gallery/videos/267095.mp4" data-poster="media/gallery/videos/267095.webp" data-width="720" data-height="1280"></div>
            <template data-gallery>
                <h2 data-gallery-title>Falling Water</h2>
                <p data-gallery-category>Falling Water</p>
                <figure data-gallery-image>
                    <img data-gallery-src="media/gallery/images/collections/waterfalls/272654.webp" data-caption-title="Pools of Jade" data-caption-description="Water steps through the green canopy." width="1280" height="857" alt="Terraced waterfalls flow into bright turquoise pools surrounded by vivid green foliage.">
                </figure>
<figure data-gallery-image>
                    <img data-gallery-src="media/gallery/images/collections/waterfalls/2191156.webp" width="960" height="1280" alt="Portrait view from above of a waterfall dropping into a turquoise pool beneath leafy trees.">
                </figure>
            </template>
        </article>
    </div>
    <script src="js/filmstrip-gallery.js"></script>
    <script>
        async function startGallery() {
            if (document.fonts) await document.fonts.ready
            window.gallery = new FWDFPAVS({
            instance: 'exampleGallery',
            parentId: 'gallery-holder',
            carouselDataId: 'gallery-data',
            displayType: 'afterparent',
            backgroundColor: '#ffffff',
            filmFrameModel: 'media/gallery/models/film_frame.glb',
            frameWidth: 6.8,
            frameHeight: 5.1,
            filmStripColor: '#000000',
            filmStripTextColor: '#d9d9d9',
            showPreloader: true,
            preloaderImageDelay: 0.05,
            useBlackAndWhite: true,
            opacityStrength: 1,
            imageSharpenStrength: 0.5,
            useFilmCurve: true,
            useRibbonMouseWheel: false,
            useCategoryMouseWheel: false,
            useCategoryPickerMouseWheel: true,
            categoryButtonColor: '#111111',
            categoryButtonIconColor: '#ffffff',
            categoryTextColor: '#111111',
            categoryImageCounterColor: '#707070',
            categoryCurrentImageNumberColor: '#000000',
            showCateogryNavigationArrows: true,
            showCateogryNavigationSelect: true,
            useFlowmap: false,
            useNoise: false,
            grid: false,
            waveAmplitude: 0,
            deepLinking: true,
            stats: false,
            gui: false,
            events: {
                ready(event) {
                    console.log('Gallery ready', event.categories)
                },
                categoryOpened(event) {
                    console.log('Category opened', event.category.title)
                },
                error(event) {
                    console.error(event.message)
                }
            }
            })
        }
        startGallery()
    </script>
</body>
</html>

Categories, images and videos

Add one article for each ribbon entry inside the hidden data element. A category article needs a unique data-gallery-id, a cover element, and a template data-gallery. The template keeps its media unloaded until the gallery requests it. The slider reads this markup, it does not scan folders on your server.

Use at least two ribbon entries. The current parser keeps the last 49 entries if more than 49 are supplied. Each category needs at least one media figure and a nonempty gallery title.

<div id="gallery-data" hidden>
    <article data-gallery-id="coast" data-title="SALT AND SEA" data-film-code="01 / 02">
        <div data-src="media/coast/cover.webp" data-width="1280" data-height="853"></div>
        <template data-gallery>
            <h2 data-gallery-title>Salt and Sea</h2>
            <figure data-gallery-media>
                <img data-gallery-src="media/coast/cover.webp" width="1280" height="853"
                     alt="Sunlight over the coast" data-deep-link-id="open-blue"
                     data-caption-title="An Open Blue"
                     data-caption-description="A quiet morning by the water.">
            </figure>
            <figure data-gallery-media>
                <img data-gallery-src="media/coast/portrait.webp" width="853" height="1280"
                     alt="A tall cliff beside the sea">
            </figure>
        </template>
    </article>
    <article data-gallery-id="woods" data-title="DEEP WOODS" data-film-code="02 / 02">
        <div data-src="media/woods/stream.mp4" data-poster="media/woods/stream.webp"
             data-width="720" data-height="1280"></div>
        <template data-gallery>
            <h2 data-gallery-title>Deep Woods</h2>
            <figure data-gallery-media>
                <video data-gallery-src="media/woods/stream.mp4" poster="media/woods/stream.webp"
                       width="720" height="1280" aria-label="Water running over green rocks"
                       data-deep-link-id="moss-motion" data-caption-title="Moss and Motion"
                       muted loop playsinline preload="none"></video>
            </figure>
        </template>
    </article>
</div>
Attribute or elementMeaning
data-gallery-idRequired unique category ID. Used by the API.
data-titleText printed on the film rail. Falls back to the gallery title, then filmStripName.
data-film-codeSmaller film rail code. Text is aligned to the right and keeps its proportions. An empty string hides it.
data-srcCover image or video URL. Put it on a child element inside the article.
data-width and data-heightActual cover dimensions. Use positive numbers with the correct aspect ratio.
data-posterRequired poster image when data-src is a video URL.
template[data-gallery]Container for the category title and authored media figures.
data-gallery-titleRequired category display title, provided as text inside an element such as h2.
figure[data-gallery-media]One category item. Both images and videos use this wrapper. The older data-gallery-image wrapper is also accepted.
data-gallery-srcImage or video source read by the asynchronous loader. Use this instead of src on template media.
width and heightRequired positive dimensions on every category image or video. These determine each mesh aspect ratio.
posterRequired image on a category video. data-gallery-poster is also accepted.
alt or aria-labelUse alt for an image and aria-label for a video to describe the media.
data-caption-titleOptional caption title. Can be on the media or its figure. The media attribute takes precedence.
data-caption-descriptionOptional caption description. Can be on the media or its figure. A figcaption text value is used as a fallback.
data-deep-link-idOptional stable item ID. Put it on the media or figure when you need URLs and API navigation to survive caption edits.

Include the cover in its category template using the same source or poster URL. This lets the opening transition reuse the cover instead of adding a separate entry. When you close a category, the nearest image can become its remembered ribbon cover. The authored item indices stay the same even if display order changes.

Images can be landscape, portrait, square or panoramic. Keep their real dimensions in the markup. JPG, PNG and WebP are supported. PNG transparency is preserved over the mesh background.

Video playback and loading

Visible videos autoplay muted, loop and have no player controls. Partially visible videos can play too. The dropdown uses poster thumbnails, while category arrow hover previews can play the destination cover video.

Posters are required because they provide the loading image, stable dimensions and a fallback before a video frame is available. A poster is also used if playback is blocked or the video fails.

  • Ribbon startup loads cover images and video posters. It does not download every category video before showing the ribbon.
  • Category images load asynchronously, with nearby visible items prioritized. Placeholder meshes appear before the image fades in.
  • Video sources are attached when needed for visible meshes. Matching sources share playback resources across the ribbon and category transitions.
  • Hidden videos pause. After about 1.5 seconds offscreen, their source and texture can be released. Playback time is remembered for a later return.
  • A hidden tab, gallery pause or destroy stops video playback. Browser autoplay restrictions can still require a pointer or keyboard interaction.

Use your own browser-compatible MP4 files and poster images. Add their URLs to the gallery markup and set width and height to the actual video dimensions.

A ribbon frame can open your URL instead of a category. Add data-link to the article or its cover element. This works with the supplied GLB film model.

For a link entry, omit data-gallery-id and template data-gallery. Keep the cover image or video, title and optional film code. If category markup is present, the category takes precedence over the link.

<article data-title="VIEW PROJECT" data-link="https://example.com/project" data-target="_blank">
    <div data-src="media/project.webp" data-width="1280" data-height="853"></div>
</article>

The frame centers and opens the URL without the category zoom. Use data-target="_self" for the current tab or _blank for a new tab. The default is _blank.

Set useActionOnlyOnCenterMesh: true if the first click on an off-center frame should only center it. Click the centered frame again to open its link or category. With false, a single click centers the frame and performs its action.

No action

A filmstrip frame can display a photo or video without opening a category or link. Keep its cover markup and omit data-gallery-id, template[data-gallery] and data-link from the article and its children. No extra JavaScript setting is required.

<article data-title="QUIET MOMENT" data-film-code="FRAME 01">
    <div data-src="media/quiet-moment.webp" data-width="1280" data-height="853"></div>
</article>

Clicking the frame centers it in the filmstrip. It does not zoom, open a category or follow a link, even when clicked again in the center. Dragging, hover effects and visible video playback remain available. This behavior also applies with the supplied GLB film model.

The useActionOnlyOnCenterMesh setting controls when category and link actions run. It does not add an action to a frame configured with no action.

Sizing and responsive layout

In afterparent mode, give the host an explicit height. A width of 100% and height of 100dvh produces a full viewport gallery. In responsive mode, the gallery sets its own host height from the sizing options.

displayType: 'responsive',
maxWidth: 1920,
maxHeight: 750,
autoScale: true,
autoScaleStartWidth: 1200

Below autoScaleStartWidth, the responsive height follows 450 + (maxHeight - 450) * (width / autoScaleStartWidth)^2.5. At wider sizes it uses maxHeight. Responsive galleries always keep at least 450px of height, including when autoScale is disabled or maxHeight is set below 450.

The title, close button, category arrows and image navigation are positioned within the gallery. They scroll with the gallery on a long page. They do not follow the browser edges independently.

The ribbon and category row wrap only when enough media cover the view. A short collection uses finite navigation. Category images retain their own aspect ratios, so their widths and visible count can differ.

Most settings are read during construction. Changing the original settings object later does not rebuild the gallery. Use API methods for navigation. To apply a different configuration, call destroy() and create a new instance. Call resize() after a layout change that does not trigger a browser resize.

Settings reference

The values below are examples from the current root index.html, not a list of omitted-value defaults. Keep the complete configuration from a working demo when starting a new integration. Some parser defaults differ from the demo values, especially optional effects and developer controls.

Booleans are unquoted. Durations are in seconds. Rotation is in radians. Caption and category spacing is in CSS pixels, while ribbon dimensions and transforms are in scene units.

The two category navigation flags are currently spelled showCateogryNavigationArrows and showCateogryNavigationSelect. Use these exact names. Enable both, either one, or neither. They replace the old categorySelectorType option.

General settings

instance

String | Example value "fwdfpavs0"

Unique name for this gallery. The instance is also registered as window[instance]. Use a different name for each gallery.

parentId

String | Example value "myDiv"

ID of the visible element that holds the canvas. Create this element before constructing the gallery.

carouselDataId

String | Example value "carouselData"

ID of the hidden element containing the ribbon articles and category templates.

displayType

String | Example value "afterparent"

Use "afterparent" to follow the host width and height. Use "responsive" to let the gallery calculate its height from maxHeight, autoScale and autoScaleStartWidth.

initializeWhenVisible

Boolean | Example value false

Wait until the host enters the viewport before starting data and media loading.

deepLinking

Boolean | Example value true

Read and write the category and item in the URL hash. Defaults to false when omitted. Enable this on only one gallery per page.

backgroundColor

String | Example value "#ffffff"

Canvas background color. Match the surrounding page when you want the gallery to blend into the layout.

maxWidth

Number | Example value 1920

Maximum canvas width in CSS pixels for responsive mode. In afterparent mode the host controls the width.

maxHeight

Number | Example value 820

Maximum canvas height in CSS pixels for responsive mode. Values below 450 use the minimum height of 450 pixels. In afterparent mode set a height on the host instead.

autoScale

Boolean | Example value true

In responsive mode, reduce the gallery height on narrower screens toward a minimum of 450 pixels. Has no sizing effect in afterparent mode.

autoScaleStartWidth

Number | Example value 1200

Container width in CSS pixels below which responsive height starts scaling. Used when autoScale is true.

showPreloader

Boolean | Example value true

Show the flat cover sequence before the ribbon intro. Video covers use their posters in this sequence.

preloaderImageDelay

Number | Example value 0.05

Minimum time between cover previews in seconds. Values below 0.05 are clamped to 0.05.

preloaderColor

String | Example value "#000000"

Color of the fallback SVG loader used without a film model. This does not recolor the photo sequence used by the current ribbon.

scrollSpeedStrength

Number | Example value 0.7

Movement sensitivity shared by ribbon and category navigation. Larger values increase the response to input.

useBlackAndWhite

Boolean | Example value true

Blend side images toward black and white while keeping the active image in color. Applies to the ribbon and opened category.

opacityStrength

Number | Example value 1

Minimum opacity of ribbon images away from the center, from 0 to 1. Use 1 to keep side frames fully visible.

imageSharpenStrength

Number | Example value 11.5

Image sharpening amount from 0 to 1. Values above 1 are clamped to 1, including the current index value shown here.

stats

Boolean | Example value false

Display the developer performance monitor. Keep false on a published gallery unless you need to inspect rendering performance.

gui

Boolean | Example value false

Display the live developer settings panel. Keep false for the normal visitor interface.

Ribbon settings

filmFrameModel

String | Example value "media/models/film_frame.glb"

URL of the supplied film_frame.glb holder. Required for the current film ribbon and Three.js category experience.

frameWidth

Number | Example value 6.8

Film frame width in scene units. The frameWidth / frameHeight ratio controls the ribbon photo proportions and related frame previews.

frameHeight

Number | Example value 5.1

Film frame height in scene units. Category images use their own authored width and height instead of this fixed ratio.

filmStripGap

Number | Example value 0

Extra spacing between neighboring frames in the main horizontal filmstrip, measured in 3D scene units rather than pixels. Use 0 to keep the filmstrip connected. Increase this value to separate its frames. This does not change the spacing between images inside an opened category or the temporary intro spread.

filmStripName

String | Example value "FILMSTRIP PHOTO & VIDEO SLIDER"

Fallback film rail title when an article has no title. An article data-title or gallery title takes precedence.

filmStripColor

String | Example value "#000000"

Base material color of the GLB holder. Lighting affects the rendered shade. Also used by the category frame previews.

filmStripTextColor

String | Example value "#d9d9d9"

Color of the labels drawn on the film rails.

useRibbonMouseWheel

Boolean | Example value true

Enable mouse-wheel and trackpad navigation over the ribbon. Dragging and touch swiping still work when false.

infinite

Boolean | Example value true

Allow the ribbon to wrap when there are enough frames to cover the view. The gallery falls back to finite navigation when repeating would leave a gap.

snap

Boolean | Example value false

Settle the ribbon toward a centered frame after movement. Clicking a frame can center it regardless of this setting.

useActionOnlyOnCenterMesh

Boolean | Example value false

When true, clicking an off-center ribbon frame only centers it. Click again once centered to open its category or link. When false, the first click centers the frame and performs its action.

useFilmCurve

Boolean | Example value true

Enable the ribbon curve. Set false for a straight ribbon. Category and selector bending have their own settings.

centerFrameFlattenStrength

Number | Example value 0

Flatten the center ribbon frame, from 0 to 1. A larger value reduces its local bend.

scrollBendStrength

Number | Example value 0.7

Extra ribbon bending caused by movement. Use 0 to remove movement-driven bending while keeping the resting curve.

scrollScaleStrength

Number | Example value 0

Scale the ribbon group in response to movement speed. Use 0 to keep the group scale steady.

filmIntroDuration

Number | Example value 0.9

Base intro fade duration in seconds. The center preview morph and side reveals share a coordinated schedule. Stagger and side delays can extend the full intro.

filmIntroStaggerDelay

Number | Example value 0.05

Additional reveal delay in seconds for each step away from the center frame.

filmIntroSideDelay

Number | Example value 0.1

Extra reveal delay in seconds for side frames, giving the center frame a head start.

filmIntroSpread

Number | Example value 3.8

Extra spacing measured in frame widths. Used by the ribbon intro and the category opening, switching and closing transitions. It is not a pixel distance.

x

Number | Example value 0

Horizontal position of the entire ribbon group in scene units.

y

Number | Example value 0.4

Vertical position of the entire ribbon group in scene units.

z

Number | Example value 0

Depth position of the entire ribbon group in scene units.

rotationX

Number | Example value 0

Rotation of the entire ribbon group around X, in radians.

rotationY

Number | Example value 0

Rotation of the entire ribbon group around Y, in radians.

rotationZ

Number | Example value 0

Rotation of the entire ribbon group around Z, in radians.

cameraPositionX

Number | Example value 0

Horizontal camera offset in scene units.

cameraPositionY

Number | Example value 0

Vertical camera offset in scene units.

Category settings

useCategoryMouseWheel

Boolean | Example value true

Enable mouse-wheel and trackpad navigation over the opened category. Independent of ribbon and dropdown wheel settings.

categoryImageGap

Number | Example value 40

Horizontal spacing between images inside an opened category, measured in CSS pixels. Galleries narrower than 600 pixels use half this value. Use filmStripGap to change spacing between the main filmstrip frames instead.

categoryBendStrength

Number | Example value 0.14

Shared bending of category images while moving, clamped from 0 to 1. Use 0 for a flat category row.

categoryImageBackgroundColor

String | Example value "#b8bcc2"

Placeholder color visible before a category image or video poster finishes loading and fading in.

categorySwitchDuration

Number | Example value 0.65

Outgoing fade and incoming reveal timing in seconds when changing categories. Clamped from 0.1 to 2.

categoryButtonColor

String | Example value "#111111"

Base color of close and navigation button discs and hover outlines. Difference blending applies only where the controls overlap category photos.

categoryButtonIconColor

String | Example value "#ffffff"

Color of the symbols inside the category buttons.

categoryTextColor

String | Example value "#111111"

Base color of the opened category title, before image-only difference blending.

categoryImageCounterColor

String | Example value "#707070"

Color of the total image count and separator between the image navigation arrows.

categoryCurrentImageNumberColor

String | Example value "#000000"

Color of the current image number between the image navigation arrows.

Caption settings

categoryCaptionEnabled

Boolean | Example value true

Show captions authored on category images and videos. Items without caption text remain caption-free.

categoryCaptionSmallViewportWidth

Number | Example value 360

Gallery viewport width in CSS pixels at which the small caption values apply. Caption sizing follows the gallery viewport, not the image aspect ratio.

categoryCaptionFullSizeViewportWidth

Number | Example value 1000

Gallery viewport width in CSS pixels at which the full caption values apply. Values interpolate between the two width thresholds.

categoryCaptionTitleFontFamily

String | Example value "Roboto, sans-serif"

CSS font-family used for caption titles. Load the font before constructing the gallery.

categoryCaptionDescriptionFontFamily

String | Example value "Roboto, sans-serif"

CSS font-family used for caption descriptions. Load the font before constructing the gallery.

categoryCaptionTitleFontSize

Number | Example value 23

Full-size caption title font size in CSS pixels, clamped from 1 to 200.

categoryCaptionTitleFontSizeSmall

Number | Example value 16

Caption title font size at the small viewport threshold, in CSS pixels.

categoryCaptionDescriptionFontSize

Number | Example value 15

Full-size caption description font size in CSS pixels, clamped from 1 to 200.

categoryCaptionDescriptionFontSizeSmall

Number | Example value 14

Caption description font size at the small viewport threshold, in CSS pixels.

categoryCaptionTitleFontWeight

Number | Example value 600

Caption title font weight from 1 to 1000. The strings "normal" and "bold" also map to 400 and 700.

categoryCaptionDescriptionFontWeight

Number | Example value 400

Caption description font weight from 1 to 1000. The strings "normal" and "bold" also map to 400 and 700.

categoryCaptionTitleFontStyle

String | Example value "normal"

Caption title font style. Accepts "normal", "italic" or "oblique".

categoryCaptionDescriptionFontStyle

String | Example value "normal"

Caption description font style. Accepts "normal", "italic" or "oblique".

categoryCaptionTitleLineHeight

Number | Example value 1.2

Unitless title line-height multiplier from 1 to 4. Applies within a wrapped title, not to the title-to-description gap.

categoryCaptionDescriptionLineHeight

Number | Example value 1.4

Unitless description line-height multiplier from 1 to 4.

categoryCaptionTitleLetterSpacing

Number | Example value 0

Additional spacing between title characters in CSS pixels, from -10 to 30.

categoryCaptionDescriptionLetterSpacing

Number | Example value 0

Additional spacing between description characters in CSS pixels, from -10 to 30.

categoryCaptionTitleMaxLines

Number | Example value 2

Maximum title lines from 0 to 20. Use 0 to hide the title block. The caption height budget can reduce the visible text further.

categoryCaptionDescriptionMaxLines

Number | Example value 2

Maximum description lines from 0 to 20. Use 0 to hide the description block. The caption height budget can reduce the visible text further.

categoryCaptionTitleColor

String | Example value "#ffffff"

Caption title text color.

categoryCaptionDescriptionColor

String | Example value "#d6d8dc"

Caption description text color.

categoryCaptionAlign

String | Example value "left"

Caption text alignment. Accepts "left", "center" or "right".

categoryCaptionPaddingX

Number | Example value 28

Full-size horizontal inset of the caption from the image edge, in CSS pixels.

categoryCaptionPaddingXSmall

Number | Example value 12

Horizontal caption inset at the small viewport threshold, in CSS pixels.

categoryCaptionPaddingY

Number | Example value 26

Full-size inset between the caption and the bottom image edge, in CSS pixels. This is not a browser-edge margin.

categoryCaptionPaddingYSmall

Number | Example value 14

Bottom caption inset at the small viewport threshold, in CSS pixels.

categoryCaptionGap

Number | Example value 6

Full-size visible gap between the title and description, in CSS pixels. Measured from the drawn text bounds so descenders do not add extra spacing.

categoryCaptionGapSmall

Number | Example value 2

Title-to-description gap at the small viewport threshold, in CSS pixels.

categoryCaptionMaxHeight

Number | Example value 0.5

Maximum fraction of image height available to the caption, from 0 to 1. Text may be shortened to fit this budget.

categoryCaptionGradientColor

String | Example value "#000000"

Color behind the lower caption area.

categoryCaptionGradientOpacity

Number | Example value 0.64

Maximum caption gradient opacity from 0 to 1.

categoryCaptionGradientHeight

Number | Example value 32

Extra gradient coverage above the full-size caption area, in CSS pixels.

categoryCaptionGradientHeightSmall

Number | Example value 24

Extra gradient coverage at the small viewport threshold, in CSS pixels.

categoryCaptionFadeInStart

Number | Example value 0.5

Opening progress at which captions start fading in, from 0 to 0.99. This is a progress fraction, not seconds.

categoryCaptionFadeOutDuration

Number | Example value 0.2

Caption fade-out duration in seconds.

showCateogryNavigationArrows

Boolean | Example value true

Show previous and next category arrows beside the close button. Keep this exact property spelling, including "Cateogry".

showCateogryNavigationSelect

Boolean | Example value true

Show the category dropdown trigger. Independent of the category arrows. Keep this exact property spelling, including "Cateogry".

categorySelectorTextColor

String | Example value "#707070"

Color of the category navigation label and total category count.

categorySelectorCurrentNumberColor

String | Example value "#000000"

Color of the bold current category number beside the category arrows.

categorySelectorPreviewWidth

Number | Example value 300

Preferred hover preview width in CSS pixels, clamped from 160 to 480. The preview can shrink to fit the gallery.

categorySelectorPreviewFontFamily

String | Example value "Roboto, sans-serif"

CSS font-family used in the category arrow hover preview.

categorySelectorPreviewLabelFontSize

Number | Example value 13

Font size of the previous/next category label and count in the hover preview, in CSS pixels from 8 to 24.

categorySelectorPreviewTitleFontSize

Number | Example value 18

Font size of the destination category title in the hover preview, in CSS pixels from 10 to 32.

categorySelectorPreviewLabelFontWeight

Number | Example value 400

Hover preview label weight from 100 to 900.

categorySelectorPreviewTitleFontWeight

Number | Example value 700

Hover preview title weight from 100 to 900.

categorySelectorPreviewTextGap

Number | Example value 8

Gap between the hover preview metadata and category title, in CSS pixels from 0 to 80.

categorySelectorPreviewPaddingTop

Number | Example value 16

Top padding of the text area below the preview frame, in CSS pixels from 0 to 80.

categorySelectorPreviewPaddingX

Number | Example value 18

Horizontal padding of the preview text area, in CSS pixels from 0 to 80.

categorySelectorPreviewPaddingBottom

Number | Example value 18

Bottom padding of the preview text area, in CSS pixels from 0 to 80.

categorySelectorPreviewLabelColor

String | Example value "#d9d9d9"

Color of the previous/next category label in the hover preview.

categorySelectorPreviewTitleColor

String | Example value "#ffffff"

Color of the destination category title in the hover preview.

categorySelectorPreviewCounterColor

String | Example value "#d9d9d9"

Color of the total category count and separator in the hover preview.

categorySelectorPreviewCurrentNumberColor

String | Example value "#ffffff"

Color of the bold destination category number in the hover preview.

categorySelectorLabels

Object | Example value See the label reference

Text and accessible labels for category arrows and hover previews. See the label table below for every key and placeholder.

Category dropdown settings

useCategoryPickerMouseWheel

Boolean | Example value true

Enable mouse-wheel and trackpad scrolling inside the vertical category dropdown. Does not change wheel input on the main ribbon or category images.

categoryPickerLabels

Object | Example value See the label reference

Text and accessible labels for the category dropdown. See the label table below for every key and placeholder.

categoryPickerWidth

Number | Example value 300

Preferred dropdown width in CSS pixels from 220 to 480. It shrinks to fit narrow galleries.

categoryPickerHeight

Number | Example value 560

Preferred dropdown height in CSS pixels from 260 to 900. Available gallery space can reduce the actual height.

categoryPickerFrameHeight

Number | Example value 210

Category thumbnail frame height in CSS pixels from 100 to 400. Frame proportions follow frameWidth and frameHeight.

categoryPickerBendStrength

Number | Example value 0.6

Bend strength of the vertical category ribbon, from 0 to 1. Use 0 for straight thumbnails.

categoryPickerBackgroundColor

String | Example value "#ffffff"

Background color of the category dropdown.

categoryPickerTextColor

String | Example value "#111111"

Main dropdown text color and fallback for several more specific colors.

categoryPickerFontFamily

String | Example value "Roboto, sans-serif"

CSS font-family used throughout the category dropdown.

categoryPickerHeaderColor

String | Example value "#ffffff"

Background color of the dropdown header area.

categoryPickerSecondaryTextColor

String | Example value "#707070"

Color of secondary dropdown text, including media count wording and selection status.

categoryPickerPhotoCountColor

String | Example value "#000000"

Color of the bold media count number in the dropdown.

categoryPickerCounterColor

String | Example value "#707070"

Color of the total category count and separator in the dropdown.

categoryPickerCurrentNumberColor

String | Example value "#000000"

Color of the bold selected category number in the dropdown.

categoryPickerTitleColor

String | Example value "#111111"

Color of the category title in the dropdown.

categoryPickerBorderColor

String | Example value "#dddddd"

Color used for the dropdown border.

categoryPickerShadowColor

String | Example value "rgba(0, 0, 0, 0.10)"

CSS color, including rgba(), used by the dropdown shadow.

categoryPickerFocusColor

String | Example value "#111111"

Keyboard focus indicator color in the dropdown.

categoryPickerSelectionColor

String | Example value "#111111"

Color of the marker beside the selected category. The marker stays on the selected category while other thumbnails are hovered.

categoryPickerScrollbarTrackColor

String | Example value "#dddddd"

Custom scrollbar track color.

categoryPickerScrollbarThumbColor

String | Example value "#111111"

Custom scrollbar handle color.

categoryPickerCloseButtonColor

String | Example value "#111111"

Dropdown close button disc and outline color.

categoryPickerCloseButtonIconColor

String | Example value "#ffffff"

Dropdown close button icon color.

Post-processing settings

antialias

Boolean | Example value true

Smooth geometry edges. The renderer uses multisampling where supported and an FXAA fallback otherwise.

waveFrequency

Number | Example value 0.1

Spatial frequency of the wave distortion. Higher values place more waves across the image. This does not control animation speed.

waveAmplitude

Number | Example value 0

Wave distortion strength. Use 0 to disable it. The Waves demo uses 0.06 with a frequency of 0.12.

useFlowmap

Boolean | Example value false

Enable pointer-driven flowmap distortion on the ribbon and opened category.

flowmapStrength

Number | Example value 3

Flowmap displacement strength from 0 to 5.

useNoise

Boolean | Example value false

Enable noise, blur and edge fading on the shared ribbon/category rendering.

noiseSize

Number | Example value 0.4

Controls noise coverage. Smaller values leave a larger clear center. Use 0.12 as a restrained starting point.

noiseFadeSize

Number | Example value 0.2

Width of the edge fade relative to the canvas width. Smaller values narrow the faded region.

noiseBlurStrength

Number | Example value 0.3

Blur strength in the noise region. The Noise demo uses 0.12.

noiseFadeColor

String | Example value "#000000"

Color of the outer fade. Use "#ffffff" on a white page.

grid

Boolean | Example value false

Enable pointer-driven grid displacement. This is an image distortion effect, not a tiled gallery layout.

gridAddRGBDistortion

Boolean | Example value false

Add color-channel separation to the grid effect. The current Grid demo keeps this false.

gridSize

Number | Example value 1600

Number of grid columns. Rows follow the canvas proportions. Use a positive integer. The parser caps the value at 400, so the current index value of 1600 is treated as 400. The Grid demo uses 24.

gridMouseRadiusFactor

Number | Example value 0.4

Radius of the affected grid area relative to the grid size. Larger values affect more cells. Values above 2 are capped at 2.

gridMouseStrengthFactor

Number | Example value 0.48

Pointer displacement strength. Values above 2 are capped at 2. The Grid demo uses 0.9.

gridMouseRelaxation

Number | Example value 0.9

Amount of displacement retained each update. Use a value from 0 to 1. Values nearer 1 take longer to settle.

Text labels and placeholders

Pass only the label keys you want to change. Missing keys keep their built-in text. An empty string is allowed. Labels are treated as text, not HTML. Keep any placeholders that your translated text needs.

categorySelectorLabels

KeyExample textMeaning
headingCategoriesCategory navigation heading.
counter{current} / {total}Category number. Supports {current} and {total}.
navigationCategory navigationAccessible name of the category navigation group.
previousPrevious category: {title}Previous category button label. Supports {title}.
nextNext category: {title}Next category button label. Supports {title}.
previewPreviousPrevious categoryPrevious category preview label.
previewNextNext categoryNext category preview label.

categoryPickerLabels

KeyExample textMeaning
headingCOLLECTIONSDropdown heading.
mediaCountOne{count} itemSingular mixed-media count. Supports {count}.
mediaCountMany{count} itemsPlural mixed-media count. Supports {count}.
photoCountOne{count} photoSingular photo-only count. Supports {count}.
photoCountMany{count} photosPlural photo-only count. Supports {count}.
currentCurrently viewingStatus for the currently selected category.
openOpen collectionStatus for a different category.
details{photos} ยท {status}Combined footer text. Supports {photos} and {status}.
counter{current} / {total}Category position. Supports {current} and {total}.
dialogChoose a collectionAccessible name of the dropdown dialog.
closeClose collection pickerAccessible name of its close button.
scrollScroll collectionsAccessible name of the custom scrollbar.
option{title}, {photos}Accessible thumbnail label. Supports {title} and {photos}.
chooseCategory{title}: choose collectionCategory title trigger label. Supports {title}.
openCategoryOpen {title}Thumbnail action label. Supports {title}.
returnToCategoryReturn to {title}Selected thumbnail action label. Supports {title}.
categorySelectorLabels: {
    heading: 'Collections',
    previous: 'Previous collection: {title}',
    next: 'Next collection: {title}'
},
categoryPickerLabels: {
    heading: 'CHOOSE A COLLECTION',
    counter: '{current} / {total}',
    close: 'Close collections'
}

Caption layout

Caption title and description are independent. Leave both attributes out for no caption, or provide only the title. Keep descriptions short enough to read while browsing. Long text wraps and can be shortened by the line and height limits.

Typography and spacing use the gallery viewport width rather than the image width. A square image and a wide image therefore use the same font size and title-to-description gap at the same gallery size. Small-screen values interpolate between the two caption viewport thresholds.

  • Use categoryCaptionGap and categoryCaptionGapSmall for the gap between title and description.
  • Use categoryCaptionPaddingY and categoryCaptionPaddingYSmall for the distance from the caption to the bottom of the image.
  • Use the line-height settings for spacing within wrapped text. They do not replace the title-to-description gap.
  • Load custom fonts before initialization. Captions are drawn into textures and do not inherit ordinary page paragraph styles.
categoryCaptionTitleFontFamily: 'Roboto, sans-serif',
categoryCaptionDescriptionFontFamily: 'Roboto, sans-serif',
categoryCaptionTitleFontSize: 23,
categoryCaptionTitleFontSizeSmall: 16,
categoryCaptionDescriptionFontSize: 15,
categoryCaptionDescriptionFontSizeSmall: 14,
categoryCaptionGap: 6,
categoryCaptionGapSmall: 2,
categoryCaptionPaddingY: 26,
categoryCaptionPaddingYSmall: 14

Set deepLinking: true to open categories and media from the URL and update the hash as the selection settles. It is false by default. Browser Back and Forward restore routes.

#category=Salt_Sea&item=An_Open_Blue

Category routes are based on their titles. Item routes use data-deep-link-id first, then the caption title, then a fallback item name. Spaces and most punctuation become underscores. Duplicate names receive suffixes such as ~2. Non-ASCII characters may still be URL-encoded by the browser.

Use stable, unique item IDs for links you plan to share. A category ID is also accepted when reading an incoming category route. An unknown category is ignored, while a missing or unknown item opens the first item of a known category.

The route waits for loading and compatible transitions. Pointer, wheel or keyboard input can interrupt a pending route. Outgoing changes are published after movement settles. Closing returns to the ribbon route. Query parameters and unrelated hash values are preserved where applicable.

Enable deep linking on only one instance per page because all instances share the same location hash. If your site already uses a hash router, coordinate ownership of the category and item parameters.

JavaScript API

Keep the object returned by new FWDFPAVS(settings). Register loading callbacks in the events constructor setting and wait for ready before calling navigation methods. Most navigation calls return immediately with a boolean, they do not return an animation promise.

A true result means the request was accepted, not that an animation or media download has finished. A false result means the request is unavailable, invalid or blocked by the current transition. Listen for the matching event when completion matters.

getState()

Returns Object

Return a snapshot of readiness, playback, view, transition, selection, selector visibility and canvas dimensions. It does not expose live Three.js objects.

getCategories()

Returns Array

Return category metadata and authored media lists. Available after dataReady. Before data exists the result is an empty array.

openCategory(id)

Returns Boolean

Open or switch to a category using a zero-based ribbon index, an exact data-gallery-id, or an exact gallery title. Wait for ready before the first call. Returns false for an unknown category, the already-open category, or an incompatible transition.

openGallery(id)

Returns Boolean

Compatibility alias for openCategory(id). Use openCategory in new integrations.

closeCategory()

Returns Boolean

Request the reverse transition back to the ribbon. Returns false if there is no category or it is already closing. Use categoryClosed to know when the transition has finished.

nextCategory()

Returns Boolean

Switch to the next authored category. Requires an open category and wraps after the last category.

previousCategory()

Returns Boolean

Switch to the previous authored category. Requires an open category and wraps before the first category.

nextItem()

Returns Boolean

Request the next media item in a ready category. Uses the category easing and wrap rules. At a finite endpoint the request may be accepted without moving beyond the endpoint.

previousItem()

Returns Boolean

Request the previous media item in a ready category. Uses the same easing and finite endpoint behavior as nextItem().

goToCategoryItem(id)

Returns Boolean

Center an item by its authored zero-based index, explicit data-deep-link-id, generated deep-link key, or exact caption title. Requires a ready category. Duplicate titles resolve to the first match, so use a unique ID or index.

goToItem(index)

Returns Boolean

Center a ribbon frame by zero-based index. This method is for the minimized ribbon and returns false while a category is open or the intro prevents navigation.

pause()

Returns Boolean

Pause gallery rendering and visible video playback. This is not an autoplay-slideshow control. Manual pause remains active across scrolling and tab visibility changes.

play()

Returns Boolean

Clear a manual pause and resume rendering and visible video playback when the document is visible.

resize()

Returns No return value

Measure the host and refresh the canvas layout. Useful after changing a surrounding container without a window resize. Call after the host has its new dimensions.

destroy()

Returns No return value

Stop loading and animation work, pause videos, remove owned DOM and listeners, dispose GPU resources, and unregister the instance. Safe during loading, opening, switching or closing. Calling it again is safe. The host and source markup remain available for a new instance.

on(type, callback)

Returns Gallery instance

Subscribe to an event. Register the same type and callback once. Use the events constructor setting to capture events from the start of loading.

off(type, callback)

Returns Gallery instance

Remove a listener using the same callback reference. Also removes a once listener by its original callback.

once(type, callback)

Returns Gallery instance

Subscribe to one occurrence. The listener is removed before its callback runs.

addEventListener(type, callback)

Returns Gallery instance

Equivalent to on(type, callback).

removeEventListener(type, callback)

Returns Gallery instance

Equivalent to off(type, callback).

function openThirdCoastImage() {
    const onOpened = event => {
        if (event.category.id !== 'coast') return
        gallery.off('categoryOpened', onOpened)
        gallery.goToCategoryItem(2)
    }
    gallery.on('categoryOpened', onOpened)
    if (!gallery.openCategory('coast')) {
        gallery.off('categoryOpened', onOpened)
    }
}

State and metadata

getState() and getCategories() return plain snapshots. Read them again when you need current values. Category and item indices start at zero. Authored indices stay stable when a remembered cover changes display order.

getState() fieldMeaning
readyWhether the initial gallery readiness requirements have finished.
destroyedWhether destroy() has run.
playingWhether the render loop is running.
view"ribbon" or "category".
transition"intro", "opening", "closing" or null.
ribbonIndexCurrent zero-based ribbon selection, or null before selection is known.
categoryCurrent category metadata, or null.
itemNearest category item metadata, or null.
selectorOpenWhether the category dropdown is open.
width, heightCanvas dimensions in CSS pixels.

A category snapshot contains index, id, title and itemCount. getCategories() adds an items array for each category.

An item snapshot contains index, displayIndex, id, title, description, src, poster, mediaType, width, height and loaded. mediaType is "image" or "video". displayIndex is null when no current display position was supplied. loaded describes image or poster availability, not video buffering or permanent GPU residency.

Events

Every callback receives type and target, plus the fields below. target is the gallery instance. Use an event string such as "categoryOpened" or its constant FWDFPAVS.EVENTS.CATEGORY_OPENED.

const gallery = new FWDFPAVS({
    ...settings,
    events: {
        ready(event) {
            console.log(event.target.getState())
        },
        categoryOpened(event) {
            console.log(event.category.title, event.item.title)
        },
        categoryClosing(event) {
            if (event.reason === 'close') showPageMenu()
        },
        error(event) {
            console.error(event.message)
        }
    }
})

function onItemChange(event) {
    console.log(event.item.id)
}
gallery.on('categoryItemChange', onItemChange)
gallery.off('categoryItemChange', onItemChange)

dataReady

FWDFPAVS.EVENTS.DATA_READY

Ribbon cover data is available. getCategories() can now be read. This does not mean the model and intro are finished.

Additional fields: categories.

loadProgress

FWDFPAVS.EVENTS.LOAD_PROGRESS

A ribbon cover photo or poster finishes loading. progress is a fraction from 0 to 1. This is not a count of all category assets.

Additional fields: loaded, total, progress, index, src.

ready

FWDFPAVS.EVENTS.READY

The ribbon has completed its loading and intro requirements and can accept API navigation. Fires once per instance.

Additional fields: categories.

error

FWDFPAVS.EVENTS.ERROR

A gallery data, cover or model error is reported. Category image failures and video failures have separate events.

Additional fields: message, text.

introStart

FWDFPAVS.EVENTS.INTRO_START

The ribbon intro starts.

Additional fields: No additional fields.

introComplete

FWDFPAVS.EVENTS.INTRO_COMPLETE

The ribbon intro finishes. Intro events may be absent when no intro runs.

Additional fields: No additional fields.

itemUpdate

FWDFPAVS.EVENTS.ITEM_UPDATE

The centered ribbon frame changes. id is its zero-based ribbon index.

Additional fields: id, category.

categoryChange

FWDFPAVS.EVENTS.CATEGORY_CHANGE

The active category changes, including return to the ribbon. category and item are null on return.

Additional fields: category, item, previousCategory.

categoryOpening

FWDFPAVS.EVENTS.CATEGORY_OPENING

A category starts appearing. reason is "open" or "switch".

Additional fields: category, item, reason.

categoryOpened

FWDFPAVS.EVENTS.CATEGORY_OPENED

The category opening or switching entrance finishes.

Additional fields: category, item.

categoryClosing

FWDFPAVS.EVENTS.CATEGORY_CLOSING

A category starts leaving. reason is "close" or "switch".

Additional fields: category, item, reason.

categoryClosed

FWDFPAVS.EVENTS.CATEGORY_CLOSED

The outgoing category is disposed after its exit. reason is "close" or "switch". Destroying the whole gallery emits destroy instead.

Additional fields: category, item, reason.

categoryItemChange

FWDFPAVS.EVENTS.CATEGORY_ITEM_CHANGE

The nearest category item changes, including items passing the center while dragging. It does not wait for movement to settle.

Additional fields: category, item, previousItem.

mediaLoad

FWDFPAVS.EVENTS.MEDIA_LOAD

A category image or poster becomes available. kind is "image" or "poster". Cached media can emit this when a category is entered again.

Additional fields: category, item, kind.

mediaError

FWDFPAVS.EVENTS.MEDIA_ERROR

A category image or poster fails to load.

Additional fields: category, item, kind.

videoPlay

FWDFPAVS.EVENTS.VIDEO_PLAY

A pooled visible video starts playing. src is the absolute video URL. Shared video sources emit one playback event per source, not one per mesh.

Additional fields: src.

videoPause

FWDFPAVS.EVENTS.VIDEO_PAUSE

A pooled video pauses.

Additional fields: src.

videoError

FWDFPAVS.EVENTS.VIDEO_ERROR

A video source reports a browser media error. Its poster remains the fallback.

Additional fields: src, code, message.

dragStart

FWDFPAVS.EVENTS.DRAG_START

Dragging begins. scope is "ribbon", "category" or "categorySelector".

Additional fields: scope, category, item.

dragEnd

FWDFPAVS.EVENTS.DRAG_END

Dragging ends. Inertia may continue after this event.

Additional fields: scope, category, item.

categorySelectorOpen

FWDFPAVS.EVENTS.CATEGORY_SELECTOR_OPEN

The category dropdown opens.

Additional fields: category, item.

categorySelectorClose

FWDFPAVS.EVENTS.CATEGORY_SELECTOR_CLOSE

The category dropdown closes.

Additional fields: category, item.

deepLinkChange

FWDFPAVS.EVENTS.DEEP_LINK_CHANGE

A route is read or published. direction is "incoming" or "outgoing". Incoming routes can be announced before their visual transition.

Additional fields: url, hash, direction.

resize

FWDFPAVS.EVENTS.RESIZE

The canvas dimensions change. Values are in CSS pixels.

Additional fields: width, height.

play

FWDFPAVS.EVENTS.PLAY

Rendering starts or resumes, including automatic visibility changes.

Additional fields: No additional fields.

pause

FWDFPAVS.EVENTS.PAUSE

Rendering stops, including automatic visibility changes.

Additional fields: No additional fields.

destroy

FWDFPAVS.EVENTS.DESTROY

Cleanup has finished. Dispatched once, synchronously after cleanup. No later events come from that instance.

Additional fields: No additional fields.

Callbacks normally run after the current internal update. Navigation or destroy() can be called from a callback. The destroy event is the exception and runs synchronously after cleanup.

Category switching overlaps an outgoing fade with an incoming reveal. Do not assume categoryClosed always occurs before categoryOpening. Check the category and reason fields. Pausing the render loop also pauses events that depend on animation progress.

Cleanup and multiple galleries

Call destroy() before removing or replacing a gallery in a component, tab or client-side route. You can call it while assets are loading or an animation is running. You do not need to wait for ready.

gallery.destroy()

// The same host and instance name can now be reused.
const replacement = new FWDFPAVS({
    ...settings,
    instance: 'exampleGallery',
    parentId: 'gallery-holder',
    carouselDataId: 'gallery-data'
})

Destroy restores the host inline position, width and height and removes the gallery-owned canvas and controls. It leaves your host and hidden HTML data in place. Remove your own application listeners and DOM separately if your component created them.

For multiple galleries, provide unique instance names and host IDs. Each instance has its own API and events. Keep deep linking enabled on at most one of them. Avoid initializing many visible video galleries at once.

Media performance

  • Resize photos close to their displayed size. The included demo uses many images around 1280 pixels on the long side. Larger screens may justify larger files, but excessive dimensions increase texture memory.
  • Use actual dimensions in the markup. Incorrect values change the mesh proportions and can cause visible layout shifts.
  • Prepare video posters with the same aspect ratio as their videos. Give each different video a distinct poster URL so cover matching stays unambiguous.
  • Compress video for the intended display size. Full-length videos are supported, but low bitrate and suitable resolution still matter.
  • Keep the effect count small on mobile. Grid cost grows with both its rows and columns. A 24-column grid is much lighter than a 400-column grid.
  • Use stats and gui only while developing. Reduce sharpening if fine image detail looks harsh.
  • Keep the supplied model and complete asset paths together when publishing beneath a subdirectory.
  • Allow cross-origin media requests when serving textures from another host. Video delivery should support byte-range requests for buffering and seeking.

The slider already limits work for offscreen meshes, loads category images asynchronously, shares visible video resources and releases inactive playback resources. These measures do not remove the cost of very large source files.

Troubleshooting

ProblemWhat to check
Blank galleryCheck that parentId and carouselDataId exist before initialization. In afterparent mode the host must have a nonzero height. Inspect the browser console for a data or WebGL error.
Model or decoder 404Publish the complete output and verify the filmFrameModel URL. The current standalone demo bundle embeds its decoder. An old bundle requesting a missing /assets/draco_decoder file should be rebuilt.
Vite dependency 504 during developmentStop the development server, clear its node_modules/.vite cache, restart it and reload the page. This is a development dependency-cache issue, not a production media URL.
Images fail onlineCheck the exact filename and letter case, HTTP status, base path and cross-origin permission. Local Windows paths such as D:\work are not public media URLs.
Video stays on its posterCheck the video request, browser codec support and autoplay policy. Listen for videoError. A blocked autoplay attempt can be retried after user input.
A category opens with unexpected proportionsVerify width and height on each category media element. Ribbon frameWidth and frameHeight do not replace category dimensions.
Captions look wrong after a font changeLoad the font first, then recreate the gallery. Confirm that the requested font weight and style are available.
Mouse wheel moves the pageEnable the flag for the specific area you want to control. Ribbon, category images and dropdown have separate wheel settings.
A short gallery does not loopWrapping is disabled when there are not enough frames to cover the view safely. Add more items or keep finite navigation.
An API request returns falseCheck getState(), the item/category identity and the current transition. Wait for ready or categoryOpened where appropriate.
A setting change has no effectCheck the exact name, native boolean type and documented units. Recreate the instance after changing constructor settings.
A shared link opens the wrong item after editing captionsUse unique data-deep-link-id values and keep them stable. Titles are used as route fallbacks.

For support, include the page URL, browser, console error, relevant settings and a small markup example. Contact tibi@fwdapps.net.

Working with the source project

The source project uses ES modules, Three.js and Vite. Install dependencies from the project folder, then start the local server or create a build.

npm install
npm run dev
npm run build
npm run build:demo
npm run build:docs

npm run build refreshes the standalone constructor and creates build/start.html with its complete asset folders, alongside the built development demo. npm run build:demo updates the standalone demo script, media and preset pages. Use the complete output for the workflow you choose. The standalone library used in this guide is demo/js/filmstrip-gallery.js.

Edit the authored media and main example settings in index.html. Demo-specific overrides live in tools/build-demo-pages.mjs. This JavaScript guide is generated by tools/build-javascript-docs.mjs, which checks that every current index setting and public event has a description.

Legacy carousel effects removed from the exposed settings are not part of the current guide. Use the current frame, category and effect options above rather than older examples with string booleans, planeWidth/planeHeight or categorySelectorType.