Make your own free website on Tripod.com

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.

Remember this and exit this page. It is not necesarry to continue to read.

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.