更新 CALayer 的旋转

Posted

技术标签:

【中文标题】更新 CALayer 的旋转【英文标题】:Update the rotation of a CALayer 【发布时间】:2014-12-18 11:51:49 【问题描述】:

我正在尝试更新 CALayer 的当前旋转(有时是位置)。

我想通过几个简单的步骤来实现:

    将几个CALayers 存储在一个数组中,以便我可以重复使用它们 将所有 CALayers 的锚点设置为 0,0。 绘制CALayer对象,对象从圆上的某个位置开始 图层以与该位置的圆相同的角度旋转 更新 CALayer 的位置和旋转以匹配新值

这是我的一段代码:

lineWidth 是线的宽度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;
    

第一次运行的结果正是我想要的:

第二次运行这段代码只是没有正确更新 CALayers,它开始看起来像这样:

我认为更新 CALayer 的 locationtransform 属性与我的代码有关,但无论我做什么,它总是会导致最后一张图片。

【问题讨论】:

啊!!你做的很棒的事情。一个愚蠢的建议 - 您可以使用图像并将它们设置为看起来像旋转的动画。 它实际上是一个图表,带有随机长度的线条。我想重用我已经拥有的 CALayers 来为它们制作动画。 【参考方案1】:

通过 Twitter 回答:设置框架和变换是互斥的。乐意效劳。查找我的 SO 登录凭据更加困难。 :D

【讨论】:

【参考方案2】:

感谢 Twitter 上的@iosengineer 找到了答案。在CALayer上设置position时,不想更新图层的frame,但想更新bounds

Smooth animation FTW

【讨论】:

哈哈。看起来像尖刺的东西,我不想拿着。

以上是关于更新 CALayer 的旋转的主要内容,如果未能解决你的问题,请参考以下文章

CALayer 旋转动画不适用于呈现的 ViewController

CALayer的动画结束回调?

立即更新 CALayer 子层

移动层上的 iOS CALayer.mask

CALayer的transform属性

在哪里调用 setNeedsDisplay 来更新 CALayer?