Update: Limited support for calculating bounds has been added. Read more here.
I get asked a lot why EaselJS does not support width and height values on DisplayObject instances. It’s an obvious feature to add, and would enable a lot of secondary functionality. On the surface it seems like it would be easy to implement, but gets a lot messier when you start digging in.
Shapes
Vector shapes are one of the biggest challenges. On first glance it seems pretty straightforward to calculate bounds. Shape data cannot be modified, so all we have to do is calculate the extents of each path as it is added, and track the min/max values to know our bounds. Right?
That definitely works with simple shapes like the line in the image below. But it gets a lot more complex when you start considering the properties that can be applied to that stroke. If the stroke is 20px wide, we now have to use a little bit of trig to calculate the corners of the end caps. That logic also has to account for the different cap types (butt, square, or round).
What about if we introduce a curve into that 20px line? Now we need to calculate the extents of the curve. The math for this is widely available, of course, but we need to be sure to account for the line width appropriately, and implement it for both cubic and quadratic curves. We also need to calculate the instantaneous angle at each end of the curve so we can correctly calculate the points from the caps.
And of course, we can’t forget about joint styles (bevel, round and miter), and applying miter limits as in the fourth example above. Little details that complicate things a lot.
All this math is doable, if fairly expensive, and hey, we only need to calculate all of this once, right? Well, sort of.
Transforms
If we can put a bounding box around our content, then calculating its transformed bounds is pretty simple, we just transform the corner points and find the new extents. However, it isn’t that simple when dealing with vector shapes.
Take a look at the images below, where we find the bounds of a simple curve and then rotate that curve 45 degrees. If we treat the shape as a box, then we wind up with the grossly exaggerated bounds in the second example, when of course we want the bounds in the third frame.
To do this, we need to run all of the relevant points in the entire shape through the concatenated transformation matrix. We can cull the list of points with some fancy logic that discards insignificant points, but it still has a fairly high cost. It’s especially expensive if you’re checking the bounds in multiple places (ex. on the shape, on its parent, on the stage), because the bounds have to be recalculated for each context.
So, shapes can be done, but doing it in JS is shockingly expensive, would involve a lot of added code, and honestly requires more math genius than I have. That said, if anyone wants to take a stab at this, we’d love to have you try!
Text
Things get even worse when looking at Text instances. The current text API for canvas simply doesn’t give us the ability to calculate bounds. We can do a pretty good job at calculating width, and offset it appropriately based on text alignment.
Height isn’t available though. We currently take a really rough guess at it by looking at the width of an M character, but it’s far from accurate. Once we have the height, we need to take an even less accurate guess at how to offset it based on the textBaseline (of which there are 6 possible values).
Sadly, calculating bounds for text is just not possible right now. The canvas API was recently updated with extended text metrics that will make this possible, but currently no browsers have support.
Conclusion
I would love to fully support display object bounds, but it doesn’t seem likely to happen soon for the reasons outlined above.
Update: Limited support for calculating bounds has been added. Read more here.
I’ve struggled with the same problems before and i think it’s better to implement the bounds feature even if it is not accurate in all use cases (e.g. lines with fancy caps and joint styles).
There is a great website explaining how to calculate the bounding box of quadratic and cubic curves.
http://pomax.github.io/bezierinfo/#boundingbox
You can also look at the source code of my project here:
https://github.com/bp74/StageXL/blob/master/lib/src/display/GraphicsCommand.dart#L251
For texts there is a workaround which works in most cases. It calculates the ascent, descant and height of texts. It draws the text in HTML and applies some CSS to it, in the end you get pretty good numbers.
https://github.com/bp74/StageXL/blob/master/lib/src/text/FontStyleMetrics.dart
The future canvas standard will have a much better TextMetrics calculation, hopefully this will be supported in all browsers soon:
http://www.w3.org/TR/2dcontext/#textmetrics
sorry for my bad english
you can try to create a virtual canvas and put your object inside and detect the first xStart, xEnd, yStart, yEnd on parsing the non-alpha pixels
width an optimised algorythme which start and stop to top and right and bottom and left, while not parsing the same time 2 pixels
I think, it was probably spend more resources but it’s not too complicated to set up
thanks for all your libraries
Hello, createjs is the first framework I’ve used, however I did think it was strange that there was no width and height. I think what I’ll do is just create my own class that has a display object, and has getWidth and getHeight methods that takes into the consideration the scale ect.
I was wondering how YOU have been handling width and height in your own code? Do you have an object that extends bitmap or HAS a bitmap and this object has these methods . Do you just you bitmap.image.width if it’s an bitmap? I’m not sure because I haven’t tried it yet but if I remember correctly I think it’s different if you want the width of an animation.
I mean most people need this, and if you don’t add we have to add it ourselves which is fine by me. Just not sure whether to use inheritance or composition to add these methods.
PS I am away that you have added a getbounds method. But would still like to know how you have been handling this up until now.
Hi, when I first checked EaselJS out I found the lack of width and height very intriguing. However, by using it and trying to find workarounds for these properties I ran into the very same questions you posted here, including one: the width and height of a container objects…
I believe that due to the migration from Flash and the similarities among it and CreateJS, one may think that the lack of the width and height properties can make the development very hard, but this is not true. You just need to “think on CreateJS terms”, not Flash ones. I can confirm this now that I’ve been used to CreateJS for some time ;-)
Is there a RoadMap? Do we have a target 1.0 release or feature set?
And of course, when will the next release be coming to us?
I was also wondering when the next release will be. There are issues in the current release that are working in the current codebase that I’m keen to put into production. Awesome work, by the way :)
For shape bounds, it’s worth noting that Flash does not take into account line width or anything like that, to include this information in flash one must first ‘convert lines to fills’.