My Clock
Windows phone 中 自制 小Clock 如图:
基本思路: 首先在界面绘制表盘,由一个圆和一些刻度 当然还有clock中间的中心点了
绘制圆和中心点都很简单,主要是刻度的绘制 如图红色为刻度
我以12点为基准线, 圆心为中心点centerpoint, 顺时针偏离角为a (如1点偏离角为30度)
则刻度的起始点就是(centerpoint.x+r*sin(a),centerpoint.y-r*cos(a)) ,为了计算刻度的终点的坐标,假设有一个稍微小一点的同心圆,同理计算出一个坐标作为终点坐标,
如图就得到刻度的起始坐标,然后绘制一条线即可。
表针的绘制:表针使用小矩形来表示,使用RenderTransform来对矩形进行控制,先绘制一个小矩形让其居中,然后让其向上移动矩形高度的一半就能使矩形像表针的样子了,设置其变换中心点,并设置其倾斜角度,当时间改变的时候通过改变其倾斜角度就能让Clock走起来了
根据时间改变三个指针的角度:这里定义了updateClock方法实现,很简单就是简单计算下各个指针应该对应的角度,如秒针就是当前second*6即可,然后根据角度设置指针的Rotation角度即可让指针倾斜到指定的角度了。
简单实现如下:
首先定义几个变量:
//ContentPanel中心点 Point centerPoint; //三个表针 Rectangle secondPointer = new Rectangle(); Rectangle minutePointer = new Rectangle(); Rectangle hourPointer = new Rectangle(); DispatcherTimer timer = new DispatcherTimer();
然后创建表盘:createClockPanel
View Code
//创建Clock面板,参数radius为clock直径,color 为表盘的颜色
private void createClockPanel(double radius,Color strockColor,double strokeThickness)
{
double centerRadius = radius * 0.08;
double contentPanelWidth = ContentPanel.ActualWidth;
double contentPanelHeight = ContentPanel.ActualHeight;
//获取ContentPanel中心点
centerPoint = new Point(contentPanelWidth / 2, contentPanelHeight / 2);
//定义clock边缘
Ellipse clockEllipse = new Ellipse();
clockEllipse.Width = radius*2;
clockEllipse.Height = radius*2;
clockEllipse.HorizontalAlignment = HorizontalAlignment.Center;
clockEllipse.VerticalAlignment = VerticalAlignment.Center;
clockEllipse.Stroke = new SolidColorBrush(strockColor);
clockEllipse.StrokeThickness = strokeThickness;
//定义Clock中心
Ellipse clockCenter = new Ellipse();
clockCenter.Width = centerRadius;
clockCenter.Height = centerRadius;
clockCenter.HorizontalAlignment = HorizontalAlignment.Center;
clockCenter.VerticalAlignment = VerticalAlignment.Center;
clockCenter.Fill = new SolidColorBrush(Color.FromArgb(255,0,255,0));
//绘制时间刻度
////获取12点处的刻度坐标
//Point twelvePoint = new Point(centerPoint.X,centerPoint.Y-radius);
//记录各点坐标
//为了绘制刻度,假设有一个比现在的边缘小10%的圆,然后找到各个角度对应的刻度 的起始坐标
Point startpoint=new Point();
Point endpoint = new Point();
for (int angle = 0; angle <=360; angle += 6)
{
//正余弦函数的参数参数 a类型:System.Double 以弧度计量的角度,所以必须先将角度转换成弧度
//注:弧长等于圆半径长的弧所对的圆心角为1弧度
double circulrAngle = Math.PI * angle / 180;
startpoint.X = centerPoint.X + radius * Math.Sin(circulrAngle);
startpoint.Y = centerPoint.Y - radius * Math.Cos(circulrAngle);
Line line1 = new Line();
double rate = 0.95;
//整点高亮显示
if (angle % 90 == 0)
{
line1.StrokeThickness = 4;
rate = 0.9;
}
else if (angle % 30 == 0 && angle % 90 != 0)
{
line1.StrokeThickness = 2;
rate = 0.92;
}
endpoint.X = centerPoint.X + (radius * rate) * Math.Sin(circulrAngle);
endpoint.Y = centerPoint.Y - (radius * rate) * Math.Cos(circulrAngle);
line1.X1 = startpoint.X;
line1.Y1 = startpoint.Y;
line1.X2 = endpoint.X;
line1.Y2 = endpoint.Y;
line1.Stroke = new SolidColorBrush(strockColor);
//绘制刻度
ContentPanel.Children.Add(line1);
}
//将表盘添加到ContentPanel中
ContentPanel.Children.Add(clockEllipse);
ContentPanel.Children.Add(clockCenter);
}
创建三个表针 :
View Code
//创建三个表针 radius 表示表盘半径
private void createClockPointer(double radius,Color pointerColor)
{
//秒针
secondPointer.Width = 2;
secondPointer.Height = radius;
secondPointer.Name = "secondPointer";
secondPointer.Fill = new SolidColorBrush(pointerColor);
CompositeTransform secondTransform = new CompositeTransform();
secondTransform.TranslateY = -secondPointer.Height / 2.5;
//这里设置秒针中心点 ,貌似有点不准确----------待解决
secondTransform.CenterX = 0;
secondTransform.CenterY = secondPointer.Height / 2.5 + secondPointer.Height/2;
secondTransform.Rotation = secondPointer.Width/2;
secondPointer.RenderTransform = secondTransform;
ContentPanel.Children.Add(secondPointer);
//分针
minutePointer.Width = 4;
minutePointer.Height = radius * 0.8;
minutePointer.Name = "minutePointer";
minutePointer.Fill = new SolidColorBrush(pointerColor);
CompositeTransform minuteTransform = new CompositeTransform();
minuteTransform.TranslateY = -minutePointer.Height / 2;
minuteTransform.CenterX = minutePointer.Width/2;
minuteTransform.CenterY = minutePointer.Height;
minutePointer.RenderTransform = minuteTransform;
ContentPanel.Children.Add(minutePointer);
//时针
hourPointer.Width = 6;
hourPointer.Height = radius * 0.7;
hourPointer.Name = "hourPointer";
hourPointer.Fill = new SolidColorBrush(pointerColor);
CompositeTransform hourTransform = new CompositeTransform();
hourTransform.TranslateY = -hourPointer.Height / 2.5;
hourTransform.CenterX = hourPointer.Width/2;
hourTransform.CenterY = hourPointer.Height/2.5+hourPointer.Height/2;
hourPointer.RenderTransform = hourTransform;
ContentPanel.Children.Add(hourPointer);
}
根据当前时间计算各个指针角度:
private void updateClock() { DateTime dt = DateTime.Now; double angle; angle=dt.Second*6; resetPointer(secondPointer, angle); angle = dt.Minute * 6 + angle / 60; resetPointer(minutePointer,angle); angle = (dt.Hour%12) * 30 + angle /60; resetPointer(hourPointer,angle); }
resetPointer方法:
//根据对应的角度重新设置pointer角度 private void resetPointer(Rectangle rect,double angle) { CompositeTransform transform = rect.RenderTransform as CompositeTransform; transform.Rotation = angle; }
当然在构造函数中需要先设置定时器并启动
timer.Interval = TimeSpan.FromSeconds(1); timer.Tick += new EventHandler(timer_Tick); timer.Start();
tick方法:
void timer_Tick(object sender, EventArgs e) { try { updateClock(); } catch(Exception ex) { MessageBox.Show(ex.ToString()); } }
然后在页面加载的时候调用reflush方法就可以了
为了当屏幕方向改变时也能正常显示,需要在ContentPanel的 SizeChanged方法中
执行如下操作:
timer.Stop(); reflush(); timer.Start();
这样就OK了。
LandScape下显示如下