Search code examples
iphoneobjective-cipadipod

Circular Rotation Of five buttons maintaining equal distance


I want to rotate five buttons on the circumference of an circle (circle with the center (120,120), which is actually center of square view i.e. 240*240) with radius 100. IS it possible to do so, with having interaction with the buttons which are rotating and a proper look.

i have tried '

x =  round(cx + redious * cos(angl));
y =  round(cy - redious * sin(angl));   

NSString *X=[NSString stringWithFormat:@"%f",x];
[xval addObject:[NSString stringWithFormat:@"%@",X]];
NSString *Y=[NSString stringWithFormat:@"%f",y];
[yval addObject:[NSString stringWithFormat:@"%@",Y]];'

to calculate points and:

map.frame= CGRectMake([[fqx objectAtIndex:counter1]intValue],[[fqy objectAtIndex:counter1]intValue], 72, 37);   
website.frame= CGRectMake([[fqx objectAtIndex:counter2]intValue],[[fqy objectAtIndex:counter2]intValue], 72, 37);   
share.frame= CGRectMake([[fqx objectAtIndex:counter3]intValue],[[fqy objectAtIndex:counter3]intValue], 72, 37); 
slideShow.frame= CGRectMake([[fqx objectAtIndex:counter4]intValue],[[fqy objectAtIndex:counter4]intValue], 72, 37);' 

to rotate but it generate weird path.. in triangular way.. ('map','share','slideShow','website') ar my buttons.. :P


Solution

  • This was too cute to pass up so here it is. This code is limited to one button rotating but I doubt you'll have trouble extending it to take multiple (hint: use ONE CADisplayLink and rotate all buttons at once in that).

    - (void)setupRotatingButtons
    {
        // call this method once; make sure "self.view" is not nil or the button 
        // won't appear. the below variables are needed in the @interface.
        // center: the center of rotation
        // radius: the radius
        // time:   a CGFloat that determines where in the cycle the button is located at
        //         (note: it will keep increasing indefinitely; you need to use 
        //         modulus to find a meaningful value for the current position, if
        //         needed)
        // speed:  the speed of the rotation, where 2 * M_PI is 1 lap a second
        // b:      the UIButton
        center = CGPointMake(100, 100);
        radius = 100;
        time = 0;
        speed = 2 * M_PI; // <-- will rotate CW 360 degrees per second (1 "lap"/s)
    
        b = [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
        b.titleLabel.text = @"Hi";
        b.frame = CGRectMake(0.f, 0.f, 100, 50);
        // we get the center set right before we add subview, to avoid glitch at start
        [self continueCircling:nil]; 
        [self.view addSubview:b];
        [self.view bringSubviewToFront:b];
        CADisplayLink *dl = [CADisplayLink displayLinkWithTarget:self 
            selector:@selector(continueCircling:)];
        [dl addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    }
    

    We also need the actual "continueCircling:" method, which is simply:

    - (void)continueCircling:(CADisplayLink *)dl
    {
        time += speed * dl.duration;
        b.center = CGPointMake(center.x + radius * cosf(time), 
                               center.y + radius * sinf(time));
    }
    

    I'm sure there are other more nifty ways to solve this, but the above works at least. :)

    Edit: I forgot to mention, you will need to add QuartzCore framework and

    #import <QuartzCore/QuartzCore.h> 
    

    for CADisplayLink.

    Edit 2: Found the PI constant (M_PI), so replaced 3.1415 with that.