zoukankan      html  css  js  c++  java
  • 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下显示如下

  • 相关阅读:
    计数和查找
    遍历
    top小火箭
    leetcode 字符串中的第一个唯一字符
    leetcode 颠倒整数
    leetcode 反转字符串
    leetcode 有效的数独
    leetcode 两数之和
    leetcode 移动零
    leetcode 加一
  • 原文地址:https://www.cnblogs.com/yinghuochong/p/2171312.html
Copyright © 2011-2022 走看看