Object angle based on current time

回眸只為那壹抹淺笑 提交于 2019-12-04 09:50:00

问题


Listen carefully, because this is specific. I'm trying to make an analog clock in iPhone SDK. I've been trying to accomplish this for three weeks now, I've asked five questions on SO, and I still have found almost NOTHING. I need help. I want to have a clock hand that simply rotates depending on the current time. I'm mostly focused on the second hand right now because it seems like the easiest.

I don't necessarily care what is used to rotate the clock hand (CALayers, UIView, etc.), just as long as it does what it needs to do. Any sort of help is greatly, greatly appreciated. Thanks.

EDIT: I also need the hands to be images. Hopefully that isn't too much. :(


回答1:


You asked kind of the same question and I said that Layers is much better... well this time I have written the hole program in a record time than less than three weeks ;). If you want to use images then get your images and set them inside initWithFrame:

Interface: ClockView.h

#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
@interface ClockView : UIView {
    CALayer *containerLayer;
    CALayer *hourHand;
    CALayer *minHand;
    CALayer *secHand;
    NSTimer *timer;
}
- (void) start;
- (void) stop;
@end

Implementation: ClockView.m

#import "ClockView.h"

@implementation ClockView

float Degrees2Radians(float degrees) { return degrees * M_PI / 180; }

- (void) start{
    timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self 
                                                    selector:@selector(updateClock) 
                                                    userInfo:nil repeats:YES];
}
- (void) stop{
    [timer invalidate];
    timer = nil;
}

- (void) updateClock{
    NSDateComponents *dateComponents = [[NSCalendar currentCalendar] components:(NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit) 
                                                                       fromDate:[NSDate date]];
    NSInteger seconds = [dateComponents second];
    NSInteger minutes = [dateComponents minute];
    NSInteger hours = [dateComponents hour];
    //correction of inverted clock
    seconds += 30; seconds %=60;
    minutes += 30; minutes %=60;
    hours += 6; hours %=12;

    hourHand.transform = CATransform3DMakeRotation (Degrees2Radians(hours*360/12), 0, 0, 1);
    minHand.transform = CATransform3DMakeRotation (Degrees2Radians(minutes*360/60), 0, 0, 1);
    secHand.transform = CATransform3DMakeRotation (Degrees2Radians(seconds*360/60), 0, 0, 1);
}
- (void) layoutSubviews{
    [super layoutSubviews];

    containerLayer.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);

    float length = MIN(self.frame.size.width, self.frame.size.height)/2;
    CGPoint c = CGPointMake(self.frame.size.width/2, self.frame.size.height/2);
    hourHand.position = minHand.position = secHand.position = c;

    hourHand.bounds = CGRectMake(0,0,10,length*0.5);
    minHand.bounds = CGRectMake(0,0,8,length*0.8);
    secHand.bounds = CGRectMake(0,0,4,length);

    hourHand.anchorPoint = CGPointMake(0.5,0.0);
    minHand.anchorPoint = CGPointMake(0.5,0.0);
    secHand.anchorPoint = CGPointMake(0.5,0.0);

}

- (id)initWithFrame:(CGRect)frame {

    self = [super initWithFrame:frame];
    if (self) {

        containerLayer = [[CALayer layer] retain];

        hourHand = [[CALayer layer] retain];
        minHand = [[CALayer layer] retain];
        secHand = [[CALayer layer] retain];

        //paint your hands: simple colors
        hourHand.backgroundColor = [UIColor blackColor].CGColor;
        hourHand.cornerRadius = 3;
        minHand.backgroundColor = [UIColor grayColor].CGColor;
        secHand.backgroundColor = [UIColor whiteColor].CGColor;
        secHand.borderWidth = 1.0;
        secHand.borderColor = [UIColor grayColor].CGColor;

        //put images
        //hourHand.contents = (id)[UIImage imageNamed:@"hour.png"].CGImage;
        //minHand.contents = (id)[UIImage imageNamed:@"min.png"].CGImage;
        //secHand.contents = (id)[UIImage imageNamed:@"sec.png"].CGImage;

        [containerLayer addSublayer:hourHand];
        [containerLayer addSublayer:minHand];
        [containerLayer addSublayer:secHand];
        [self.layer addSublayer:containerLayer];

        self.layer.borderColor = [UIColor greenColor].CGColor;
        self.layer.borderWidth = 1.0;

    }
    return self;
}
- (void)dealloc {
    [self stop];
    [hourHand release];
    [minHand release];
    [secHand release];
    [containerLayer release];
    [super dealloc];
}
@end

Usage:

#import "ClockView.h"

- (void)viewDidLoad {
    [super viewDidLoad];

    ClockView *clockView = [[ClockView alloc] initWithFrame:CGRectMake(0,0,100,100)];
    [self.view addSubview:clockView];
    [clockView start];
    [clockView release];

}



回答2:


three weeks? Seriously?
my clock is very fugly but it is a clock, and it looks good enough to guess the current time from it.

static inline float PGVmyRadians(double degrees) { return degrees * M_PI / 180; }

- (void)drawRect:(CGRect)rect {
    CGFloat boundsWidth = self.bounds.size.width;
    CGFloat boundsHeight = self.bounds.size.height;
    CGPoint center = CGPointMake(boundsWidth/2, boundsHeight/2);

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextClearRect(context, self.bounds);
    CGContextSetFillColorWithColor(context, [UIColor magentaColor].CGColor);
    CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor);
    CGContextSetLineWidth(context, 10);
    CGContextSetLineCap(context, kCGLineCapRound);
    CGContextAddArc(context, boundsWidth/2, boundsHeight/2, boundsWidth/2, PGVmyRadians(0), PGVmyRadians(360), 0);

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

    if (hour > 12) {
        hour -= 12;
    }

    CGFloat angleSec = ((seconds - 15) / 60.0) * 360.0;
    CGFloat thetaSec = PGVmyRadians(angleSec);
    CGFloat lengthSec = 0.9 * boundsHeight/2;
    CGFloat Xsec = center.x + lengthSec * cos(thetaSec);
    CGFloat Ysec = center.y + lengthSec * sin(thetaSec);

    CGContextMoveToPoint(context, center.x, center.y);
    CGContextAddLineToPoint(context, Xsec, Ysec);

    CGFloat angleMin = ((minutes - 15) / 60.0) * 360.0;
    CGFloat thetaMin = PGVmyRadians(angleMin);
    CGFloat lengthMin = 0.7 * boundsHeight/2;
    CGFloat Xmin = center.x + lengthMin * cos(thetaMin);
    CGFloat Ymin = center.y + lengthMin * sin(thetaMin);

    CGContextMoveToPoint(context, center.x, center.y);
    CGContextAddLineToPoint(context, Xmin, Ymin);

    CGFloat angleHour = ((hour - 3) / 12.0) * 360.0;
    CGFloat thetaHour = PGVmyRadians(angleHour);
    CGFloat lengthHour = 0.5 * boundsHeight/2;
    CGFloat Xhour = center.x + lengthHour * cos(thetaHour);
    CGFloat Yhour = center.y + lengthHour * sin(thetaHour);

    CGContextMoveToPoint(context, center.x, center.y);
    CGContextAddLineToPoint(context, Xhour, Yhour);
    CGContextStrokePath(context);
}


来源:https://stackoverflow.com/questions/4843563/object-angle-based-on-current-time

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!