Rotate a clip then set _width=200
ericlin@ms1.hinet

Make a movieClip and put on these script:

clip._rotation = 30;
clip.setWidth(200);
trace(clip._width);
clip.setWidth(200);
trace(clip._width);

We get 2 outputs by the trace(clip._width) script; All of the values are different. None of them is 200.

So, what happened to my "200" ? What was going on ?

OK, a common principle is that, in any condition, we should transform our clip by setting the _xscale and _yscale of the clip instead of _width and _height.

Unless you have huge curiosity.

Before we discuss the detail of that mysterious script, we may review some basic knowledge about _xscale and _width. If you are already familiar with those properties, skip this section.

First:

I invent two new normenclature, the "protoWidth" and "protoHeight" to tell the story. Lets create a movieClip symbol, a square of 100x100. The width before transformation is 100 and the height is 100; The width and height in the library (100 _xscale and 100 _yscale) are what I call protoWidth and protoHeight.

When we set _xscale=200, then the result _width will be _xscale*protoWidth/100;

When we set _width=200, then the result _xscale will be 100*(widthSetting/protoWidth); Becareful, the return value is invalid if the protoWidth is 0 like in the case of emptyMovieClip. And, we have no way to make movieClip flip horizontally or vertically by setting _width and _height, because _width and _height are always positive.

In fact, Flash is a movie about vector animation. All the calculation is through _xscale and _yscale. So, any transformation commands setting width and height are converted to xscale and yscale changes to draw the shape. _xscale and _yscale store values of signed float. Negative value of _xsclae and _yscale means flipping horizontally and vertically. They are more powerful and meaningful than width and height which store only positive integer of TWIP.

Second:

The definition of _width and _height are horizontal and vertical extent of the clip. However, the true meaning is not so straight forward when the clip get rotated.

A clip, containing a square of 100x100, gets rotated 45 degrees, the _width is 141.44 and the _height is 141.44. Few would arguet about such definition of _width and _height.

How about a clip containing a circle of 100x100 ? When it gets rotated 45 degrees, the _width is also 141.44 and _height is 141.44, the same as cliips of square. This might surprise you. On the screen, the horizontal and vertical extent do not show any changes because it is a circle. Then , why is the _width 141.44 not 100 ? Well, the _width and _height are the extent of the "CANVUS", not the fills. This concept is very important if you want to use the function clip1.hitTest(clip2); For checking hitTest between two rotated circles, the result might surprise you much, because the _width and _height are much larger than what you see on the stage.

So, when a clip gets rotated, the ratio _xscale to _width is no more proportional, so is _yscale to _height;

How does Flash handle the script "_width=200"  when the clip is in rotation state ?

See this Movie.

The upper picture is a clip containing a 45-degree-rotated box. When we set its width by "_width=240", it calculate the "protoWidth" - the width when the clip is in 100 xscale and 100 yscale. Then the _xscale is calculated by 100*desiredWidth/protoWidth. Here the resulting _xscale is 169.3. After render the shape by _xscale=169.3, the result is a skewed trapezoid like the one shown above. If we do trace(sq2._width), the output is 240.  Also, the height and _yscale are not affected by this setting width command. Perfect !

Lets see the lower picture. The clip itself gets rotated to 45 degrees. When we try to set its width by "_width=240", it calculate the "protoWidth" - the width when the clip is in 100 xscale and 100 yscale. Then the _xscale is calculated and the value is the same as above. Flash render the shape by _xscale=169.3. The result is shown as the lower picture. It is not what we want. If we trace(sq1._width), the output is not 240, neither the length of X limb.

Even worse, Flash still updates the _yscale although we are setting the width only. The _yscale is calculated by the same equation:

_yscale= 100*desiredHeight/protoHeight;

Here, the desired Height is current _height. Unfortunately, when the clip is in rotated state, the relation between the height and the _yscale is not fixed. The _height is also affected by X limb. And, the result is a mess. We will discuss this in later section: "repeated setting _width=240" changes the _yscale and _height every time.

We can see that, the logic is definitely wrong. The X limb is not horizontaly oriented but already rotated 45 degree. Even worse thing is that, stretch along the rotated X limb changes not only the WIDTH of the clip, the HEIGHT is also affected.  Anyway, this is not logical, so we are not surprised by a "HEIGHT CHANGE by SETTING WIDTH".

Yes, it is how Flash handle the "_width=240";

Let me tell the story by Action script:

MovieClip.prototype.setWidth = function(w) {
this.getProtoWH();
trace("_width="+w+" is convert to commands:");
trace(" _xscale="+100*w/this.protoWidth);
trace(" _yscale="+100*this._height/this.protoHeight);
this._width = w;
trace("end _xscale="+this._xscale);
trace("end _yscale="+this._yscale);
};
MovieClip.prototype.setHeight = function(h) {
this.getProtoWH();
trace("_width="+w+" is convert to commands:");
trace(" _xscale="+100*this._width/this.protoWidth);
trace(" _yscale="+100*h/this.protoHeight);
this._height = h;
trace("end _xscale="+this._xscale);
trace("end _yscale="+this._yscale);
};
MovieClip.prototype.getProtoWH = function() {
var w0 = this._width;
var h0 = this._height;
this._xscale = this._yscale=100;
this.protoWidth = this._width;
this.protoHeight = this._height;
this._width = w0;
this._height = h0;
};

Lets check the mysterious scripts step by step.

When we rotatte this clip 30 degree, the _width changed from 100 to 136.6 and _height changed to 136.6;

the protoHeight is changed to 136.6 and the protoWidth is 136.6;

When we set _width=200, Flash create a rotated symbol as template with protoHeight 136.6 and protoWidth 136.6; Take the 200 as the desired width to calculate _xscale, the result is 146.41. Take the old _height to calculate _yscale and the result is 100; Then renders the shape by _xscale and _yscale. The resulted shape is 176.8 wide and 159.6 high.

Please note that, the end _width is not 200; Also note that, although setting a _width does not change the _yscale, the _height does get changed because of the rotated state.

Lets do "_width=200;" once more; The calculated _xscale is the same as above. However, the _height is already changed from 136.6 to 159.6, so the is the _yscale. The calculated _yscale now is 146.41; Flash renders the shape by _xscale and _yscale. The resulted shape is 195.3 wide and 184.5 high;

Please note that, you might have expect that to repeat a script of "_width=200" immediately after a command of "_width=200" should have no any further effect. Well, it does not affect _xscale any more. But, it affect _yscale. Through the change of _yscale, it changes _width and _height;

If we do "_width=200" a third time, the yscale will be affected agian, so will the _width and _height.

When we repeatedly call "_width=200", the end result is increasing _yscale for each call. And we never get a _width of 200;

I dont know whether this confuse you. Anyway, this is how Flash does its job.