# CanvasClass

I started using p5.js in December, 2019. I wanted to have two canvases for my first significant application and was really disappointed to read "Calling createCanvas more than once in a sketch will result in very unpredictable behavior." Because that has not a HTML or javascript restriction, I decided to see if there was away around this problem. My first effort was semi-successful but required a lot of coding. Then I learned about instance mode which supposedly solves the problem but in my experience seems to be mystical and makes it difficult to use events.

I started over again and came up with `CanvasClass` (for the lack of a better name). As the name suggests, it declares a CanvasClass class. I think it enables users to avoid the problems with instance mode. Most of the p5.js methods (except for some WEBGL methods) and events for the canvas work. Over 110 functions are believed to work with over a dozen additional ones that work in part.

Here is a very simple example that uses two canvases and demonstrates the type of coding needed. Notice that one has to name each canvas and use the name whenever referring to the canvas or the mouse. Drag your mouse over the two canvases and click on the first one. You will notice that the events and mouse values only work when the mouse is over the canvas.

    let canvas1, canvas2, backgroundColor1;
    function setup() {
      canvas1 = createCanvasClass(180, 170);
      canvas1.parent("Example");
      canvas1.fill(255, 0, 0);
      canvas1.mouseClicked(clicked);
      backgroundColor1 = "FloralWhite";
      canvas2 = createCanvasClass(150, 200);
      canvas2.parent("Example");
      canvas2.stroke(255, 0, 255);
    }
    function draw() {
      canvas1.background(backgroundColor1);
      canvas1.rect(canvas1.mouseX, canvas1.mouseY, 100 ,80);
      canvas2.background("Khaki");
      canvas2.line(canvas2.mouseX, canvas2.mouseY, 75, 100);
    }
    function clicked() {
      if (backgroundColor1 == "FloralWhite") {
        backgroundColor1 = "LightCyan";
      } else {
        backgroundColor1 = "FloralWhite";
      }
    }

Notice that names for canvases and mouse positions are used consistently. In regular p5 canvases there are times when a canvas name is required and other times when it is not allowed.

Want to be able to follow the mouse even when the mouse is not over the canvas? See philExample.html

.

A significant problem is related to the fact that p5.js resets some transformations (using resetMatrix) and WEBGL rotations every time a new frame is drawn. Unfortunately I haven't figured out how to do either automatically. It is relatively easy to solve problems related to resetMatrix, translate, rotate, and scale but I have been unable to solve problems related to WEBGL. 16 methods WEBGL methods have been implemented: (plane, box, cylinder, cone, torus, sphere, ambientLight, pointLight, specularColor, normalMaterial, ambientMaterial, specularMaterial, shininess, rotateX, rotateY, and rotateZ). All of these methods work when used in `setup()`. Implementing them was easy. But there is a problem. The first 9 work nicely when used in `draw()` unless the object is put in motion using 3 rotate methods. I am pretty sure that the problem is related to the fact the rotations are not reset every time a new frame is drawn.

I am sure that persons who better understand instance mode, nameSpace, `_pInst` and renderer could write better code and solve the problems with resetting things with each time `draw()` is executed. There were some times I had to make choices about how to implement methods - some of those choices are debatable. Unfortunately, there are probably still some coding errors despite a lot of testing.

CanvasClass actually uses instance mode to create the canvas but hides it so users don't need to be concerned with it. Most methods are trivial to implement but a few (particularly those that use hidden data) had to be rewritten.

implementation.html Lists the methods and other elements that have been implemented CanvasClass.

Some examples and testing:
sketch.html A program to allow drawing with different shapes that uses several CanvasClass methods.
ball.html A rewrite of a SonnySanberg demo with three bouncing ball using CanvasClass.
Birthday.html A fun page that uses one CanvasClass.
bezier.html Demo using bezier curves.
Enlarge.html Allows one to load a large image file into one CanvasClass and then look at a enlarged portion of it in a second CanvasClass.
child.html Tests child, text, style, id, background, elt, canvas, and fill comparing them to a regular p5.js canvas.
colors.html Tests several color related methods.
colorTest.html Test several color related methods with emphasis on colorMode, HSL and HSB.
CanvasClassTest.html Test over 50 methods using 15 canvases. image.html Tests image, blend, background(image) and pixelDensity
domImage.html Tests parent, id, clear, text, background, rect, applyMatrix, resetMatrix, image, and imageMode.
rotation.pjs Demonstrates successes and failures when working with WEBGL and "in-motion" rotations.
webgl.html Also demonstrates successes and failures when working with WEBGL and "in-motion" rotations.Tests the 12 WEBGL related methods that have been implemented.
ambient.html Tests the WEBGL functions `ambientLight`, `ambientMaterial`, and `emissiveMaterial` succesfully.
events.html Tests many events.
events2.html Illustrates how to use CanvasClass events.
hideShow.html Tests resize, hide and show demonstrating the CanvasClass option to show the canvas inline.
save.html Tests saveCanvas.
TV.html There are 4 "TV's" each doing there own thing. It tests image, mouseClicked and keyIsPressed along with several methods.
transforms.html Tests resetMatrix, scale, rotate, and translate along with several other methods.
get.html Tests `get`. Works correctly with 2 arguements but not with 0 or 4.
getImageFromWebPage.html Tests and demonstates 3 ways to load images from the web page. Loading images from the web pages avoids having to preload or use local servers.

### Known problems:

Any help in solving these problems would be appreciated.

- In a regular p5 canvas, `resetMatrix()` is called every time the frame is redrawn. This does not happen in CanvasClass. The solution is to call `resetMatrix()` at the beginning of `draw()` if `applyMatrix`, `rotate`, `scale`, or `translate` are used.
- Rotations don't work in "in-motion" draw()s in the WEBGL mode.
- In some situations, it is necessary to say can.canvas (or can.elt) when referring to the canvas. Example: see saveCanvas. (Here we are assuming that the canvas is named "can".);
- `get()` and `get(x, y, w, h)`have problems even though `get(x, y)` works OK.

If you have an application you would like to share, have questions, suggestions, or comments, please let me know. brinkje@plu.edu

The CanvasClass.pjs file.
CanvasClass.zip a zip file containing all the files listed above.

James Brink, 7/23/2020