简体   繁体   English

更新CALayer的旋转

[英]Update the rotation of a CALayer

I am trying to update the current rotation (and sometimes the position) of a CALayer. 我正在尝试更新CALayer的当前轮换(有时是位置)。

What I am trying to in a couple of simple steps: 我想通过几个简单的步骤来尝试:

  1. Store a couple of CALayers in an array, so I can reuse them 将几个CALayers存储在一个数组中,这样我就可以重用它们
  2. Set the anchor point of all CALayers to 0,0. 将所有CALayers的锚点设置为0,0。
  3. Draw CALayer objects where the object starts at a position on a circle 绘制CALayer对象,其中对象从圆上的位置开始
  4. The layers are rotated by the same angle as the circle at that position 这些层旋转的角度与该位置的圆相同
  5. Update the position and rotation of the CALayer to match new values 更新CALayer的位置和旋转以匹配新值

Here is a piece of code I have: 这是我的一段代码:

lineWidth is the width of a line lineWidth是一条线的宽度
self.items is an array containing the CALayer objects self.items是一个包含CALayer对象的数组

func updateLines() {

    var space = 2 * M_PI * Double(circleRadius);
    var spaceAvailable = space / (lineWidth)

    var visibleItems = [Int]();

    var startIndex = items.count - Int(spaceAvailable);
    if (startIndex < 0) {
        startIndex = 0;
    }

    for (var i = startIndex; i < self.items.count; i++) {
        visibleItems.append(self.items[i]);
    }

    var circleCenter = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame));

    /* Each line should move up and rotate accordin to this value */
    var anglePerLine: CGFloat = (360 / CGFloat(visibleItems.count)).toRadians()

    /* Starting position, 270 degrees is on top */
    var startAngle: CGFloat = CGFloat(270).toRadians();

    /* Lines default rotation, we rotate it to get the right side up */
    var lineAngle: CGFloat = CGFloat(180).toRadians();

    for (var itemIndex = 0; itemIndex < visibleItems.count; itemIndex++) {
        var itemLayer = self.itemLayers[itemIndex];
        itemLayer.opacity = 1 - ((0.9 / visibleItems.count) * itemIndex);

        /* Calculate start position of layer */
        var x = CGFloat(circleRadius) * cos(startAngle) + CGFloat(circleCenter.x);
        var y = CGFloat(circleRadius) * sin(startAngle) + CGFloat(circleCenter.y);
        var height = CGFloat((arc4random() % 80) + 10);

        /* Set position and frame of layer */
        itemLayer.frame = CGRectMake(CGFloat(x), CGFloat(y), CGFloat(lineWidth), height);
        itemLayer.position = CGPointMake(CGFloat(x), CGFloat(y));

        var currentRotation = CGFloat((itemLayer.valueForKeyPath("transform.rotation.z") as NSNumber).floatValue);
        var newRotation = lineAngle - currentRotation;

        var rotationTransform = CATransform3DRotate(itemLayer.transform, CGFloat(newRotation), 0, 0, 1);
        itemLayer.transform = rotationTransform;

        lineAngle += anglePerLine;
        startAngle += anglePerLine;
    }
}

The result of the first run is exactly as I want it to be: 第一次运行的结果与我希望的完全一样:

在此输入图像描述

The second run through this code just doesn't update the CALayers correctly and it starts to look like this: 第二次运行此代码只是没有正确更新CALayers,它开始看起来像这样:

在此输入图像描述

I think it has to do with my code to update the location and transform properties of the CALayer, but whatever I do, it always results in the last picture. 我认为它与我的代码有关,以更新CALayer的locationtransform属性,但无论我做什么,它总是导致最后一张图片。

Answered via Twitter: setting frames and transform is mutually exclusive. 通过Twitter回答:设置框架和转换是互斥的。 Happy to help. 乐意效劳。 Finding my login credentials for SO is harder. 查找我的SO登录凭据更难。 :D :d

Found the answer thanks to @iosengineer on Twitter. 感谢@iosengineer在Twitter上找到答案。 When setting a position on the CALayer, you do not want to update the frame of the layer, but you want to update the bounds . 在CALayer上设置position时,您不希望更新图层的frame ,但是您想要更新bounds

Smooth animation FTW 平滑动画FTW

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM