Signatur
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
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);
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]);
// Wichtig · Fallstricke
- Schreibgeschützt: Eine Zuweisung wie
gl.canvas = otherwird ignoriert (im Strict ModeTypeError). Größenänderungen erfolgen übergl.canvas.width/height. - Typ prüfen: In Bibliotheken, die sowohl im Hauptthread als auch in Workern laufen, vor dem Zugriff auf
clientWidth,getBoundingClientRect()odertoDataURL()mitinstanceof HTMLCanvasElementprüfen – beimOffscreenCanvasexistieren diese nicht. - Canvas-Größe ≠ Zeichenpuffer:
gl.canvas.widthkann vongl.drawingBufferWidthabweichen, wenn der Browser die Puffergröße begrenzt. Fürgl.viewport()daher diedrawingBuffer*-Werte verwenden. - Kontextverlust: Auch nach
webglcontextlostbleibtgl.canvasgültig; die Listener fürwebglcontextlost/webglcontextrestoredhängt man am besten angl.canvas. - Kompatibilität: In allen modernen Browsern verfügbar;
OffscreenCanvasmit WebGL wird in Safari erst ab Version 16.4 unterstützt.