53 votes

Est-il possible de créer un canevas HTML sans élément DOM ?

J'aimerais disposer d'un contexte de canevas HTML sur lequel je puisse peindre et lire hors écran (dans cet exemple, écrire du texte et lire la forme qui est créée, mais c'est une question générale). J'aimerais également utiliser un canevas comme frame-buffer hors écran.

Je suppose que je pourrais créer un élément DOM caché mais je préférerais le créer à partir de JavaScript (je pourrais vouloir créer et détruire un certain nombre de canevas au moment de l'exécution).

Possible ?

64voto

Felix Kling Points 247451

Vous pouvez créer un nouveau canvas élément avec document.createElement :

var canvas = document.createElement('canvas');

et d'en tirer le contexte. Assurez-vous simplement de définir l'option width y height . Il n'est pas nécessaire d'ajouter la toile à l'arbre pour que cela fonctionne :

DEMO

Mais vous devez absolument créer ce nœud. Vous pourriez cependant créer une fonction pour cela :

function createContext(width, height) {
    var canvas = document.createElement('canvas');
    canvas.width = width;
    canvas.height = height;
    return canvas.getContext("2d");
}

Mais c'est là que s'arrête ma compétence... si vous pouvez d'une manière ou d'une autre transférer un contexte à un autre contexte ou à une toile, je ne sais pas...

8voto

Dave Points 71

C'est vieux mais que diriez-vous de sauvegarder un canevas avec toDataURL et de le copier sur l'autre avec drawImage. Vous pourriez également utiliser la sauvegarde et la restauration pour créer un tampon de trame.

function createCanvas(width, height) {
    var c = document.createElement('canvas');
    c.setAttribute('width', width);
    c.setAttribute('height', height);
    return c;
}

function canvasImg(canvas) {
    var ctx = canvas.getContext('2d');
    ctx.fillRect(0,0,canvas.width, canvas.height);
    var img = canvas.toDataURL('image/png');

    return img;
}

function placeImage(canvas, img) {
    var ctx = canvas.getContext('2d');
    ctx.drawImage(img, 0,0);
}

window.onload = function(){
    var canvas = createCanvas(400, 400);
    var hiddenCanvas = createCanvas(400,400);
    var i = canvasImg(hiddenCanvas);
    var img = new Image();
    img.src = i;
    placeImage(canvas, img);
    document.body.appendChild(canvas);
}

8voto

Isti115 Points 131

Il y a apparemment une nouvelle chose appelée OffscreenCanvas qui a été délibérément conçu pour ce cas d'utilisation. Un bonus supplémentaire est qu'il fonctionne également dans les Web Workers.

Vous pouvez lire les spécifications ici : https://html.spec.whatwg.org/multipage/canvas.html#the-offscreencanvas-interface

Et voyez des exemples ici : https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas

Actuellement, il n'est entièrement pris en charge que par Chrome et est disponible derrière des drapeaux dans Firefox et Opera, mais vous pouvez toujours vérifier les dernières informations sur les navigateurs pris en charge ici : https://caniuse.com/#feat=offscreencanvas

ps. : Google a également un guide dédié expliquant son utilisation dans les Web Workers : https://developers.google.com/web/updates/2018/08/offscreen-canvas

0voto

nevernew Points 560

Les classes CanvasRenderingContext2D et WebGLRenderingContext ont toutes deux l'élément canvas associé à la propriété canvas ; et, comme d'habitude, les instances de contexte et leurs toiles seront collectées lorsque votre code ne fera plus référence à elles au moment de l'exécution.

Vous pouvez utiliser cette fonction pour créer un nouveau contexte

function newContext({width, height}, contextType = '2d') {
    const canvas = document.createElement('canvas');
    canvas.width = width;
    canvas.height = height;
    return canvas.getContext(contextType);
}

const ctx = newContext({width: 100, height: 100});
console.log(ctx.canvas.width == 100) // true

En utilisant le déréférencement, vous pouvez facilement créer un clone d'un canevas DOM pour la mise en mémoire tampon comme ceci :

const domCanvas = document.getElementById('myCanvas');

const frameBuffer = newContext(domCanvas);
frameBuffer.drawImage(domCanvas, 0, 0);

Ce qui créera un contexte avec la même largeur et hauteur que l'élément de toile transmis. Vous pouvez étendre cette fonction selon vos besoins.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X