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);
};
/**