Flash/Flex学习笔记(49):3D基础 里已经介绍了3D透视的基本原理,不过如果每次都要利用象该文中那样写一堆代码,估计很多人不喜欢,事实上AS3的DisplayObject类已经内置了z坐标、rotationX、rotationY、rotationZ属性,再加上PerspectiveProjection类用于处理透视转换,基本上可以满足大多数的3D要求。
001
import
flash.events.Event;
002
import
flash.display.Sprite;
003
import
flash.text.TextField;
004
import
flash.events.MouseEvent;
005
import
flash.text.TextFieldAutoSize;
006
007
var
isAngleChangeing =
false
;
008
009
var
txtX:TextField,txtY:TextField,txtZ:TextField,txtPosZ:TextField,txtFieldOfView:TextField,txtInfo:TextField,txtCenter:TextField,txtFocusLength:TextField;
010
txtX =
new
TextField();
011
txtX.text =
"rotationX:"
;
012
txtY =
new
TextField();
013
txtY.text =
"rotationY:"
;
014
txtZ =
new
TextField();
015
txtZ.text =
"rotationZ:"
;
016
txtPosZ =
new
TextField();
017
txtPosZ.text =
"Z:"
;
018
txtFieldOfView =
new
TextField();
019
txtFieldOfView.text =
"视角:"
;
020
txtCenter =
new
TextField();
021
txtCenter.text =
"消失点:"
022
txtFocusLength =
new
TextField();
023
txtFocusLength.text =
"焦距:"
;
024
txtX.y = txtY.y = txtZ.y =
5
;
025
txtX.x = txtPosZ.x =
10
;
026
txtPosZ.y = txtX.y +
26
;
027
txtPosZ.x +=
40
;
028
txtY.x = txtX.x +
180
;
029
txtZ.x = txtY.x +
180
;
030
txtFieldOfView.x = txtPosZ.x +
160
;
031
txtFieldOfView.y = txtPosZ.y;
032
txtCenter.x = txtFieldOfView.x +
170
;
033
txtCenter.y = txtPosZ.y;
034
txtInfo =
new
TextField();
035
txtInfo.text=
""
;
036
txtFocusLength.x = txtX.x +
25
;
037
txtFocusLength.y = txtPosZ.y +
25
;
038
039
var
imgBD:BitmapData =
new
ImgSample();
040
var
img:Bitmap =
new
Bitmap(imgBD);
041
trace
(
"img.width="
,img.width,
",img.height="
,img.height);
042
043
var
imgSprite:Sprite =
new
Sprite();
044
img.x = - img.width /
2
;
045
img.y = - img.height /
2
;
046
imgSprite.addChild(img);
047
trace
(
"imgSprite.width="
,imgSprite.width,
",imgSprite.height="
,imgSprite.height);
048
049
var
containerSprite:Sprite =
new
Sprite();
050
containerSprite.addChild(imgSprite);
051
imgSprite.x = img.width /
2
;
052
imgSprite.y = img.height /
2
;
053
054
addChild(containerSprite);
055
trace
(
"containerSprite.width="
,containerSprite.width,
",containerSprite.height="
,containerSprite.height);
056
057
containerSprite.x = stage.stageWidth /
2
- containerSprite.width /
2
;
058
containerSprite.y = stage.stageHeight /
2
- containerSprite.height /
2
;
059
containerSprite.z =
50
;
060
061
var
silderX:SimpleSlider =
new
SimpleSlider(
0
,
360
,
0
);
062
silderX.x = txtX.x +
160
;
063
silderX.y = txtX.y +
7
;
064
silderX.rotation =
90
;
065
066
var
silderY:SimpleSlider =
new
SimpleSlider(
0
,
360
,
0
);
067
silderY.x = txtY.x +
160
;
068
silderY.y = silderX.y;
069
silderY.rotation =
90
;
070
071
var
silderZ:SimpleSlider =
new
SimpleSlider(
0
,
360
,
0
);
072
silderZ.x = txtZ.x +
160
;
073
silderZ.y = silderX.y;
074
silderZ.rotation =
90
;
075
076
var
silderPosZ:SimpleSlider =
new
SimpleSlider(-
200
,
200
,
50
);
077
silderPosZ.x = txtX.x +
160
;
078
silderPosZ.y = silderX.y +
25
;
079
silderPosZ.rotation =
90
;
080
081
var
silderFieldOfView:SimpleSlider =
new
SimpleSlider(
0.1
,
179.9
,
90
);
082
silderFieldOfView.x = silderPosZ.x +
180
;
083
silderFieldOfView.y = silderPosZ.y;
084
silderFieldOfView.rotation =
90
;
085
086
var
silderCenterPos:SimpleSlider =
new
SimpleSlider(
150
,
400
,
275
);
087
silderCenterPos.x = silderFieldOfView.x +
180
;
088
silderCenterPos.y = silderPosZ.y;
089
silderCenterPos.rotation =
90
;
090
091
var
silderFocusLength:SimpleSlider =
new
SimpleSlider(
100
,
500
,
300
);
092
silderFocusLength.x = silderPosZ.x ;
093
silderFocusLength.y = silderPosZ.y +
25
;
094
silderFocusLength.rotation =
90
;
095
096
addChild(txtX);
097
addChild(txtY);
098
addChild(txtZ);
099
addChild(txtPosZ);
100
addChild(txtFieldOfView);
101
addChild(txtInfo);
102
addChild(txtCenter);
103
addChild(txtFocusLength);
104
addChild(silderX);
105
addChild(silderY);
106
addChild(silderZ);
107
addChild(silderPosZ);
108
addChild(silderFieldOfView);
109
addChild(silderCenterPos);
110
addChild(silderFocusLength);
111
112
silderX.addEventListener(Event.CHANGE,silderXChangeHandler);
113
silderY.addEventListener(Event.CHANGE,silderYChangeHandler);
114
silderZ.addEventListener(Event.CHANGE,silderZChangeHandler);
115
silderPosZ.addEventListener(Event.CHANGE,silderPosZChangeHandler);
116
silderFieldOfView.addEventListener(Event.CHANGE,silderFieldOfViewChangeHandler);
117
silderFieldOfView.addEventListener(MouseEvent.MOUSE_UP,
function
(){isAngleChangeing =
false
});
118
silderCenterPos.addEventListener(Event.CHANGE,silderCenterPosChangeHandler);
119
silderFocusLength.addEventListener(Event.CHANGE,silderFocusLengthChangeHandler);
120
121
122
function
showTxtInfo(s:SimpleSlider){
123
txtInfo.text = s.value.toString().substr(
0
,
5
);
124
txtInfo.x = mouseX +
20
;
125
txtInfo.y = s.y +
5
;
126
}
127
128
function
silderXChangeHandler(e:Event):
void
{
129
imgSprite.rotationX = silderX.value;
130
showTxtInfo(silderX);
131
}
132
133
function
silderYChangeHandler(e:Event):
void
{
134
imgSprite.rotationY = silderY.value;
135
showTxtInfo(silderY);
136
}
137
138
function
silderZChangeHandler(e:Event):
void
{
139
imgSprite.rotationZ = silderZ.value;
140
showTxtInfo(silderZ);
141
}
142
143
function
silderPosZChangeHandler(e:Event):
void
{
144
containerSprite.z = silderPosZ.value;
145
showTxtInfo(silderPosZ);
146
}
147
148
149
function
silderFieldOfViewChangeHandler(e:Event):
void
{
150
doPerspectiveProjection();
151
showTxtInfo(silderFieldOfView);
152
isAngleChangeing =
true
;
153
}
154
155
function
silderCenterPosChangeHandler(e:Event):
void
{
156
doPerspectiveProjection();
157
showTxtInfo(silderCenterPos);
158
}
159
160
function
silderFocusLengthChangeHandler(e:Event):
void
{
161
doPerspectiveProjection();
162
showTxtInfo(silderFocusLength);
163
}
164
165
function
doPerspectiveProjection():
void
{
166
var
pp:PerspectiveProjection=
new
PerspectiveProjection();
167
pp.fieldOfView = silderFieldOfView.value;
168
if
(!isAngleChangeing){
169
pp.focalLength = silderFocusLength.value;
170
}
171
//trace(pp.focalLength);
172
pp.projectionCenter =
new
Point(silderCenterPos.value,silderCenterPos.value);
173
containerSprite.transform.perspectiveProjection = pp;
174
175
}
176
177
doPerspectiveProjection();
178
179
var
txtAuthor:TextField =
new
TextField();
180
txtAuthor.htmlText =
"<a href='http://yjmyzz.cnblogs.com/' target='_blank'>by 菩提树下的杨过</a>"
;
181
addChild(txtAuthor);
182
txtAuthor.y = txtFocusLength.y;
183
txtAuthor.x =
425
;
184
txtAuthor.autoSize = TextFieldAutoSize.LEFT;
稍加解释:
z坐标:即对象在z轴上的坐标,flash默认采用的是右手三维坐标,也就是说z值越大,物体越小
rotaionX,rotationY,rotationZ:即对象绕着x,y,z轴旋转的角度
PerspectiveProjection对象的三个属性:
1.focalLength 即焦距,使用效果上貌似焦距越大,物体也越大(?跟常规理解的不同),而且据官方帮助上讲:在透视转换过程中,将使用视野的角度和舞台的高宽比(舞台宽度除以舞台高度)来自动计算 focalLength
2.fieldOfView 即观察点的三维"视角"(0到180之间的值),怎么理解我还没想好,不过在使用效果上,如果当物体的z轴坐标不为0时,该值越大,物体的扭曲和形变越夸张,而且动态调整该值时focalLength值也会自动重新计算。(所以如果用代码写死了focalLength,不管如何调整fieldOfView都是看不到效果的)
3.projectionCenter:即3D透视中的消失点,当z轴坐标趋近于无限大时,物体越趋向于该点(消失)。
最后:上面的代码中暗藏了二个小技巧
1.为啥要先把图片放到imgSprite中,然后再将imgSprite又放到containerSprite中?
因为旋转时有一个旋转的中心点,而Flash默认这个中心就是对象的左顶点,即(0,0)位置,用二个sprite嵌套后,再配合坐标的设定,巧妙的将中心点正好移动到了图片中心,如下图:
2.如何用代码从库里取出一张图片?
如上图,关键在于导入图片时要指定“类”名,这样在代码中就可以用
1
var
imgBD:BitmapData =
new
ImgSample();
//从库中取出一张图片
2
var
img:Bitmap =
new
Bitmap(imgBD);
得到一个图片的Bigmap实例