如何旋转24小时制的时钟指针?

时间:2013-02-12 17:35:34

标签: iphone ios objective-c xcode

我正在研究一个时钟项目,我知道如何实现12小时时钟的手(小时,分钟,秒)旋转。我使用的代码如下:

CGFloat secAngle,minAngle,hourAngle;

NSDateComponents *dateComponents = [[NSCalendar currentCalendar] components:(NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate:[NSDate date]];
NSInteger seconds = [dateComponents second];
NSInteger minutes = [dateComponents minute];
NSInteger hours = [dateComponents hour];



if (timeFormat == 12)//12 hour clock
{

    if (hours > 12) hours -=12; //PM

     secAngle = Degrees2Radians(seconds/60.0*360);
     minAngle = Degrees2Radians(minutes/60.0*360);

     hourAngle = Degrees2Radians(hours/12.0*360) + minAngle/12.0;

    //secHand.transform = CATransform3DMakeRotation (secAngle+M_PI, 0, 0, 1);
    minHand.transform = CATransform3DMakeRotation (minAngle+M_PI, 0, 0, 1);
    hourHand.transform = CATransform3DMakeRotation (hourAngle+M_PI, 0, 0, 1);
}
else //24 hour clock
{

    secAngle = Degrees2Radians(seconds/60.0*360);
    minAngle = Degrees2Radians(minutes/60.0*360);
    hourAngle = (30 * hours + minutes / 2) /2;

    //secHand.transform = CATransform3DMakeRotation(secAngle * M_PI / 180,0,0,1);
    minHand.transform = CATransform3DMakeRotation(minAngle * M_PI ,0,0,1);
    hourHand.transform = CATransform3DMakeRotation(hourAngle * M_PI,0,0,1);


}

但是当我尝试实施24小时制时。它不起作用。每当我运行这个项目时,时钟显示错误的时间。

有谁能告诉我我做错了什么。非常感谢提前

2 个答案:

答案 0 :(得分:4)

我是这样做的 - 我使用面部中心和角度来计算手的端点的x,y位置,绘图很简单。这是一个完整的钟面课程。它是UIView的子类。每秒设置它的时间属性,它就像一个魅力......

//
//  ClockFace.h
//

#import <UIKit/UIKit.h>

@interface ClockFace : UIView

@property (strong,nonatomic) NSDate *time;

@end


//  ClockFace.m

#import "ClockFace.h"

@interface ClockFace ()

@property(assign,nonatomic) CGPoint boundsCenter;
@property(assign,nonatomic) NSInteger seconds;
@property(assign,nonatomic) NSInteger minutes;
@property(assign,nonatomic) NSInteger hours;

@end

@implementation ClockFace

@synthesize time=_time;
@synthesize boundsCenter=_boundsCenter;

- (id)initWithCoder:(NSCoder *)aDecoder {

    self = [super initWithCoder:aDecoder];
    if (self) {
        _boundsCenter = CGPointMake(self.bounds.size.width/2.0, self.bounds.size.height/2.0);
    }
    return self;
}

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        _boundsCenter = CGPointMake(self.bounds.size.width/2.0, self.bounds.size.height/2.0);
    }
    return self;
}

- (CGPoint)secondsHandPosition {

    float secondsAsRadians = (float)self.seconds / 60.0 * 2.0 * M_PI - M_PI_2;
    float handRadius = self.frame.size.width / 2.4;
    return CGPointMake(handRadius*cosf(secondsAsRadians)+self.boundsCenter.x, handRadius*sinf(secondsAsRadians)+self.boundsCenter.y);
}

- (CGPoint)minutesHandPosition {

    float minutesAsRadians = (float)self.minutes / 60.0 * 2.0 * M_PI - M_PI_2;
    float handRadius = self.frame.size.width / 2.2;
    return CGPointMake(handRadius*cosf(minutesAsRadians)+self.boundsCenter.x, handRadius*sinf(minutesAsRadians)+self.boundsCenter.y);
}

- (CGPoint)hoursHandPosition {

    float hoursAsRadians = (float)self.hours / 12.0 * 2.0 * M_PI - M_PI_2;
    float handRadius = self.frame.size.width / 3.8;
    return CGPointMake(handRadius*cosf(hoursAsRadians)+self.boundsCenter.x, handRadius*sinf(hoursAsRadians)+self.boundsCenter.y);
}


// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();

    CGFloat zClear[4] = {1.0,1.0,1.0,0.0};
    CGContextSetFillColor(context, zClear); 
    CGContextFillRect(context, rect);

    CGRect face = CGRectInset(rect, 1.0, 1.0);
    CGContextSetLineWidth(context, 1.0);
    CGContextAddEllipseInRect(context, face);
    CGContextStrokePath(context);

    CGRect center = CGRectMake(self.boundsCenter.x-2.0, self.boundsCenter.y-2.0, 4.0, 4.0);
    CGContextAddEllipseInRect(context, center);
    CGContextStrokePath(context);

    CGFloat red[4] = {1.0f, 0.0f, 0.0f, 1.0f};
    CGPoint secondsHandPosition = [self secondsHandPosition];

    CGContextSetStrokeColor(context, red);
    CGContextBeginPath(context);
    CGContextMoveToPoint(context, self.boundsCenter.x, self.boundsCenter.y);
    CGContextAddLineToPoint(context, secondsHandPosition.x, secondsHandPosition.y);
    CGContextStrokePath(context);

    CGFloat black[4] = {0.0f, 0.0f, 0.0f, 1.0f};
    CGPoint minutesHandPosition = [self minutesHandPosition];

    CGContextSetStrokeColor(context, black);
    CGContextBeginPath(context);
    CGContextMoveToPoint(context, self.boundsCenter.x, self.boundsCenter.y);
    CGContextAddLineToPoint(context, minutesHandPosition.x, minutesHandPosition.y);
    CGContextStrokePath(context);

    CGPoint hoursHandPosition = [self hoursHandPosition];

    CGContextSetStrokeColor(context, black);
    CGContextBeginPath(context);
    CGContextMoveToPoint(context, self.boundsCenter.x, self.boundsCenter.y);
    CGContextAddLineToPoint(context, hoursHandPosition.x, hoursHandPosition.y);
    CGContextStrokePath(context);
}

- (void)setTime:(NSDate *)time {

    _time = time;

    static NSCalendar *gregorian;

    if (!gregorian) gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    NSDateComponents *weekdayComponents =
    [gregorian components:(NSDayCalendarUnit | NSWeekdayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit) fromDate:time];

    self.hours = [weekdayComponents hour];
    if (self.hours > 12) self.hours -= 12;
    self.minutes = [weekdayComponents minute];
    self.seconds = [weekdayComponents second];

    [self setNeedsDisplay];
}


@end

要在视图控制器中使用它,请创建一个属性:

#import "ClockFace.h"

// ...

@property(strong, non atomic) ClockFace *clockFace;

在视图中加载(或在故事板中,如果您知道如何添加自定义视图):

self.clockFace = [[ClockFace alloc] initWithFrame:CGRectMake(10, 10, 300, 300)];

每当您想要运行时钟时,请设置一个计时器:

[NSTimer scheduledTimerWithTimeInterval:1.0
    target:self
    selector:@selector(timerFired:)
    userInfo:nil
    repeats:NO];

当计时器触发时,告诉时钟它的时间:

- (void)timerFired:(NSTimer *)timer {

    self.clockFace.time = [NSDate date];
}

答案 1 :(得分:0)

@danh答案已更新为Swift。

时钟面孔:

class ClockFace: UIView {

    var calendar: NSCalendar!
    var time: Date!
    private var figureCenter: CGPoint = .zero
    private var faceRadius: CGFloat = 0
    private var seconds: Int = 0
    private var minutes: Int = 0
    private var hours: Int = 0
    private let angleOffset: CGFloat = -.pi / 2 // an offset to make 0 at "12:00" instead of "3:00"

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        figureCenter = CGPoint(x: bounds.midX, y: bounds.midY)
        faceRadius = frame.size.width / 2.0
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        // Initialization code
        figureCenter = CGPoint(x: bounds.midX, y: bounds.midY)
        faceRadius = frame.size.width / 2.0
    }

    func secondsHandPosition() -> CGPoint {
        let radiansPerSecond = (CGFloat.pi * 2) / 60
        let secondsAsRadians: CGFloat = angleOffset + (CGFloat(seconds) * radiansPerSecond )
        let handRadius: CGFloat = faceRadius / 1.1
        return CGPoint(x: CGFloat(handRadius * cos(secondsAsRadians) + figureCenter.x), y: CGFloat(handRadius * sin(secondsAsRadians) + figureCenter.y))
    }

    func minutesHandPosition() -> CGPoint {
        let radiansPerMinute = (CGFloat.pi * 2) / 60
        let minutesAsRadians: CGFloat = angleOffset + (CGFloat(minutes) * radiansPerMinute)
        let handRadius: CGFloat = faceRadius / 1.25
        return CGPoint(x: CGFloat(handRadius * cos(minutesAsRadians) + figureCenter.x), y: CGFloat(handRadius * sin(minutesAsRadians) + figureCenter.y))
    }

    func hoursHandPosition() -> CGPoint {
        let radiansPerHour = (CGFloat.pi * 2) / 12
        let hoursAsRadians: CGFloat = angleOffset + (CGFloat(hours) * radiansPerHour)
        let handRadius: CGFloat = faceRadius / 1.8
        return CGPoint(x: CGFloat(handRadius * cos(hoursAsRadians) + figureCenter.x), y: CGFloat(handRadius * sin(hoursAsRadians) + figureCenter.y))
    }

    override func draw(_ rect: CGRect) {
        let context = UIGraphicsGetCurrentContext()!
        context.setFillColor(UIColor.white.cgColor)
        context.fill(rect)

        for count in 0...60 {
            let tickRadius = faceRadius / ((count % 5 == 0) ? 1.20 : 1.15)
            let lineWidth = (count % 5) == 0 ? 3 : 2
            let tickAngle = CGFloat(count) * ((CGFloat.pi * 2) / 60)
            context.beginPath()
            context.move(to: CGPoint(x: CGFloat(faceRadius * cos(tickAngle) + figureCenter.x), y: CGFloat(faceRadius * sin(tickAngle) + figureCenter.y)))
            context.addLine(to: CGPoint(x: CGFloat(tickRadius * cos(tickAngle) + figureCenter.x), y: CGFloat(tickRadius * sin(tickAngle) + figureCenter.y)))

            context.setStrokeColor(UIColor.black.cgColor)
            context.setLineWidth(CGFloat(lineWidth))
            context.strokePath()
        }

        let lineWidth: CGFloat = 5.0
        let face = rect.insetBy(dx: lineWidth / 2, dy: lineWidth / 2)
        context.setLineWidth(lineWidth)
        context.addEllipse(in: face)
        context.strokePath()

        let secondsHandPosition = self.secondsHandPosition()

        context.beginPath()
        context.move(to: figureCenter)
        context.addLine(to: secondsHandPosition)
        context.setLineWidth(1)
        context.setStrokeColor(UIColor.red.cgColor)
        context.strokePath()

        let minutesHandPosition = self.minutesHandPosition()

        context.beginPath()
        context.move(to: figureCenter)
        context.addLine(to: minutesHandPosition)
        context.setLineWidth(3)
        context.setStrokeColor(UIColor.black.cgColor)
        context.strokePath()

        let hoursHandPosition = self.hoursHandPosition()

        context.beginPath()
        context.move(to: figureCenter)
        context.addLine(to: hoursHandPosition)
        context.setLineWidth(5)
        context.setStrokeColor(UIColor.black.cgColor)
        context.strokePath()

        let center = CGRect(x: figureCenter.x - 5.0, y: figureCenter.y - 5.0, width: 10.0, height: 10.0)
        context.addEllipse(in: center)
        context.setFillColor(UIColor.black.cgColor)
        context.fillPath()
        context.strokePath()
    }

    func setTime(_ time: Date?) {

        self.time = time
        var weekdayComponents: DateComponents!

        if calendar == nil {
            calendar = NSCalendar(identifier: NSCalendar.Identifier.gregorian)
        }

        if let time = time {
            weekdayComponents = calendar.components([.day, .weekday, .hour, .minute, .second], from: time)
        }

        if weekdayComponents != nil {
            hours = weekdayComponents.hour!
            minutes = weekdayComponents.minute!
            seconds = weekdayComponents.second!

            hours = (hours + (12 - 1)) % 12 + 1;
        }

        self.setNeedsDisplay()
    }
}

视图控制器:

class ViewController: UIViewController {

    @IBOutlet weak var clockView: ClockFace!

    override func viewDidLoad() {
        super.viewDidLoad()

        Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(timerFired(_:)), userInfo: nil, repeats: true)
    }

    @objc func timerFired(_ timer: Timer?) {
        clockView.setTime(Date())
    }
}