I used the Lottie animation example from the Three.js documentation within a React project. It works fine with the WEBXR extension on Mozilla Firefox. However, when using Meta Quest 2 to access the project through an HTTPS link provided by ngrok, the Lottie animation does not work correctly; it gets stuck and fails to play properly.
import React, { useEffect, useRef } from ‘react’;
import * as THREE from ‘three’;
import { RoomEnvironment } from ‘three/examples/jsm/environments/RoomEnvironment’;
import { RoundedBoxGeometry } from ‘three/examples/jsm/geometries/RoundedBoxGeometry’;
import { LottieLoader } from ‘three/examples/jsm/loaders/LottieLoader’;
import { OrbitControls } from ‘three/examples/jsm/controls/OrbitControls’;
import { VRButton } from ‘three/examples/jsm/webxr/VRButton.js’;
const JsonAnimation = () => {
const sceneRef = useRef(null);
useEffect(() => {
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(50, window.innerWidth / window.innerHeight, 0.1, 10);
camera.position.z = 2.5;
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.xr.enabled = true;
const container = sceneRef.current; // Captura a referência em uma variável
container.appendChild(renderer.domElement);
scene.background = new THREE.Color(0x111111);
document.body.appendChild(VRButton.createButton(renderer));
const loader = new LottieLoader();
loader.setQuality(2);
loader.load('utils/24017-lottie-logo-animation.json', (texture) => {
setupControls(texture.animation);
const geometry = new RoundedBoxGeometry(1, 1, 1, 7, 0.2);
const material = new THREE.MeshStandardMaterial({ roughness: 0.1, map: texture });
const mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
const animate = () => {
if (mesh) {
mesh.rotation.y -= 0.001;
}
renderer.render(scene, camera);
renderer.setAnimationLoop(animate);
};
animate();
});
const environment = new RoomEnvironment(renderer);
const pmremGenerator = new THREE.PMREMGenerator(renderer);
scene.environment = pmremGenerator.fromScene(environment).texture;
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.25;
controls.enableZoom = true;
const onWindowResize = () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
};
window.addEventListener('resize', onWindowResize);
return () => {
window.removeEventListener('resize', onWindowResize);
if (container) {
container.removeChild(renderer.domElement); // Usa a variável container
}
};
}, );
const setupControls = (animation) => {
const scrubber = document.getElementById(‘scrubber’);
scrubber.max = animation.totalFrames;
scrubber.addEventListener('pointerdown', () => {
animation.pause();
});
scrubber.addEventListener('pointerup', () => {
animation.play();
});
scrubber.addEventListener('input', () => {
animation.goToAndStop(parseFloat(scrubber.value), true);
});
animation.addEventListener('enterFrame', () => {
scrubber.value = animation.currentFrame;
});
};
return (
<div ref={sceneRef} style={{ width: ‘100vw’, height: ‘100vh’ }}>
<input id=“scrubber” type=“range” defaultValue=“0” style={{ width: ‘300px’ }} />
);
};
export default JsonAnimation;