Skip to main content

Using JavaScript

For more advanced functionality, you can use JavaScript.

Before you begin

Since custom elements are initialized asynchronously by the browser, you’ll need to wait for them to be defined before accessing their properties and methods. You don’t need to wait for all custom elements to be defined—just the ones you’re using.

If you don’t wait for the custom elements to be defined, you risk accessing properties that are not defined yet.

await customElements.whenDefined("miris-scene");  // only if controlling <miris-scene>
await customElements.whenDefined("miris-stream"); // only if controlling <miris-stream>
await customElements.whenDefined("miris-camera"); // only if controlling <miris-camera>
await customElements.whenDefined("miris-group"); // only if controlling <miris-group>

// The rest of your code goes here

Transformations

You can position, rotate, and scale <miris-stream>, <miris-camera>, and <miris-group> elements.

// Wait for the custom element to be defined
await customElements.whenDefined("miris-stream");

const stream = document.querySelector("miris-stream");

stream.position.z = -10; // Position at -10 along the Z-axis
stream.rotation.y = 3.142; // Rotate by 180º along the Y-axis
stream.scale.set(2, 2, 2); // Scale by 2 along all axes
info

rotation and scale have no effect on <miris-camera>.

Interaction

The example below hooks up an <input type="range"> to control the rotation of an asset.

<miris-scene viewer-key="VIEWER_KEY">
<miris-stream uuid="ASSET_ID" position="0 0 -5"></miris-stream>
</miris-scene>
<!-- –180º to +180º, in radians -->
<input type="range" min="-3.142" max="3.142" step="0.001" />
// Wait for the custom element to be defined
await customElements.whenDefined("miris-stream");

const input = document.querySelector("input");
const stream = document.querySelector("miris-stream");

input.addEventListener("input", () => {
// Rotate the stream based on the input’s value
stream.rotation.y = input.value;
});

Animation

To render animations, you’ll want to use requestAnimationFrame(). The example below oscillates a stream along the X-axis.

// Wait for the custom element to be defined
await customElements.whenDefined("miris-stream");

const stream = document.querySelector("miris-stream");
const animate = (timestamp) => {
// Oscillate the stream along the X-axis
stream.position.x = Math.sin((Math.PI * timestamp) / 1000);

// Animate on every frame
requestAnimationFrame(animate);
};

// Run the animation
animate();

Fetching assets

You can fetch a list of all assets available to your viewer key with <miris-scene>.fetchAssets().

// Wait for the custom element to be defined
await customElements.whenDefined("miris-scene");
await customElements.whenDefined("miris-stream");

const scene = document.querySelector("miris-scene");

// Fetch the first asset
const [asset] = await scene.fetchAssets();

if (asset) {
// Create a stream
const stream = document.createElement("miris-stream");

// Set the stream’s asset ID and position
stream.uuid = asset.uuid;
stream.position.z = -5;

// Add the stream to the scene
scene.append(stream);
}

fetchAssets() also supports filtering by tag:

// Filter assets by tags (comma-separated)
await scene.fetchAssets("tag-one,tag-two");

// Or filter by using an array of tags
await scene.fetchAssets(["tag-one", "tag-two"]);

Lazy loading

You can lazily load streams by first setting the disabled attribute on the stream element and then setting the steam’s disabled property to true when you’re ready to load the stream. The example below implements lazy loading for an entire scene using IntersectionObserver:

<miris-scene viewer-key="VIEWER_KEY">
<miris-stream uuid="ASSET_ID" position="0 0 -5" disabled></miris-stream>
</miris-scene>
// Wait for the custom elements to be defined
await customElements.whenDefined("miris-scene");
await customElements.whenDefined("miris-stream");

const scene = document.querySelector("miris-scene");

// Create a new IntersectionObserver
const observer = new IntersectionObserver((entries) => {
for (const entry of entries) {
// Return if the scene is not visible
if (entry.isIntersecting) {
return;
}

// Get all the streams in the scene
const streams = scene.querySelectorAll("miris-stream");

// Enable all the scene’s streams
for (const stream of streams) {
stream.disabled = false;
}

// Unobserve the scene
observer.unobserve(scene);
}
});

// Observe the scene
observer.observe(scene);

Adding controls

In addition to the controls attribute, you can set the controls property directly on a stream or camera:

// Wait for the custom element to be defined
await customElements.whenDefined("miris-stream");

const stream = document.querySelector("miris-stream");

stream.controls = true;
// Wait for the custom element to be defined
await customElements.whenDefined("miris-camera");

const camera = document.querySelector("miris-camera");

camera.controls = true;

Listening for events

<miris-scene> and <miris-scene> each dispatch an event when they have loaded. To listen for these events, just use addEventListener() like you would with any other element:

// Wait for the custom elements to be defined
await customElements.whenDefined("miris-scene");
await customElements.whenDefined("miris-stream");

const scene = document.querySelector("miris-scene");
const stream = document.querySelector("miris-stream");

scene.addEventListener("sceneloaded", () => {
// Do something
});

stream.addEventListener("streamloaded", () => {
// Do something
});