One question I had early on was along the lines of “What if I want to have two canvases with wirelib animations in them?” The answer was, you couldn’t. Because the wirelib object was a sort of singleton, initialized with a single canvas and that was that. That might be ok for some implementations, but I could definitely see the use case, and it was an interesting exercise to convert it to work that way.
It seemed to me the best way to have multiple instances of the library, each initialized with its own canvas, was to use a constructor function. Then you could do something like:
var wl1 = new Wirelib(myCanvas1);
var wl2 = new Wirelib(myCanvas2);
Then you could add different lines to each one, and animate them separately.
Well, it took a bit of work, but that’s what I got going. The architecture is a bit different, so it’s a good chance to explore different ways of doing things.
You can see the result here: http://www.bit-101.com/jscanvas/wirelib_0.1.js
Note that the whole thing is now contained in a single function definition:
[php lang=“JavaScript”]function Wirelib(canvas) {
//…
}[/php]
This really brings back some good old AS1 memories. Remember, in JS, a function is an object. And you can use the “new” keyword with any function to make a new object that will use that function as its prototype. Doing this, you can simulate all kinds of Object Oriented, class based setups. But in reality, JS does not have classes, so all you are doing is simulating such. We did this in AS1 and while it was useful and led to AS2, which standardized the syntax, and AS3 which really DOES have classes, it always felt pretty hacky back then. I was pleased to read from a few sources that this kind of pseudo-class stuff is often frowned upon. From what I’ve seen, it’s most often implemented by people coming into JavaScript from an object oriented language like AS3. Not being comfortable with the classless system, and not wanting to learn the lay of the land and the way most other JS programmers do things, they insist on simulating classes and inheritance and probably cause more problems than they are solving.
Anyway, simply using a constructor function does not fall into this category. It’s a valid part of the core JavaScript language and not a hack. Here, the constructor function takes a canvas as an argument.
Note that all the functions now are redefined to be in the form of “this.funcName = function() {…};”. This makes these functions available as properties of the object created with new. If we were to do this:
[php lang=“JavaScript”]function Foo() {
function bar() {
alert(“hello world”);
}
}
var foo = new Foo();
foo.bar();[/php]
Nothing would happen. In fact, we’d get an error that “Object #< Foo > has no method ‘bar’”. However, this does work:
[php lang=“JavaScript”]function Foo() {
this.bar = function() {
alert(“hello world”);
}
}
var foo = new Foo();
foo.bar();[/php]
So in WireLibJS, after the variables are declared, all the functions are defined with “this”. Finally, the last block of code gets the width, height, context, etc.
[php lang=“JavaScript”] if (canvas !== undefined) {
width = canvas.width;
height = canvas.height;
cx = width / 2;
cy = height / 2;
cz = fl * 2;
context = canvas.getContext(“2d”);
}
[/php]
Note that nothing is returned explicitly. When using a constructor function, it automatically returns this. Another change I made is that there were a few “public” variables returned before: strokeStyle, lineWidth, showCenter, and clearCanvas. I could have continued to have them be properties like that by saying, for example, this.strokeStyle = “#000000”; somewhere in the function. However, I chose to create them as local vars and gave setters and getters to each of them: setStrokeStyle, getClearCanvas, etc. I’m not sure this was the “best” thing to do. I was just experimenting with different styles and this is where it landed as of this writing.
OK, then, let’s see it in action. First, we have a web page that includes this new file, and two canvases, a bit of css to position them, and another .js file:
[php lang=“html”]