Search code examples
javascripthtmlweb-componentnative-web-component

How to expose ctx from inside Webcomponent?


When I try to set the width and height of the canvas element in the draw function, it seems to be setting them on some canvas, but not the one I'm looking at. Upon inspection of the canvas with the border I defined in the webcomponent, you will see that it still has the standard dimensions instead of being resized.

I'd like to expose the ctx of the component for use outside of it. What am I doing wrong?

class Component extends HTMLElement {
    constructor() {
        super();
        this.shadow = this.attachShadow({ mode: 'open' });
        const canvasContainer = document.createElement('div');
        canvasContainer.classList.add('canvas-container')
        canvasContainer.innerHTML = `
        <style>
            .canvas-container {
                width: 100%;
                height: 100%;
            }
            canvas {
                border: 1px solid black;
            }
        </style>
        <canvas></canvas>
        `;

        this.shadow.appendChild(canvasContainer);
    }
    get ctx () {
        return this.shadow.querySelector('canvas').getContext('2d');
    }
}

customElements.define('canvas-component', Component);
const component = new Component();
const ctx = component.ctx;
const canvas = component.ctx.canvas;

const draw = () => {
    canvas.width  = window.innerWidth;
    canvas.height = window.innerHeight;
    console.log(canvas);
    window.requestAnimationFrame(draw);
}

draw();
html, body {
    width: 100%;
    height: 100%;
    margin: 0;
}
<canvas-component></canvas-component>


Solution

  • repeating comment:

    Why const component = new Component(); and not work with the in the DOM? Those are 2 different objects and only the latter is visible on your screen (which you do NOT change the size of)

    And you can shorten that code to:

    <script>
    customElements.define('canvas-component', class Component extends HTMLElement {
      constructor() {
        super().attachShadow({mode:'open'}).innerHTML = `
            <style>canvas { width:100%;height:100%; border:1px solid black }</style>
            <canvas></canvas>`;
      }
      get ctx(){
        return this.shadowRoot.querySelector('canvas').getContext('2d');
      }
      size(w, h) {// also clears the whole canvas
        this.ctx.canvas.width = w; this.ctx.canvas.height = h;
      }
      rect({x=10,y=x,w=20,h=w,l=2,c='red'}){
        this.ctx.lineWidth   = l;
        this.ctx.strokeStyle = c;
        this.ctx.strokeRect( x, y, w, h );
      }
    });
    </script>
    <canvas-component id="C1"></canvas-component>
    <script>
      onload = () => {
        C1.size(innerWidth, innerHeight);
        C1.rect({});
        C1.rect({x:80,w:50});
        C1.rect({x:50,w:150,c:'green',l:3});
      }
    </script>