Using web components (vanilia JS) to display THREE.js

Hello,

This weekend I’ve been trying to use webcomponents (templates, shadow DOM and custom elements) to encapsulate THREE scene. I have done the following:

I’m having trouble displaying the code properly, so here’s a Fiddle to show it: https://jsfiddle.net/6zje01gr/1/

I am trying to reproduce the first example of this page: https://threejsfundamentals.org/threejs/lessons/threejs-responsive.html (with only one green cube)

If someone could help me understand what I am doing wrong, I’ll be grateful.

Cheers,

Eric

https://jsfiddle.net/ed7zwpvg/ :gift:

(0. I added html and body tags, but am not sure they are necessary on JSFiddle.)

  1. Certain things in init, I think mainly offsetWidth/offsetHeight, depended on being already connected.
  2. You never called renderer.render.

They are not :innocent:

Well, silly me… I had never thought of executing init() from connectedCallback… I tried so many things that I forgot to add to render this time.

Thank you!

I am glad to have helped you. :smiley:

Hello again,

I thought I could take over from after the help you gave me but I’m still stuck and I don’t understand why. I’ve done this several times without web components.

https://jsfiddle.net/Laf067wp/1/

I hope that once the the cube animation works, I’ll be able to make it work. So, if someone could help me, that would be very nice!

Short question: In the “responsive design” post (https://threejsfundamentals.org/threejs/lessons/threejs-responsive.html), they compute whether they should resize the canvas at each frame. Isn’t it better to use an eventListener on the window to do that, performance-wise? (second option seen in many other examples).

Thank you!

https://jsfiddle.net/1yxnecgo/

The problem was passing a method to requestAnimationFrame. You have to instead wrap the method call in a function. To avoid losing the this context, I used an arrow function. Not that obvious, eh? :wink:

PS: If you configure the renderer with antialias: true at construction, you will get smoother edges on the cube: https://jsfiddle.net/1yxnecgo/1/

1 Like

Thank you! or thanks again, should I say.

No, not obvious at all! It reminds of something I learnt a few days ago. To call a method from another method in the same class, in the constructor they added:

this.method = this.method.bind(this);

So I tried it here (Edit fiddle - JSFiddle - Code Playground lines 27 and 66)… but it did not work… perhaps because they are two levels? The console says: too much recursion.

This is very useful. Web components have difficulties I am not accustomed. I’m glad you’re helping me! :slight_smile: It is very interesting!

I am glad to have helped you!

That does not make too much sense. :wink: Function.prototype.bind() - JavaScript | MDN

If you need to pass a long function that needs the this context, you can either use tricks like someFunction.bind(this); or declare a named reference to the this context outside the function: const scope = this; and use scope instead of this inside the function. Or you can use an arrow function with a block (because arrow functions keep the this context):

(arg1, arg2) => {
    let something = makeSomething(arg1);
    this.aMethod(something, arg2);
}

ok… I don’t know what to say.

I’ll read the MDN page tonight. Thanks!