Вращающееся колесо с этикетками - как держать этикетки в горизонтальном положении при вращении колеса?

Я искал решение о том, как реализовать колесо типа фортуны (работающее хорошо), за исключением того, что мне нужны изображения / метки на периферии колеса, чтобы они оставались горизонтальными и не вращались вместе с колесом. Я реализовал следующее, но метки (в данном случае красные овалы) не остаются горизонтальными.

Колесо должно быть

Я прилагаю свой код, который строит красные овалы на экране:

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];

      }

   }

Ниже приведена функция, которая вращает колесо; Я делаю строку кода, которая выполняет вращение для меток - я, очевидно, здесь что-то делаю не так, но я понятия не имею, что. Любое руководство с благодарностью.

-(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];
  }
}

3 ответа

Аргументы CATransform3DMakeRotation угол и три составляющие оси вращения. Ось вращения как для колеса, так и для подслоев надписей должна быть просто осью Z. Вы получили это право на колесо, но не на этикетки.

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

Однако было бы проще использовать аффинные преобразования, которые могут вращаться только вокруг оси Z:

-(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 преобразует аффинные преобразования в трехмерные преобразования для вас.

Другой способ избавиться от этой проблемы - не использовать метки в качестве подвида колеса. Вы просто помещаете их сверху колеса. Поэтому, когда колесо вращается, ярлыки будут на том же месте. Дайте мне знать, если я не достаточно ясно

РЕДАКТИРОВАТЬ

Вот альтернативное решение для вашей проблемы. Это не идеально, но может дать вам новое направление мышления.

  1. Возьмите свое изображение колеса в формате PNG.
  2. сделайте фон прозрачным для вашего колеса. (Не нужно.. просто чтобы украсить)
  3. сделайте отверстие в тех местах на колесе, где вы хотите показать метку. (Под отверстием я хотел сделать часть прозрачной).
  4. Теперь поместите метки за руль. Поместите их в соответствии с необходимым углом поворота.
  5. Теперь, когда вы поворачиваете колесо под точными углами, вы сможете видеть метки. Это как два слоя бумаги.

Почему это не Perfect Labels не будет двигаться с колесом. Таким образом, вы сможете видеть метки только под определенными углами.

Я не знаю точную цель требования вашего вопроса, но я использовал этот подход для создания Jog dial для своего приложения.

Проблема в том, что вы вращаете все колесо, для которого эти метки являются subViews.so, а также колесо, которое они также вращают.
Наилучшим подходом является вычисление значения угла поворота. Из этого угла рассчитайте новые позиции меток на этом круге и поместите метки (не подколесные колеса) в эти новые позиции.

ИЛИ (метод 2)

установите отрицание этого преобразования вращения на эти метки.

Другие вопросы по тегам