正确的方法来继承CAShapeLayer

时间:2015-10-06 00:39:20

标签: ios swift core-animation cashapelayer

this example的启发,我为楔形和弧线创建了一个自定义parseFloat子类。允许我绘制弧形和楔形并对它们进行动画修改,使它们径向扫过。

对他们来说,其中一个令人沮丧的是,显然当你走这条有子类446的路线时,你会受到图层框架剪辑的限制。对于库存图层,您有CALayer,默认为drawInContext()!但是看起来你曾经是带绘图的子类路线,因为它是隐式且不可改变的masksToBounds

所以我想我会尝试一种不同的方法,通过继承false代替。而不是添加自定义true,我只需要让CAShapeLayerdrawInContext()的变量更新接收器的start。这很好用,但它不再像过去那样动画:

sweep

是否无法重新生成路径并更新,因为它会为值设置动画?使用path语句,我可以看到它在动画期间按预期插值。我尝试在各个地方添加import UIKit class WedgeLayer:CAShapeLayer { var start:Angle = 0.0.rotations { didSet { self.updatePath() }} var sweep:Angle = 1.0.rotations { didSet { self.updatePath() }} dynamic var startRadians:CGFloat { get {return self.start.radians.raw } set {self.start = newValue.radians}} dynamic var sweepRadians:CGFloat { get {return self.sweep.radians.raw } set {self.sweep = newValue.radians}} // more dynamic unit variants omitted // we have these alternate interfaces because you must use a type // which the animation framework can understand for interpolation purposes override init(layer: AnyObject) { super.init(layer: layer) if let layer = layer as? WedgeLayer { self.color = layer.color self.start = layer.start self.sweep = layer.sweep } } override init() { super.init() } required init(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } func updatePath() { let center = self.bounds.midMid let radius = center.x.min(center.y) print("updating path \(self.start) radius \(radius)") if self.sweep.abs < 1.rotations { let _path = UIBezierPath() _path.moveToPoint(center) _path.addArcWithCenter(center, radius: radius, startAngle: self.start.radians.raw, endAngle: (self.start + self.sweep).radians.raw, clockwise: self.sweep >= 0.radians ? true : false) _path.closePath() self.path = _path.CGPath } else { self.path = UIBezierPath(ovalInRect: CGRect(around: center, width: radius * 2, height: radius * 2)).CGPath } } override class func needsDisplayForKey(key: String) -> Bool { return key == "startRadians" || key == "sweepRadians" || key == "startDegrees" || key == "sweepDegrees" || key == "startRotations" || key == "sweepRotations" || super.needsDisplayForKey(key) } } ,但无济于事。

1 个答案:

答案 0 :(得分:2)

有一些技巧可以让它正常工作:

  • 请勿使用didSet。相反,您应该覆盖display()并在那里更新self.path

  • 使用(presentation() as! WedgeLayer? ?? self).sweep访问该媒体资源。 (presentation,在Obj-C和Swift 2中称为presentationLayer,允许您在动画期间访问当前可见的属性值。)

  • 如果您想要隐式动画,请按照this answer中的说明实施actionForKey