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下显示如下

原文地址:https://www.cnblogs.com/yinghuochong/p/2171312.html