diff --git a/src/core/p5.Graphics.js b/src/core/p5.Graphics.js index 8d7c00eb74..f4d9c557ac 100644 --- a/src/core/p5.Graphics.js +++ b/src/core/p5.Graphics.js @@ -21,16 +21,26 @@ import * as constants from './constants'; * @param {Number} h height * @param {Constant} renderer the renderer to use, either P2D or WEBGL * @param {p5} [pInst] pointer to p5 instance + * @param {Object} [canvas] existing html canvas element */ p5.Graphics = class extends p5.Element { - constructor(w, h, renderer, pInst) { - let canvas = document.createElement('canvas'); - super(canvas, pInst); + constructor(w, h, renderer, pInst, canvas) { + let canvasTemp; + if (canvas) { + canvasTemp = canvas; + } else { + canvasTemp = document.createElement('canvas'); + } + + super(canvasTemp, pInst); + this.canvas = canvasTemp; + const r = renderer || constants.P2D; - this.canvas = canvas; const node = pInst._userNode || document.body; - node.appendChild(this.canvas); + if (!canvas) { + node.appendChild(this.canvas); + } // bind methods and props of p5 to the new object for (const p in p5.prototype) { diff --git a/src/core/rendering.js b/src/core/rendering.js index 6c2cc167fd..31448ac7a9 100644 --- a/src/core/rendering.js +++ b/src/core/rendering.js @@ -34,6 +34,9 @@ const defaultClass = 'p5Canvas'; * function. If createCanvas() is not used, the * window will be given a default size of 100×100 pixels. * + * Optionally, an existing canvas can be passed using a selector, ie. `document.getElementById('')`. + * If specified, avoid using `setAttributes()` afterwards, as this will remove and recreate the existing canvas. + * * For more ways to position the canvas, see the * * positioning the canvas wiki page. @@ -42,6 +45,7 @@ const defaultClass = 'p5Canvas'; * @param {Number} w width of the canvas * @param {Number} h height of the canvas * @param {Constant} [renderer] either P2D or WEBGL + * @param {Object} [canvas] existing html canvas element * @return {p5.Renderer} pointer to p5.Renderer holding canvas * @example *
@@ -57,56 +61,84 @@ const defaultClass = 'p5Canvas'; * @alt * Black line extending from top-left of canvas to bottom right. */ -p5.prototype.createCanvas = function(w, h, renderer) { +/** + * @method createCanvas + * @param {Number} w + * @param {Number} h + * @param {Object} [canvas] + * @return {p5.Renderer} pointer to p5.Renderer holding canvas + */ +p5.prototype.createCanvas = function(w, h, renderer, canvas) { p5._validateParameters('createCanvas', arguments); //optional: renderer, otherwise defaults to p2d - const r = renderer || constants.P2D; + + let r; + if (arguments[2] instanceof HTMLCanvasElement) { + renderer = constants.P2D; + canvas = arguments[2]; + } else { + r = renderer || constants.P2D; + } + let c; - if (r === constants.WEBGL) { + if (canvas) { c = document.getElementById(defaultId); if (c) { - //if defaultCanvas already exists c.parentNode.removeChild(c); //replace the existing defaultCanvas - const thisRenderer = this._renderer; - this._elements = this._elements.filter(e => e !== thisRenderer); } - c = document.createElement('canvas'); - c.id = defaultId; - c.classList.add(defaultClass); + c = canvas; + this._defaultGraphicsCreated = false; } else { - if (!this._defaultGraphicsCreated) { - c = document.createElement('canvas'); - let i = 0; - while (document.getElementById(`defaultCanvas${i}`)) { - i++; + if (r === constants.WEBGL) { + c = document.getElementById(defaultId); + if (c) { + //if defaultCanvas already exists + c.parentNode.removeChild(c); //replace the existing defaultCanvas + const thisRenderer = this._renderer; + this._elements = this._elements.filter(e => e !== thisRenderer); } - defaultId = `defaultCanvas${i}`; + c = document.createElement('canvas'); c.id = defaultId; c.classList.add(defaultClass); } else { - // resize the default canvas if new one is created - c = this.canvas; + if (!this._defaultGraphicsCreated) { + if (canvas) { + c = canvas; + } else { + c = document.createElement('canvas'); + } + let i = 0; + while (document.getElementById(`defaultCanvas${i}`)) { + i++; + } + defaultId = `defaultCanvas${i}`; + c.id = defaultId; + c.classList.add(defaultClass); + } else { + // resize the default canvas if new one is created + c = this.canvas; + } } - } - // set to invisible if still in setup (to prevent flashing with manipulate) - if (!this._setupDone) { - c.dataset.hidden = true; // tag to show later - c.style.visibility = 'hidden'; - } + // set to invisible if still in setup (to prevent flashing with manipulate) + if (!this._setupDone) { + c.dataset.hidden = true; // tag to show later + c.style.visibility = 'hidden'; + } - if (this._userNode) { - // user input node case - this._userNode.appendChild(c); - } else { - //create main element - if (document.getElementsByTagName('main').length === 0) { - let m = document.createElement('main'); - document.body.appendChild(m); + if (this._userNode) { + // user input node case + this._userNode.appendChild(c); + } else { + //create main element + if (document.getElementsByTagName('main').length === 0) { + let m = document.createElement('main'); + document.body.appendChild(m); + } + //append canvas to main + document.getElementsByTagName('main')[0].appendChild(c); } - //append canvas to main - document.getElementsByTagName('main')[0].appendChild(c); } // Init our graphics renderer @@ -216,11 +248,15 @@ p5.prototype.noCanvas = function() { * to check what version is being used, or call pg.setAttributes({ version: 1 }) * to create a WebGL1 context. * + * Optionally, an existing canvas can be passed using a selector, ie. document.getElementById(''). + * By default this canvas will be hidden (offscreen buffer), to make visible, set element's style to display:block; + * * @method createGraphics * @param {Number} w width of the offscreen graphics buffer * @param {Number} h height of the offscreen graphics buffer * @param {Constant} [renderer] either P2D or WEBGL * undefined defaults to p2d + * @param {Object} [canvas] existing html canvas element * @return {p5.Graphics} offscreen graphics buffer * @example *
@@ -245,9 +281,20 @@ p5.prototype.noCanvas = function() { * @alt * 4 grey squares alternating light and dark grey. White quarter circle mid-left. */ -p5.prototype.createGraphics = function(w, h, renderer) { +/** + * @method createGraphics + * @param {Number} w + * @param {Number} h + * @param {Object} [canvas] + * @return {p5.Graphics} offscreen graphics buffer + */ +p5.prototype.createGraphics = function(w, h, renderer, canvas) { + if (arguments[2] instanceof HTMLCanvasElement) { + renderer = constants.P2D; + canvas = arguments[2]; + } p5._validateParameters('createGraphics', arguments); - return new p5.Graphics(w, h, renderer, this); + return new p5.Graphics(w, h, renderer, this, canvas); }; /**