Start · Sprachen · JavaScript · Referenz · WebGLRenderingContext.canvas

WebGLRenderingContext.canvas

Eigenschaft

Schreibgeschützter Verweis auf das <code>HTMLCanvasElement</code> oder <code>OffscreenCanvas</code>, zu dem der WebGL-Kontext gehört.

seit JavaScript Baseline: alle Browser (WebGL 1); OffscreenCanvas- Kategorie: webapi

Signatur

WebGLRenderingContext.canvas

Beschreibung

Die Eigenschaft canvas eines WebGLRenderingContext (und ebenso eines WebGL2RenderingContext) verweist auf die Zeichenfläche, von der der Kontext über getContext("webgl") bzw. getContext("webgl2") erzeugt wurde. Die Eigenschaft ist schreibgeschützt: Ein Kontext bleibt für seine gesamte Lebensdauer an genau eine Zeichenfläche gebunden.

Nützlich ist sie vor allem dann, wenn eine Funktion nur den Kontext gl übergeben bekommt, aber Zugriff auf die Zeichenfläche braucht – etwa um width/height auszulesen, die Darstellungsgröße über clientWidth/clientHeight anzupassen, Ereignis-Listener anzuhängen oder mit toDataURL() einen Screenshot zu erzeugen. So muss man das Canvas-Element nicht zusätzlich durch den Code reichen.

Wird der Kontext in einem Worker auf einem OffscreenCanvas erzeugt, liefert canvas dieses OffscreenCanvas-Objekt. Dort gibt es keine DOM-Eigenschaften wie clientWidth oder toDataURL(); stattdessen stehen etwa convertToBlob() und transferToImageBitmap() zur Verfügung.

Rückgabewert

Typ
HTMLCanvasElement | OffscreenCanvas
Beschreibung
Die Zeichenfläche, zu der der Kontext gehört. Im Hauptthread in der Regel ein HTMLCanvasElement, in Workern ein OffscreenCanvas.

Beispiele

Zeichenfläche aus dem Kontext ermitteln

const canvas = document.createElement('canvas');
canvas.width = 300;
canvas.height = 150;
const gl = canvas.getContext('webgl');

console.log(gl.canvas === canvas);
console.log(gl.canvas.width, gl.canvas.height);
true 300 150

Canvas-Auflösung an Anzeigegröße anpassen (nur mit gl)

const resizeToDisplay = (gl) => {
  const canvas = gl.canvas;
  const dpr = window.devicePixelRatio || 1;
  const width = Math.round(canvas.clientWidth * dpr);
  const height = Math.round(canvas.clientHeight * dpr);

  if (canvas.width !== width || canvas.height !== height) {
    canvas.width = width;
    canvas.height = height;
  }
  // Viewport an den tatsächlichen Zeichenpuffer anpassen
  gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
};

const gl = document.querySelector('#scene').getContext('webgl');

const render = () => {
  resizeToDisplay(gl);
  gl.clearColor(0.1, 0.2, 0.3, 1);
  gl.clear(gl.COLOR_BUFFER_BIT);
  requestAnimationFrame(render);
};
requestAnimationFrame(render);

Screenshot der Szene erstellen

const canvas = document.querySelector('#scene');
// preserveDrawingBuffer, damit der Inhalt nach dem Frame noch lesbar ist
const gl = canvas.getContext('webgl', { preserveDrawingBuffer: true });

gl.clearColor(1, 0.5, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);

const saveScreenshot = (gl) => {
  const link = document.createElement('a');
  link.download = 'szene.png';
  link.href = gl.canvas.toDataURL('image/png');
  link.click();
};

saveScreenshot(gl);

OffscreenCanvas im Worker

// worker.js
self.onmessage = async ({ data }) => {
  const gl = data.canvas.getContext('webgl');
  console.log(gl.canvas instanceof OffscreenCanvas);

  gl.clearColor(0, 1, 0, 1);
  gl.clear(gl.COLOR_BUFFER_BIT);
};

// main.js
// const offscreen = document.querySelector('#scene').transferControlToOffscreen();
// const worker = new Worker('worker.js');
// worker.postMessage({ canvas: offscreen }, [offscreen]);
true

// Wichtig · Fallstricke

  • Schreibgeschützt: Eine Zuweisung wie gl.canvas = other wird ignoriert (im Strict Mode TypeError). Größenänderungen erfolgen über gl.canvas.width/height.
  • Typ prüfen: In Bibliotheken, die sowohl im Hauptthread als auch in Workern laufen, vor dem Zugriff auf clientWidth, getBoundingClientRect() oder toDataURL() mit instanceof HTMLCanvasElement prüfen – beim OffscreenCanvas existieren diese nicht.
  • Canvas-Größe ≠ Zeichenpuffer: gl.canvas.width kann von gl.drawingBufferWidth abweichen, wenn der Browser die Puffergröße begrenzt. Für gl.viewport() daher die drawingBuffer*-Werte verwenden.
  • Kontextverlust: Auch nach webglcontextlost bleibt gl.canvas gültig; die Listener für webglcontextlost/webglcontextrestored hängt man am besten an gl.canvas.
  • Kompatibilität: In allen modernen Browsern verfügbar; OffscreenCanvas mit WebGL wird in Safari erst ab Version 16.4 unterstützt.