aframe 不渲染 lottie json 纹理映射到 canvas 但在 three.js 中工作

aframe not rendering lottie json texture mapped to canvas but works in three.js

所以我基本上是在尝试通过 aframe 将 json 渲染到 canvas 上,你确实成功地将它映射到 three.js 中的 canvas 上,但是当我尝试在框架中复制它时,它只显示一个白色框架,它表明它在那里,但没有显示动画。

无法在框架中呈现 (https://glitch.com/edit/#!/sun-innate-cupboard)

能够在 three.js (https://jsfiddle.net/crays/15cgbvsp)

中呈现
function init() {

    camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );
    camera.position.z = 5;

    scene = new THREE.Scene();
        scene.background = new THREE.Color( 0xffffff );
        
        const canvas = document.createElement( 'canvas' );
        canvas.width = 1024;
        canvas.height = 1024;
        const context = canvas.getContext( '2d' );
        
        const animation = bodymovin.loadAnimation( {
            container: document.getElementById( 'bm' ),
            renderer: 'canvas',
            rendererSettings: {
                context: context
            },
            loop: true,
            autplay: true,
            path: 'https://assets5.lottiefiles.com/packages/lf20_mb9ka7yz.json'
      //animationData: json
        } );

        const texture = new THREE.CanvasTexture( canvas );

    const geometry = new THREE.PlaneGeometry();
    const material = new THREE.MeshBasicMaterial( { map: texture } );

    mesh = new THREE.Mesh( geometry, material );
    scene.add( mesh );

    renderer = new THREE.WebGLRenderer( { antialias: true } );
    renderer.setSize( window.innerWidth, window.innerHeight );
    document.body.appendChild( renderer.domElement );

}

function animate() {

    requestAnimationFrame( animate );
        
        mesh.material.map.needsUpdate = true;
    

    renderer.render( scene, camera );

}

会不会是我遗漏了什么?

两件事,不仅关于 lottie 动画,而且关于一般纹理:

1. canvas 包含透明元素

您需要告诉 material 您希望它是透明的,否则您会看到这样的伪像:

这样做相当straight-forward:

<!-- in threejs: material.transparent = true -->
<!-- in a-frame: -->
<a-entity material="transparent: true">

2。 canvas 动画

您需要告诉纹理在每个渲染循环中更新。否则只有动画的第一帧是可见的(或一个空的 cavas)。 您可以使用 custom component 轻松完成,简而言之:

// grab the mesh upon initialization
const mesh = element.getObject3D("mesh");
// cache it for later use
texture = mesh.material.map;

// on each renderloop
texture.needsUpdate = true;

3。将理论付诸实践

// load the lottie animation
const canvas = document.getElementById('animation')
const context = canvas.getContext("2d");

const animation = bodymovin.loadAnimation({
  renderer: "canvas",
  rendererSettings: {
    context: context
  },
  loop: true,
  autplay: true,
  path: "https://assets5.lottiefiles.com/packages/lf20_mb9ka7yz.json"
});
<script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bodymovin/5.7.3/lottie.min.js"></script>
<script>
  AFRAME.registerComponent("update-texture", {
    init: function() {
      this.el.addEventListener("loaded", e => {
        const mesh = this.el.getObject3D("mesh");
        this.texture = mesh.material.map
      })
    },
    tick: function() {
      if (this.texture) {
        this.texture.needsUpdate = true;
      }
    }
  })
</script>

<canvas id="animation" width="1024" height="1024"></canvas>
<a-scene background="color: #ECECEC">
  <a-plane position="0 1.5 -1" material="shading: flat; transparent: true; src: #animation" update-texture></a-plane>
</a-scene>