0

I have been searching for a solution of how to implement a wheel of fortune-type wheel (working well) with the exception that I need the images/labels on the periphery of the wheel to stay horizontal and not rotate with the wheel. I have the following implemented, but the labels ( in this case the red ovals ) aren't staying horizontal.

This is how it should always look, no matter where the wheel has rotated

enter image description here

I am enclosing my code that builds the red ovals on the screen :

CGFloat cita = 0;
for(int i = 1; i < 2; ++i)
{
    CGFloat smallCircleRadius = bigCircleRadius / 8.0;
    for (int i = 0; i < 8; i++)
    {

        CGPoint smallCircleCenter = CGPointMake(wheelCenter.x  + bigCircleRadius * cos(cita) - smallCircleRadius/2.0 , wheelCenter.y + bigCircleRadius * sin(cita) - smallCircleRadius / 2.0 );


        CGRect smallCircleRect = CGRectMake(smallCircleCenter.x,smallCircleCenter.y,smallCircleRadius * 2,smallCircleRadius);

        cita += M_PI / 4.0;

        CAShapeLayer *l = [CAShapeLayer layer];
        UIBezierPath * p1 = [UIBezierPath bezierPathWithOvalInRect:smallCircleRect];

        l.path = p1.CGPath;
        l.strokeColor = [[UIColor redColor] CGColor];
        l.fillColor = [[UIColor redColor] CGColor];
        l.lineWidth = 3.0;

        l.anchorPoint = CGPointMake(.5, .5);

        [self.emoticonsArray addObject:l];

        [self.baseWheel.layer addSublayer:l];

      }

   }

Below is the function that spins the wheel; I'm making the line of code that does the rotation for the labels - I'm obviously doing something wrong here, but I have no idea what. Any guidance greatly appreciated.

-(void)spin:(double)delta
{
currentAngle = currentAngle + delta;

CATransform3D transform = CATransform3DMakeRotation(currentAngle, 0, 0, 1);

[self.baseWheel.layer setTransform:transform];

  // rotate the red labels here.
  for (CAShapeLayer * l in self.emoticonsArray)
  {

    CGPoint miniWheelCenter = [l convertPoint:l.position toLayer:self.baseWheel.layer.superlayer];


    // !! something wrong here!! but what? 
    CATransform3D t_l = CATransform3DMakeRotation(-currentAngle, miniWheelCenter.x/2, miniWheelCenter.y/2, 1);
    [l setTransform:t_l];
  }
}
pikovayadama
  • 808
  • 2
  • 8
  • 26
  • the problem is because you are rotating the entire wheel for which those lables are subViews.so along with wheel they also rotate. – santhu Jan 21 '14 at 20:09
  • that is the expected behavior. what I would like to do is keep the red ovals moving with the wheel behind them, while having their orientation not change - meaning that they should stay horizontally oriented as they are now, while rotating around the circle, like a ferris wheel. – pikovayadama Jan 22 '14 at 03:39

3 Answers3

1

The arguments to CATransform3DMakeRotation are the angle and the three components of the axis of rotation. The axis of rotation for both the wheel and the label sublayers should simply be the Z axis. You got this right for the wheel but wrong for the labels.

CATransform3D t_l = CATransform3DMakeRotation(-currentAngle, 0, 0, 1);
[l setTransform:t_l];

However, it would be simpler to just use affine transforms, which can only rotate around the Z axis:

-(void)spin:(double)delta {
    currentAngle = currentAngle + delta;
    self.baseWheel.layer.affineTransform = CGAffineTransformMakeRotation(currentAngle);

    CGAffineTransform labelTransform = CGAffineTransformMakeRotation(-currentAngle);
    for (CAShapeLayer *l in self.emoticonsArray) {
        l.affineTransform = labelTransform;
    }
}

Core Animation will convert the affine transforms to 3D transforms for you.

rob mayoff
  • 375,296
  • 67
  • 796
  • 848
  • it's very elegant, but unfortunately didn't work - I have this happening [link] (https://www.dropbox.com/lightbox/home/Public) – pikovayadama Jan 21 '14 at 20:32
  • so sorry - here it is [link](https://www.dropbox.com/s/d97a9w1z8iywij6/Screen%20Shot%202014-01-21%20at%203.28.59%20PM.png) – pikovayadama Jan 21 '14 at 20:37
0

the problem is because you are rotating the entire wheel for which those lables are subViews.so along with wheel they also rotate.
The best approach is calculate the rotation angle value.From that angle, calculate new positions of labels on that circle, and place lables(not subivews of wheel) in those new postions.

OR (method 2)

set the negative of that rotation transform to those labels.

santhu
  • 4,796
  • 1
  • 21
  • 29
  • if you look closely at my code, setting the negative angle is exactly what I'm doing. I've added a new image - the first one made it seem like the ovals weren't moving at all, but they are indeed being transformed, just not as expected. In the code I set the following : `CGPoint miniWheelCenter = [l convertPoint:l.position toLayer: self.baseWheel.layer.superlayer]; // !! something wrong here!! but what? CATransform3D t_l = CATransform3DMakeRotation(-currentAngle, miniWheelCenter.x/2, miniWheelCenter.y/2, 1); ` - i believe something in here is wrong. – pikovayadama Jan 21 '14 at 20:17
0

Other way you can get rid of this issue is, Don't use labels as subView of the wheel. You just place them on top of the wheel. So when the wheel rotates, labels would be on same place. Let me know if I am not clear enough

EDIT

Here is an alternate solution for your problem. It's not perfect, but might give you a new direction to think.

  1. Take your wheel image in png format.
  2. make the background transparent for your wheel. (Not needed.. just to beautify)
  3. make a hole in the positions on wheel where you want to show label. (By hole I meant to make the portion transparent).
  4. Now put Labels behind the wheel.Position them according to required rotation angle.
  5. Now when you rotate the wheel, at exact angles, you would be able to see the labels. Its just like two layers of paper.

Why It is not Perfect Labels will not be moving with wheel. So you would be able to see labels only at certain angles only.

I don't know the exact purpose behind requirement of your question, but I used this approach to create Jog dial for my app..

Prince Agrawal
  • 3,619
  • 3
  • 26
  • 41
  • I need the labels to move with the wheel; I just need them to stay horizontal as they do - like a ferris wheel - does that make sense? – pikovayadama Jan 21 '14 at 20:19
  • yeah.. it totally makes a sense & I think I got an alternative solution for your issue. Check my updated answer in 5 mins. – Prince Agrawal Jan 21 '14 at 20:23
  • I'm afraid I wasn't making myself clear enough. I DO need the labels to along with the wheel - as if they are tracing their own arc around the circumference of the wheel. What I need to change is the actual angle of the text (once I put it in) on the labels - so that the image on the label always stays angled north. A ferris wheel is a good example - the individual booths move along with the ferris wheel, but the booths and the people in them are always sitting in the same position w/r/t/their vertical and horizontal orientation.Positions change but orientations don't. – pikovayadama Jan 21 '14 at 20:47
  • I found another [question] (http://stackoverflow.com/questions/17953283/ios-implement-a-rotating-wheel-with-custom-views-being-horizontally-stationary#comment32042849_17953283) which describes it better - but the part about the stationary views was never answered - perhaps this will be clearer : – pikovayadama Jan 21 '14 at 21:02