您的位置:首页 > 其它

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

2015-09-07 11:33 246 查看
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坐标系看来是顺时针的,反之亦然.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: