With a very busy summer of client work behind us, the core CreateJS team is back in the saddle and working hard to get the next build of the libraries completed.
If you follow us on GitHub, you’ll have noticed that our Issues & Pull Requests are now up to date, and that we’ve been committing code constantly. We’re also working on a new site & community strategy, but that’s a topic for another post.
One of the low-level items we’ve tackled recently is revising our class and inheritance model. We wanted to standardize our approach, and make it a little more approachable, while keeping a strong focus on performance.
We implemented three major changes:
- Moved all property definitions off of the prototype and into the constructor. This produces a more consistent object signature, and allows browsers to more effectively optimize methods at run time. The end result: a display list that is over 2x faster, and vastly faster property access throughout the library. (Thanks to webskin & MannyC for the input)
- Added and implemented an
extend
method. This codifies prototype inheritance in the library, and hopefully makes it easier for us to tweak the model moving forward. - Added a
promote
method, which promotes overridden superclass methods (and the constructor) to the subclass prototype. This makes these methods available in the object scope, without the significant performance overhead of usingfunction.apply()
.The other effect of this change was eliminating the
initialize
methods in favour of using promotedSuperClass_constructor
methods instead.
As always, we were careful to make sure that these new methods are totally independent of the library (you can use them wherever), and also that we retained as much backwards compatibility as possible. You can still use the previous inheritance approach to extend classes in the library with no problems.
All of these changes have been made in a branch of each library, and will be merged to master in the next few days once they’ve had a bit more testing. If you’d like to check them out, or test with them, you can grab them here:
EaselJS, SoundJS, PreloadJS, TweenJS.
If you’d like to learn more about the changes, the EaselJS branch has an updated inheritance tutorial.
We’ve done a reasonable amount of testing, but with the number of deep changes we’ve made in the past few weeks, we’d really appreciate if you could take a few moments to test your existing content against these revisions. The main thing you are likely to run into, is the missing initialize
methods, if you’ve been extending classes. Also, be sure to check out the VERSIONS file for each library for a full list of changes.
Hey, still fairly new to CreateJS. Regarding the above changes, are you proposing that we try to adopt the following changes into our own code once these get fully integrated into the library? Will there be a blog post/examples/templates available once this does happen?
The above provided inheritance example seems sufficient, but what about properties that aren’t assigned values via constructor args i.e. constants or variables assigned values outside of class instantiation? Would we need to also specify all other properties/constants inside the constructor as well?
Cheers,
Rich
Amazing!
EaselJS has merged these changes into master.
I have not tested it but was wondering if there is something to the old versions, I can not understand really well if applied in earlier versions of CreateJS.
You guys are awesome! Coming up in the Flash and AS3 world for years and having authored books on both Flash game development (The Essential Guide To Flash Games) and the O’Reilly HTML5 Canvas Books, I can say hat CreateJS is absolutely the best evolution of both! Keep up the great work. I’m moving to make this the standard HTML5 Canvas dev tool in the large Toy Company I work for.
Is there some way to use the new class model with the FlashCC export? Or will the export be fixed with the next stable version? Because this missing initilize function is problematic…
The latest version maintains an
initialize
method for compatibility with Flash CC.Well, with the NEXT build you get a “TypeError: this.initialize is not a function” with an exported movieclip … can we use the next tagged release with FlashCC or not?
Yes, that’s the same issue that we experience with content exported with Flash CS6/CreateJS ToolKit
It is our goal that is is compatible. We will look into the issue. Feel free to log something in GitHub issues. http://github.com/CreateJS/EaselJS/issues
Libraries generated from Flash use the old inheritance model. Even if the compatibility issues are solved, will content generated from flash enjoy the performance improvements that the next version comes with?
In that case I would consider writing a utility that updates libraries to use the new inheritance model (especially since we’re using Flash CS6 and I don’t expect to see a Toolkit upgrade anytime soon).
I have a similar question. We’re using Flash CS6 and the CreateJS Toolkit to generate most content, which currently doesn’t seem to be compatible with the new Class model. What will be the best way to handle this?
The new class model doesn’t change anything that will break compatibility with Flash export. You should be able to drop the latest libs into Flash projects without issue. If you run into problems, feel free to let us know.
Hi Lanny,
Does PhoneGap Build supports this new class model? Class references are not found when exporting through PhoneGap Build to Android…
Any suggestions?
Theo
Hi Lanny,
After some debugging I found out that the wrapper function in the provided class file example:
(function() {
function Button…
and
window.Button = …
are causing problems in Phonegap. By removing the wrapper function and replacing “window” by “this” everything works fine in both PhoneGap and browser.
Best regards,
Theo van Wijk
Thanks for the debugging. Unfortunately the function wrapper is a requirement to keep code isolated and not pollute the global scope. I don’t think that will change any time soon. Open to solutions that support both goals.
I am looking for an example of multiple inheritance. The provided example in the Inheritance folder has Button extending Container. What if I wanted another class to extend Button? I am not sure how to do that and am running into issues here.
Inheritance works with multiple levels. For example, the DisplayObject extends EventDispatcher, and is then itself extended by all display classes (Container, MovieClip, Text, Bitmap, etc). There is nothing special to due multi-level inheritance.
If you haven’t already, check out the new inheritance approach in GitHub, using “extend” and “promote”, which is much easier to use than the older approach. The tutorial on inheritance has also been updated, but won’t be published on the website until later this week.
cool, but the new promote method dose not work at IE old version.
EaselJS and SoundJS are only supported in IE9+, this only affects PreloadJS and TweenJS. We are looking at solutions. Thanks for the report!
Pingback: Extending a "class" and exporting it via modules « news-Knowlage FeeD
Guys, any idea why this isn’t working when I add it to the stage?
(function(window){
‘use strict’;
window.mag = window.mag || {};
function MagSprite() {
this.__super.call(this);
this.width = undefined;
this.height = undefined;
this.__shape = null;
this.addChildren();
};
MagSprite.prototype = Object.create(createjs.Container.prototype);
MagSprite.prototype.constructor = MagSprite;
MagSprite.prototype.__super = createjs.Container;
MagSprite.prototype.addChildren = function() {
this.__shape = new createjs.Shape();
this.addChild(this.__shape);
};
MagSprite.prototype.setWidth = function(value) { this.width = value; };
MagSprite.prototype.setHeight = function(value) { this.height = value; };
MagSprite.prototype.getWidth = function(value) {
if(this.width>=0) return this.width;
var bounds = this.getBounds();
if(bounds) return bounds.width-bounds.x;
return 0;
};
MagSprite.prototype.getHeight = function(value) {
if(this.height>=0) return this.height;
var bounds = this.getBounds();
if(bounds) return bounds.height-bounds.y;
return 0;
};
MagSprite.prototype.draw = function()
{
this.__shape.graphics.beginFill(“#FF0000”).drawRect(0,0,this.getWidth(),this.getHeight());
};
window.mag.MagSprite = MagSprite;
})(window);
In my main.js file, this is how I add it, then I check, the numberOfChildren of the stage, and they increase, so it is added but nothing visual changes.
var mag = window.mag;
var ms = new mag.MagSprite();
stage.addChild(ms);
ms.setWidth(100);
ms.setHeight(40);
ms.x = 50;
ms.y = 100;
ms.draw();
stage.update();
got it, I use draw method, and obviously override something I shouldn’t..