我正在研究一个时钟项目,我知道如何实现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小时制时。它不起作用。每当我运行这个项目时,时钟显示错误的时间。
有谁能告诉我我做错了什么。非常感谢提前
答案 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())
}
}