Flash/Flex学习笔记(18):画线及三角函数的基本使用
Sprite有一个graphics可以用来绘制基本图形,比如我们要画下面这个图形:

对应的AS3代码为:
01 package {
02 import flash.display.Sprite;
03
04 public class Arrow extends Sprite {
05 public function Arrow():void {
06 init();
07 }
08 private function init():void{
09 graphics.lineStyle(1,0,1);
10 graphics.beginFill(0xffff99);
11 graphics.drawCircle(0,0,2);//中心点
12 graphics.moveTo(0,50);
13 graphics.lineTo(100,50);
14 graphics.lineTo(100,0);
15 graphics.lineTo(150,75);
16 graphics.lineTo(100,150);
17 graphics.lineTo(100,100);
18 graphics.lineTo(0,100);
19 graphics.lineTo(0,50);
20 graphics.endFill();
21 }
22 }
23 }
把它加到舞台上,并自动跟着鼠标转动(下列代码写在第一帧):
01 var _arrow:Arrow = new Arrow();
02 addChild(_arrow);
03 _arrow.x=stage.stageWidth/2-50;
04 _arrow.y=stage.stageHeight/2-75;
05
06 this.addEventListener(Event.ENTER_FRAME,EnterFrameHandler);
07
08 function EnterFrameHandler(e:Event):void {
09 var dx:Number=mouseX-_arrow.x;
10 var dy:Number=mouseY-_arrow.y;
11 //trace("dy=" + dy + ",dx=" + dx);
12 var angle:Number=Math.atan2(dy,dx);
13 _arrow.rotation=angle*180/Math.PI;
14 }
这里用到了反正切函数,其原理示意图如下:

即以鼠标所在点与Arrow图形中心点为参考,构建一个三角形,利用对边比邻边得到正切,然后利用反正切求出角度,最终让图形旋转该角度,下面是效果:
但是好象有点问题,相信您也看出来了,因为我们绘制图形时,默认是以坐标原点为中心,而非图形中心点为中心,所以在跟随鼠标旋转时,总感觉有些错位,没关系,只要调整一下Arrow.cs即可 
01 package {
02 import flash.display.Sprite;
03
04 public class Arrow extends Sprite {
05 public function Arrow():void {
06 init();
07 }
08 private function init():void{
09 graphics.lineStyle(1,0,1);
10 graphics.beginFill(0xffff99);
11 graphics.drawCircle(0,0,2);//中心点
12 graphics.moveTo(-75,-25);
13 graphics.lineTo(25,-25);
14 graphics.lineTo(25,-75);
15 graphics.lineTo(75,0);
16 graphics.lineTo(25,75);
17 graphics.lineTo(25,25);
18 graphics.lineTo(-75,25);
19 graphics.lineTo(-75,-25);
20 graphics.endFill();
21 }
22 }
23 }
另一个很有用的三角函数就是正弦Sin函数--对边比斜边
当Sin函数的角度参数从0度变化到360度时,正弦函数的值会在1到-1之间来回摆动,如果在动画中需要来回振荡的情况,正弦函数就派上用场了
01 package{
02 import flash.display.Sprite;
03
04 //小球 类
05 public class Ball extends Sprite{
06
07 private var radius:Number ;//半径
08 private var color:uint;//颜色
09
10 public function Ball(r:Number=50,c:uint=0xff0000){
11 this.radius = r;
12 this.color = c;
13 init();
14 }
15
16 private function init():void{
17 graphics.beginFill(color);
18 graphics.drawCircle(0,0,radius);
19 graphics.endFill();
20 }
21 }
22 }
这里我们先定义一个基本的小球类Ball,在接下来的动画里,我们让小球沿正弦轨迹运行,同时另一个小球模拟“心跳”运动(即改变大小)
01 var angle:Number = 0;
02
03 //参数常量
04 const Y_SPEED = 0.1; //y轴移动速度
05 const X_SPEED = 1; //x轴移动速度
06 const AMPLITUDE = 50.0; //最大振幅
07 const X_START = 0; //x轴的起始点
08
09 //变量
10 var ySpeed:Number = Y_SPEED;
11 var xSpeed:Number = X_SPEED;
12 var amplitude:Number = AMPLITUDE;
13
14 var b:Ball = new Ball(5,0xff0000);
15 addChild(b);
16 b.x = X_START;
17
18 var heart:Ball = new Ball(50,0x0000ff);
19 addChild(heart);
20 heart.x = stage.stageWidth/2;
21 heart.y = stage.stageHeight/2;
22 heart.alpha = 0.3;
23
24 addEventListener(Event.ENTER_FRAME,EnterFrameHandler);
25
26 function EnterFrameHandler(e:Event){
27 b.y = stage.stageHeight/2 + Math.sin(angle) * amplitude;
28 angle += ySpeed;
29 b.x += xSpeed;
30
31 heart.scaleX = heart.scaleY = 1 + Math.sin(angle) * 0.5;
32
33 graphics.lineStyle(1,0xefefef,1);
34 graphics.lineTo(b.x,b.y);
35
36
37 //x,y,振幅 逐渐加大
38 xSpeed += 0.08;
39 ySpeed += 0.003;
40 amplitude += 1;
41
42 if (b.x > stage.stageWidth + b.width){
43 //超出舞台后,还原参数
44 b.x = X_START;
45 xSpeed = X_SPEED;
46 ySpeed = Y_SPEED;
47 amplitude = AMPLITUDE;
48 }
49
50 }
甚至还可以同时把正弦函数应用到多个属性:
01 //参数常量
02 const Y_SPEED = 0.07; //y轴变化速度
03 const X_SPEED = 0.10; //x轴变化速度
04 const AMPLITUDE = 150.0; //最大振幅
05 const X_START = stage.stageWidth/2; //x轴的起始点
06 const Y_START = stage.stageHeight/2; //y轴的起始点
07
08 //变量
09 var ySpeed:Number = Y_SPEED;
10 var xSpeed:Number = X_SPEED;
11 var amplitude:Number = AMPLITUDE;
12 var angleX = 0;
13 var angleY = 0;
14
15 var b:Ball = new Ball(5,0xff0000);
16 addChild(b);
17
18 b.x = X_START;
19 b.y = Y_START;
20
21 graphics.moveTo(b.x,b.y);
22
23 addEventListener(Event.ENTER_FRAME,EnterFrameHandler);
24
25 function EnterFrameHandler(e:Event){
26
27 b.y = Y_START + Math.sin(angleY) * amplitude;
28 b.x = X_START + Math.sin(angleX) * amplitude;
29
30 angleX += xSpeed;
31 angleY += ySpeed;
32
33 //angleX += Math.random()/10;
34 //angleY += Math.random()/5;
35
36 graphics.lineStyle(1,0xefefef,1);
37 graphics.lineTo(b.x,b.y);
38 }
如果把代码中的二行注释启用,即让x,y的变化速度改成随机,结果可能更有趣:
浙公网安备 33010602011771号