Skip to content

<oim-player> Web Component Guide ​

The <oim-player> is a lightweight, framework-agnostic Custom Element that decodes and renders .oim interactive images directly in any web browser. Encapsulated inside an open Shadow DOM, it guarantees zero CSS conflicts with the host application.


1. Quick Installation & CDN Setup ​

You can load <oim-player> either from modern package registries or directly via CDN script tag:

html
<!-- Import standalone bundle via CDN -->
<script type="module" src="https://cdn.oim.media/player/v1/oim-player.js"></script>

<!-- Or install via npm/pnpm -->
<!-- pnpm add @oim-media/player-oim -->

Usage in standard HTML markup:

html
<oim-player
  src="https://cdn.oim.media/demo/imagen-muestra.oim.png"
  lang="en"
  fit="contain"
  allow-dynamic-colors="true">
</oim-player>

2. Observed DOM Attributes ​

<oim-player> observes attributes and updates the render tree dynamically upon changes:

AttributeTypeDefaultDescription
srcstring (URL or Blob)""Source path of the .oim.png or .oim file
langstring"en"Currently active language code ("en", "es", etc.)
fit"contain" | "cover""contain"Aspect-ratio fitting mode inside parent container
align"center" | "top" | "bottom""center"Vertical alignment positioning
placeholderstring""Image URL to display while binary metadata loads
allow-dynamic-colors"true" | "false""true"Enables semantic CSS custom property themes
palettestring(none)Named palette from the .oim palettes to apply; without it the player follows prefers-color-scheme when the file has dark and light, else defaultPalette
allow-zoom"true" | "false""false"Enables smooth interactive pan-and-zoom controls
disable-animations"true" | "false""false"Halts all loops (respects prefers-reduced-motion)
auto-rotate-langnumber | "false""false"Interval in ms to automatically cycle languages

3. Public JavaScript API & Methods ​

The custom element instance exposes imperative methods on the DOM node:

typescript
const player = document.querySelector('oim-player');

// Get the verified metadata object extracted from the PNG
const metadata = await player.getMetadata();
console.log('Document ID:', metadata.oim_id);

// Switch language programmatically in real-time
player.setLang('es');

// Inspect cryptographic signature verification status
const security = player.getSecurityStatus(); // "verified" | "unsigned" | "invalid"

// Control interactive zoom (1.0x to 4.0x)
player.setZoom(1.5);

// Teardown and clean observers
player.destroy();

4. Custom Events & Event Handling ​

The player dispatches native Custom Events that bubble up to the host application:

Event NameDetail PayloadDescription
oim:loaded{ type: string, metadata: object }Fired when metadata is extracted and validated
oim:langchange{ lang: string }Fired when the active language changes
oim:action{ slot, name, trigger, targets }Fired when a user interacts with a slot
oim:incomplete{ missing_capabilities: string[] }Fired if asset requires unsupported features
error{ message: string, code: string }Fired upon network or decompression failure

Intercepting Actions with preventDefault() ​

When a user clicks on an interactive slot with an action, the host app can intercept and control the navigation:

javascript
player.addEventListener('oim:action', (event) => {
  const { slot, name } = event.detail;
  if (name === 'buy_button') {
    event.preventDefault(); // Stop default navigation
    openCustomCheckoutModal(slot.id);
  }
});

5. Security & Shadow DOM Isolation ​

The internal structure is isolated from global CSS:

  • Shadow DOM: Uses mode: 'open' with internal <style> injection.
  • Dynamic Colors Sanitization: Color values are strictly sanitized through isSafeCssColor before application to CSS variables (var(--oim-color-*)).
  • Signature Verification: Verifies ECDSA P-256 signatures against public keys embedded in the player at build time, so rendering a file contacts no server and tells no one who is looking. Only a file signed with a key this build does not know makes the player ask for it, at https://api.oim.media/v1/media/keys by default; a self-hosted fork can point elsewhere with window.OIM_PLAYER_CONFIG = { keysUrl: "..." } before loading the player.

6. Loading, Zoom and Styling from the Host Page ​

The player ships clean: it does only what the format needs and carries no decoration of its own. How it looks around the artwork belongs to the page that embeds it, through CSS custom properties. They inherit into the Shadow DOM, so set them on <oim-player> or any ancestor.

First load: one reveal, no piecemeal build ​

The artwork stays behind a veil (blurred and transparent) while it is built. Every layer is placed at its final size and opacity underneath, and the veil lifts once fonts, embedded layer images and Lottie animations are ready, then two frames later so layout and scale are applied. Visitors never see shapes appearing one by one or text growing into place. The wait is capped at 1.2 s, so a broken asset can never leave the artwork hidden.

A later re-render (for example a language switch) never drops the veil back: a language change uses its own short blur, or a plain fade when the visitor asked for reduced motion.

CSS custom properties ​

PropertyDefaultEffect
--oim-reveal-blur14pxBlur of the veil on first load. 0px for a plain fade.
--oim-reveal-duration0.32sHow long the veil takes to lift.
--oim-color-<role>the author's colourRecolours a semantic role (primary, on-primary, secondary, on-secondary, surface, on-surface, outline, accent). See Dynamic Colors.
css
oim-player {
  --oim-reveal-blur: 6px;
  --oim-reveal-duration: 0.2s;
  --oim-color-primary: #2563eb;
}

A role you leave unset falls back to the colour the author saved in each layer. Use allow-dynamic-colors="false" to exempt one artwork from your palette.

The palette attribute picks one of the named palettes the artwork ships (for example palette="light"). Changing it updates the player without a reload. Your own --oim-color-* variables still win over the palette.

Zoom ​

With allow-zoom="true", the wheel and trackpad zoom proportionally to how far they move (one mouse-wheel notch is about 5%), between 1x and 4x. A pinch (ctrl + wheel) responds faster than scrolling. Small back-and-forth deltas at the end of a trackpad gesture barely move the zoom, so the artwork does not shake.