iOS icon jiggle algorithm

前端 未结 11 877
执笔经年
执笔经年 2020-12-12 16:31

I am writing an iPad app that presents user documents similar to the way Pages presents them (as large icons of the actual document). I also want to mimic the jiggling beha

11条回答
  •  感动是毒
    2020-12-12 17:07

    Here is the Swift 4.2 version of @mientus' code (which is itself an update of Paul Popiel's version), as an extension of CALayer:

    extension CALayer {
    
        private enum WigglingAnimationKey: String {
            case position = "wiggling_position_animation"
            case transform = "wiggling_transform_animation"
        }
    
        func startWiggling() {
            let duration = 0.25
            let displacement = 1.0
            let negativeDisplacement = displacement * -1
            let rotationAngle = Measurement(value: 2, unit: UnitAngle.degrees)
    
            // Position animation
            let positionAnimation = CAKeyframeAnimation(keyPath: #keyPath(CALayer.position))
            positionAnimation.beginTime = 0.8
            positionAnimation.duration = duration
            positionAnimation.values = [
                NSValue(cgPoint: CGPoint(x: negativeDisplacement, y: negativeDisplacement)),
                NSValue(cgPoint: CGPoint.zero),
                NSValue(cgPoint: CGPoint(x: 0, y: negativeDisplacement)),
                NSValue(cgPoint: CGPoint(x: negativeDisplacement, y: negativeDisplacement))
            ]
            positionAnimation.calculationMode = .linear
            positionAnimation.isRemovedOnCompletion = false
            positionAnimation.repeatCount = .greatestFiniteMagnitude
            positionAnimation.beginTime = CFTimeInterval(Float(Int.random(in: 0...25)) / 100)
            positionAnimation.isAdditive = true
    
            // Rotation animation
            let transformAnimation = CAKeyframeAnimation(keyPath: #keyPath(CALayer.transform))
            transformAnimation.beginTime = 2.6
            transformAnimation.duration = duration
            transformAnimation.valueFunction = CAValueFunction(name: .rotateZ)
            transformAnimation.values = [
                CGFloat(rotationAngle.converted(to: .radians).value * -1),
                CGFloat(rotationAngle.converted(to: .radians).value),
                CGFloat(rotationAngle.converted(to: .radians).value * -1)
            ]
            transformAnimation.calculationMode = .linear
            transformAnimation.isRemovedOnCompletion = false
            transformAnimation.repeatCount = .greatestFiniteMagnitude
            transformAnimation.isAdditive = true
            transformAnimation.beginTime = CFTimeInterval(Float(Int.random(in: 0...25)) / 100)
    
            self.add(positionAnimation, forKey: WigglingAnimationKey.position.rawValue)
            self.add(transformAnimation, forKey: WigglingAnimationKey.transform.rawValue)
        }
    
        func stopWiggling() {
            self.removeAnimation(forKey: WigglingAnimationKey.position.rawValue)
            self.removeAnimation(forKey: WigglingAnimationKey.transform.rawValue)
        }
    }
    

    Usage (where anyLayer is a CALayer):

    // Start animating.
    anyLayer.startWiggling()
    // Stop animating.
    anyLayer.stopWiggling()
    

提交回复
热议问题