Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Non-DOM components with WebGL in Vue.js

yomotsu
November 10, 2018

Non-DOM components with WebGL in Vue.js

Both in English and Japanese.
The example code can be seen below:
https://github.com/yomotsu/vue-webgl-non-dom-component-example

yomotsu

November 10, 2018
Tweet

More Decks by yomotsu

Other Decks in Programming

Transcript

  1. • High optimized rendering performances • Advanced effects with GLSL

    Filters beyond CSS • Yet Vue can handle UI, data and APIs Why with WebGL?
  2. • WebGL is async. 
 WebGL Rendering is not synced

    with DOM Rendering. • Made a pure class,
 independent of Vue. Separate WebGL and Vue…
  3. • Same data in 2 places.
 (Vuex and the pure

    class) • Infinite loop in two-way binding.
 (Due to number precision in JS) • Unreadable code… Separate WebGL and Vue…
  4. mounted() { this.glRender = this.glRender.bind( this ); this.renderer = new

    THREE.WebGLRenderer( { canvas: this.$el, stencil: false, alpha: true, } ); ……
  5. • <canvas> for <template> • Init the WebGL Renderer at

    mounted • Destroy the Renderer at destroyed WebGL Canvas component
  6. export default { name: ‘DisplayObject3D’, …… render() { // template

    がないので、 // 空の render を明示して // `Failed to mount component: template or render function not defined.` // のエラーを防ぐ } }
  7. created() { var loader = new THREE.GLTFLoader(); loader.load( './vue.glb', (

    gltf ) => { this.mesh = gltf.scene; this.mesh.userData.vuexId = this.id; this.mesh.traverse( ( obj ) => obj.userData.vuexId = this.id ); this.scene.add( this.mesh ); this.scene.add( this.transformControl ); this.transformControl.attach( this.mesh ); this.$emit( 'changed' ); } ...
  8. • WebGL objects are not DOM. • <template> is not

    needed. • But Vue props. Display Object components
  9. • omit <template> • Void render • Init the component

    at created. • Dispose at destroyed. Display object components
  10. • WebGL root component listen events. • Then, WebGL render.

    • Doesn't rely on Virtual-DOM. Render them
  11. <template> <canvas …(snip) > <template v-if="renderReady"> <template v-for=“object in objects">

    {{ /* 必ず一意のkeyを入れる */ }} <Object3D @changed="glRender" …(snip) />
  12. methods: { glRender() { if ( this.willRender ) return; this.willRender

    = true; requestAnimationFrame( () => { if ( ! this.renderer ) return; this.renderer.render( this.scene, this.camera ); delete this.willRender; } ); }, …(snip)
  13. • Avoid multiple update at the sometime. • Combine multiple

    props into one object. • “Watch” will be also merged into one. Use computed for combined-props
  14. • DOM is easier to build UI • Since WebGL

    doesn’t make DOM,
 You cannot use DOM inspector. • (May makes more difficult to inspect.) Consider using DOM
  15. • Mount can be done without <template> • Init and

    $mount the component manually.
 (But it usually for testing.) Manual Mounting
  16. • Mount can be done without <template> • Init and

    $mount the component manually.
 (But it usually for testing.) खಈϚ΢ϯτ
  17. // CanvasComponent(親)内で、手動でマウントする const displayObject3D = new DisplayObject3d( { propsData: {

    id: object.id, positionX: object.positionX, positionY: object.positionY, …(snip) } } ); displayObject3D.$on( 'changed', () => { this.glRender(); } );
  18. • <template> less component
 could be a solution
 for None-DOM

    instances • Then, your data flow would be clearer