• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

Movie clip scaling inaccurately in HTML5 canvas

Community Beginner ,
Oct 02, 2022 Oct 02, 2022

Copy link to clipboard

Copied

Since I read that HTML5 Canvas doesn't support 9-slice scaling, I thought I'd code it myself.  I use two rectangles (rect_horiz and rect_vert) and four circles (corner_0, corner_1 etc.), and the shapes overlap, and should theoretically produce a pretty rounded rectangle.  It seems to almost work, but I'm getting weird inaccuracies in the graphics, on the top and left edges (the bottom right corner came out as hoped). 

 

To keep this post simple, here is just the code for rect_horiz (the rectangle that stretches across the entire width of the rounded rectangle I'm trying to create) and corner_0 (the top left corner).  The movie clip roundRect contains these two movie clips.  In the library, the circle is exactly 50 px across, and the rectangle is exactly 10px x 10px.  Neither one has a stroke. 

 

The idea in this example is to create a rounded rectangle programmatically with width 500 and height 100.  Again, this is just a piece of the code, but if it worked correctly, in the resulting graphics (green shapes shown in screenshot from browser, below), the left edge of the rectangle should be flush with the left edge of the circle.  Instead, the circle sticks out to the left by several pixels.  (The same problem occurred with rect_vert which I had intended to fill the top white gap, but I omitted that rect here for brevity).

 

Offset-graphics.jpg

 

(Note: "fixOrigin" follows the recommended method to deal with the problem that "CreateJS returns Transformation Point in instead of movieclip's x,y properties" (https://community.adobe.com/t5/animate-discussions/createjs-returns-transformation-point-in-instead-...and that approach has worked fine for me elsewhere.)

 

I feel like there must be some kind of rounding error in how the scaling is being applied here?  Is there a way to fix this problem?

 

var width = 500;
var height = 100;
var cornerRadius = 25;
var unitSize = 10;

fixOrigin(this.roundRect);
fixOrigin(this.roundRect.rect_horiz);
fixOrigin(this.roundRect.corner_0);

this.roundRect.rect_horiz.x = 0;
this.roundRect.rect_horiz.y = cornerRadius;
this.roundRect.rect_horiz.scaleX = width/unitSize;
this.roundRect.rect_horiz.scaleY = (height - 2 * cornerRadius) / unitSize;

this.roundRect.corner_0.x = 0;
this.roundRect.corner_0.y = 0;


function fixOrigin (mc) {
mc.x -= mc.regX;
mc.y -= mc.regY;
mc.regX = 0;
mc.regY = 0;
}

 

Views

157

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines

correct answers 1 Correct answer

Community Expert , Oct 05, 2022 Oct 05, 2022

Hi.

 

Congrats on your progress.

 

Alternatively, have you tried the ScaleBitmap class?

http://blog.createjs.com/scaling-and-stretching-with-the-scalebitmap-class/

 

Please let us know.

 

Regards,

JC

Votes

Translate

Translate
Community Beginner ,
Oct 04, 2022 Oct 04, 2022

Copy link to clipboard

Copied

Well, here's an idea.  Instead of two overlapping rectangles, I'll try it with 6 rectangles (plus the 4 circles to make the rounded corners).  One rectangle for each edge, plus another big rectangle for the center of the rounded rectangle.  This will be more cumbersome code and presumably will require more processing, but hopefully won't be as buggy...

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Oct 04, 2022 Oct 04, 2022

Copy link to clipboard

Copied

If anybody is curious, that second method (dividing up into actually 5 rectangles) works pretty well.  At first there were "cracks" of white showing through, because the bug in scaling is still there.  But I was able to cover it up using a "fudge factor" of 0.65 which expands the middle rectangle slightly.  The cracks start to show through if the rectangle is too large.

 

So, there really seems to be some kind of bug wherein scaling by a large amount shifts the movie clip over.  I'd love to know if there's a direct fix for that.

 

Here's my 9-slice scaling code, for anyone who's interested.  The circles are now 20px across, and the squares are still 10px x 10px.

 

var width = 326; // arbitrary dimensions for rounded rectangle
var height = 197;
var cornerRadius = 10;
var unitSize = 10;

fixOrigin(this.roundRect);
fixOrigin(this.roundRect.rect_top);
fixOrigin(this.roundRect.rect_right);
fixOrigin(this.roundRect.rect_bottom);
fixOrigin(this.roundRect.rect_left);
fixOrigin(this.roundRect.rect_middle);
fixOrigin(this.roundRect.corner_0);
fixOrigin(this.roundRect.corner_1);
fixOrigin(this.roundRect.corner_2);
fixOrigin(this.roundRect.corner_3);

this.roundRect.rect_top.x = cornerRadius;
this.roundRect.rect_top.y = 0;
this.roundRect.rect_top.scaleX = (width - 2 * cornerRadius) / unitSize;
this.roundRect.rect_top.scaleY = 1;

this.roundRect.rect_right.x = width - cornerRadius;
this.roundRect.rect_right.y = cornerRadius;
this.roundRect.rect_right.scaleX = 1;
this.roundRect.rect_right.scaleY = (height - 2 * cornerRadius) / unitSize;

this.roundRect.rect_bottom.x = cornerRadius;
this.roundRect.rect_bottom.y = height - cornerRadius;
this.roundRect.rect_bottom.scaleX = (width - 2 * cornerRadius) / unitSize;
this.roundRect.rect_bottom.scaleY = 1;

this.roundRect.rect_left.x = 0;
this.roundRect.rect_left.y = cornerRadius;
this.roundRect.rect_left.scaleX = 1;
this.roundRect.rect_left.scaleY = (height - 2 * cornerRadius) / unitSize;

this.roundRect.rect_middle.x = 0.65 * cornerRadius; // 0.65 is probably not the optimal value, but it worked for me
this.roundRect.rect_middle.y = 0.65 * cornerRadius;
this.roundRect.rect_middle.scaleX = (width - 2 * 0.65 * cornerRadius) / unitSize;
this.roundRect.rect_middle.scaleY = (height - 2 * 0.65 * cornerRadius) / unitSize;

this.roundRect.corner_0.x = 0;
this.roundRect.corner_0.y = 0;
this.roundRect.corner_1.x = width - 2 * cornerRadius;
this.roundRect.corner_1.y = 0;
this.roundRect.corner_2.x = width - 2 * cornerRadius;
this.roundRect.corner_2.y = height - 2 * cornerRadius;
this.roundRect.corner_3.x = 0;
this.roundRect.corner_3.y = height - 2 * cornerRadius;

function fixOrigin (mc) {
mc.x -= mc.regX;
mc.y -= mc.regY;
mc.regX = 0;
mc.regY = 0;
}

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Oct 04, 2022 Oct 04, 2022

Copy link to clipboard

Copied

Aha, I found a better fix.  I was able to make it work with my original method (just 2 rectangles overlapping like a Swiss cross, plus the 4 circles for corners).  Simply start with really huge squares, like 1000px x 1000px.  So unitSize = 1000, using my original code in the OP.  Lo and behold, the scaled shapes line up perfectly, no doubt because any "error" in the positioning of the scaled shapes is trivial in comparison to their starting size.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 05, 2022 Oct 05, 2022

Copy link to clipboard

Copied

Hi.

 

Congrats on your progress.

 

Alternatively, have you tried the ScaleBitmap class?

http://blog.createjs.com/scaling-and-stretching-with-the-scalebitmap-class/

 

Please let us know.

 

Regards,

JC

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Oct 05, 2022 Oct 05, 2022

Copy link to clipboard

Copied

Thank you so much!  I will have a look at this.

 

Lesson learned.  I only searched within this forum and found nothing so I assumed it was up to me to build from scratch.  It's a good reminder that really, what I am doing is building with EaselJS, and Animate (for HTML5 Canvas) is simply a tool to make that easier.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 06, 2022 Oct 06, 2022

Copy link to clipboard

Copied

You're welcome!

 

Yeah, the people behind CreateJS has lots of stuff on their blog, GitHub, CodePen, JSFiddle, and other places.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 06, 2022 Oct 06, 2022

Copy link to clipboard

Copied

LATEST

@JoãoCésar,

 

ScaleBitmap works great and is easy to use (including with animate).

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines