flex两种方式画出一个动态时钟

flex在画图方面有着得天独厚的条件.它的前身是flash,让画图和动画变得更加容易.打败了java的applet.另外就算在windows编程

这一块.flex也要比java的swing更容易编写.网上看到有人写了个java的时钟,我觉得写的太艰难,于是用flex的两种方式简单实现了一下:


方式一

采用的是画布的方式实现,利用画布中的graphics调用基础的画图API.
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
					   xmlns:s="library://ns.adobe.com/flex/spark" 
					   xmlns:mx="library://ns.adobe.com/flex/mx"
					   creationComplete="init(event)">
 <fx:Script>
	 <![CDATA[
		 import mx.events.FlexEvent;
		 private var g:Graphics;
		 private var middlePointX:Number = 200;//中心点位置
		 private var middlePointY:Number = 200;
		 private var hourCursorLength:Number = 120;//各表针长度
		 private var minuteCursorLength:Number = 160;
		 private var secCursorLength:Number = 180;
		 private var hangle:Number = 0;//各表针相对于0点的角度
		 private var mangle:Number = 0;
		 private var sangle:Number = 0;
		 private var nowDate:Date;//当前时间
		 [Bindable]
		 private var hour:Number;//当前时,分,秒
		 [Bindable]
		 private var min:Number;
		 [Bindable]
		 private var sec:Number;
		 private var R:Number = 200;//表盘半径
		 
		 protected function init(event:FlexEvent):void
		 {
			 g = canvas.graphics;
			 var timer:Timer = new Timer(1000);//1秒刷新一次界面
			 timer.addEventListener(TimerEvent.TIMER,drawClock);
			 timer.start();
		 }
		 
		 private function drawClock(e:TimerEvent):void
		 {
			 g.clear();//先擦除
			 //画个表盘
			 for(var i:int = 0; i < 60; i++)//表盘上有60个点
			 {
				 var r:Number = 10;
				 if(i % 5 == 0)//每5个点是一个钟头
				 {
					 g.beginFill(0x00cc00,1);
					 r = 10;
				 }
				 else
				 {
					 g.beginFill(0xcc0000,1);
					 r = 5;
				 }
				 g.drawCircle(
				  middlePointX + R*Math.cos(Math.PI/2 - Math.PI/30*i),
				  middlePointY + R*Math.sin(Math.PI/2 - Math.PI/30*i),
				  r
				 );
				 g.endFill();
			 }
			 ///
			 nowDate = new Date;
			 hour = nowDate.getHours();
			 min = nowDate.getMinutes();
			 sec = nowDate.getSeconds();
			 //秒
			 sangle = Math.PI/2 - sec*Math.PI/30;//以90度为0点,逆时针旋转
			 drawCursor(1,0xff0000,1,secCursorLength,sangle);
			 //分
			 mangle = Math.PI/2 - (min + sec/60)*Math.PI/30;//分针的旋转角度是分和秒在分上的积累
			 drawCursor(3,0x00ff00,1,minuteCursorLength,mangle);
			 //时
			 hangle =  Math.PI/2 - (hour+min/60+sec/3600)*Math.PI/6;
			 drawCursor(6,0x0000ff,1,hourCursorLength,hangle);
		 }
		 
		 private function drawCursor(thickness:Number,color:uint,alpha:Number,cursorLen:Number,angle:Number):void
		 {
			 g.lineStyle(thickness,color,alpha);
			 g.moveTo(middlePointX,middlePointY);
			 g.lineTo(
				middlePointX + cursorLen*Math.cos(angle),
				middlePointY - cursorLen*Math.sin(angle)
			 );
		 }
	 ]]>
 </fx:Script>
	<mx:Canvas id="canvas" width="100%" height="100%" top="20" left="30"/>
</s:WindowedApplication>

方式二:

采用矢量图形的办法,这种方式在flex4之后才有.可以很方便的用现有的图形来组合出想要的效果
<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
					   xmlns:s="library://ns.adobe.com/flex/spark" 
					   xmlns:mx="library://ns.adobe.com/flex/mx"
					   backgroundColor="green" width="800" height="600"
					   creationComplete="init(event)">
	<fx:Script>
		<![CDATA[
			import mx.events.FlexEvent;
			
			private var increament:Number = 0;
			
			protected function init(event:FlexEvent):void
			{
				var timer:Timer = new Timer(1000);
				timer.addEventListener(TimerEvent.TIMER,function(e:TimerEvent):void
				{
					run("timer");
				});
				timer.start();  
			}
			
			private function run(mode:String = "clock"):void
			{
				var nowDate:Date = new Date;
				var hour:Number = mode == "clock" ? nowDate.hours : 0;
				var min:Number = mode == "clock" ? nowDate.minutes : 0;
				var sec:Number = mode == "clock" ? nowDate.seconds : ++increament;
				
				var sangle:Number = sec*6 - 90;
				var mangle:Number = (min + sec/60)*6 - 90 ;
				var hangle:Number =  (hour+min/60+sec/3600)*30 - 90;
				
				secNeedle.rotation = sangle;
				minNeedle.rotation = mangle;
				hourNeedle.rotation = hangle;
			}
			
		]]>
	</fx:Script>
	
	<s:Group top="30" left="50">
		
		<s:Ellipse width="300" height="300">
			<s:stroke>
				<s:SolidColorStroke color="black" weight="4"/>
			</s:stroke>
		</s:Ellipse>
		
		<s:Ellipse width="10" height="10" x="145" y="145">
			<s:stroke>
				<s:SolidColorStroke color="black" weight="2"/>
			</s:stroke>
			<s:fill>
				<s:SolidColor color="white"/>
			</s:fill>
		</s:Ellipse>
		
		<s:Line x="150" y="150" width="140" id="secNeedle" rotation="-90">
			<s:stroke>
				<s:SolidColorStroke color="red" weight="1"/>
			</s:stroke>
		</s:Line>
		
		<s:Line x="150" y="150" width="110" id="minNeedle" rotation="-90">
			<s:stroke>
				<s:SolidColorStroke color="yellow" weight="2"/>
			</s:stroke>
		</s:Line>
		
		<s:Line x="150" y="150" width="70" id="hourNeedle" rotation="-90">
			<s:stroke>
				<s:SolidColorStroke color="blue" weight="3"/>
			</s:stroke>
		</s:Line>
	</s:Group>
</s:WindowedApplication>

对第一种方式的正确理解:

<?xml version="1.0" encoding="utf-8"?>
<s:WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009" 
<span style="white-space:pre">					</span>   xmlns:s="library://ns.adobe.com/flex/spark" 
<span style="white-space:pre">					</span>   xmlns:mx="library://ns.adobe.com/flex/mx"
<span style="white-space:pre">					</span>   creationComplete="init(event)">
 <fx:Script>
<span style="white-space:pre">	</span> <![CDATA[
<span style="white-space:pre">		</span> import mx.events.FlexEvent;
<span style="white-space:pre">		</span> 
<span style="white-space:pre">		</span> private var g:Graphics;
<span style="white-space:pre">		</span> 
<span style="white-space:pre">		</span> private var middlePointX:Number = 200;//中心点位置
<span style="white-space:pre">		</span> private var middlePointY:Number = 200;
<span style="white-space:pre">		</span> 
<span style="white-space:pre">		</span> private var hourCursorLength:Number = 120;//各表针长度
<span style="white-space:pre">		</span> private var minuteCursorLength:Number = 160;
<span style="white-space:pre">		</span> private var secCursorLength:Number = 180;
<span style="white-space:pre">		</span> 
<span style="white-space:pre">		</span> private var R:Number = 200;//表盘半径
<span style="white-space:pre">		</span> 
<span style="white-space:pre">		</span> protected function init(event:FlexEvent):void
<span style="white-space:pre">		</span> {
<span style="white-space:pre">			</span> g = canvas.graphics;
<span style="white-space:pre">			</span> var timer:Timer = new Timer(1000);//1秒刷新一次界面
<span style="white-space:pre">			</span> timer.addEventListener(TimerEvent.TIMER,drawClock);
<span style="white-space:pre">			</span> timer.start();
<span style="white-space:pre">		</span> }
<span style="white-space:pre">		</span> 
<span style="white-space:pre">		</span> private function drawClock(e:TimerEvent):void
<span style="white-space:pre">		</span> {
<span style="white-space:pre">			</span> g.clear();//先擦除
<span style="white-space:pre">			</span> //画个表盘
<span style="white-space:pre">			</span> for(var i:int = 0; i < 60; i++)//表盘上有60个点
<span style="white-space:pre">			</span> {
<span style="white-space:pre">				</span> var r:Number = 10;
<span style="white-space:pre">				</span> if(i % 5 == 0)//每5个点是一个钟头
<span style="white-space:pre">				</span> {
<span style="white-space:pre">					</span> g.beginFill(0x00cc00,1);
<span style="white-space:pre">					</span> r = 10;
<span style="white-space:pre">				</span> }
<span style="white-space:pre">				</span> else
<span style="white-space:pre">				</span> {
<span style="white-space:pre">					</span> g.beginFill(0xcc0000,1);
<span style="white-space:pre">					</span> r = 5;
<span style="white-space:pre">				</span> }
<span style="white-space:pre">				</span> g.drawCircle(
//<span style="white-space:pre">					</span> 由于整好画满一个圆周,所以从哪里画并不重要,结果都是一致的
//<span style="white-space:pre">					</span> middlePointX + R*Math.cos(Math.PI/2 - Math.PI/30*i),
//<span style="white-space:pre">					</span> middlePointY + R*Math.sin(Math.PI/2 - Math.PI/30*i),
<span style="white-space:pre">				</span>  middlePointX + R*Math.cos(Math.PI/30*i),
<span style="white-space:pre">				</span>  middlePointY + R*Math.sin(Math.PI/30*i),
<span style="white-space:pre">				</span>  r
<span style="white-space:pre">				</span> );
<span style="white-space:pre">				</span> g.endFill();
<span style="white-space:pre">			</span> }
<span style="white-space:pre">		</span>
<span style="white-space:pre">			</span> var nowDate:Date = new Date;
<span style="white-space:pre">			</span> var hour:Number = nowDate.getHours();
<span style="white-space:pre">			</span> var min:Number = nowDate.getMinutes();
<span style="white-space:pre">			</span> var sec:Number = nowDate.getSeconds();
<span style="white-space:pre">			</span> 
<span style="white-space:pre">			</span> //在PC坐标中角度递增是顺时针旋转,与笛卡尔坐标相反
<span style="white-space:pre">			</span> //另外0刻所在的角度是90度,所以要减去90度
<span style="white-space:pre">			</span> var sangle:Number = sec*Math.PI/30 - Math.PI/2 ;
<span style="white-space:pre">			</span> drawCursor(1,0xff0000,1,secCursorLength,sangle);
<span style="white-space:pre">			</span> var mangle:Number = (min + sec/60)*Math.PI/30 - Math.PI/2 ;
<span style="white-space:pre">			</span> drawCursor(3,0x00ff00,1,minuteCursorLength,mangle);
<span style="white-space:pre">			</span> var hangle:Number = (hour + min/60 + sec/3600)*Math.PI/6 - Math.PI/2 ;
<span style="white-space:pre">			</span> drawCursor(6,0x0000ff,1,hourCursorLength,hangle);
<span style="white-space:pre">		</span> }
<span style="white-space:pre">		</span> 
<span style="white-space:pre">		</span> private function drawCursor(thickness:Number,color:uint,alpha:Number,cursorLen:Number,angle:Number):void
<span style="white-space:pre">		</span> {
<span style="white-space:pre">			</span> g.lineStyle(thickness,color,alpha);
<span style="white-space:pre">			</span> g.moveTo(middlePointX,middlePointY);
<span style="white-space:pre">			</span> g.lineTo(
<span style="white-space:pre">				</span> middlePointX + cursorLen*Math.cos(angle),
<span style="white-space:pre">				</span> middlePointY + cursorLen*Math.sin(angle)
<span style="white-space:pre">			</span> );
<span style="white-space:pre">		</span> }
<span style="white-space:pre">	</span> ]]>
 </fx:Script>
<span style="white-space:pre">	</span><mx:Canvas id="canvas" width="100%" height="100%" top="20" left="30"/>
</s:WindowedApplication>

======================================================================================================================

我觉得第一种方式代码写分离性不如第二种高.第一种是要进行整体的考虑,每次都要对每个指针进行擦除和绘制.而第二种布局好了固定不变的
图形安排后.剩下的任务就是编写指针的运动逻辑.这样便于代码的阅读和维护.


结尾补充:

计算机坐标系是笛卡尔坐标系y轴区间对x轴的镜像.或者说相当于笛卡尔坐标系沿着x轴翻转180度.
笛卡尔坐标系中的顺时针,在PC坐标系看来是顺时针的,反之亦然.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值