受this example的启发,我为楔形和弧线创建了一个自定义parseFloat
子类。允许我绘制弧形和楔形并对它们进行动画修改,使它们径向扫过。
对他们来说,其中一个令人沮丧的是,显然当你走这条有子类446
的路线时,你会受到图层框架剪辑的限制。对于库存图层,您有CALayer
,默认为drawInContext()
!但是看起来你曾经是带绘图的子类路线,因为它是隐式且不可改变的masksToBounds
。
所以我想我会尝试一种不同的方法,通过继承false
代替。而不是添加自定义true
,我只需要让CAShapeLayer
和drawInContext()
的变量更新接收器的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)
}
}
,但无济于事。
答案 0 :(得分:2)
有一些技巧可以让它正常工作:
请勿使用didSet
。相反,您应该覆盖display()
并在那里更新self.path
。
使用(presentation() as! WedgeLayer? ?? self).sweep
访问该媒体资源。 (presentation
,在Obj-C和Swift 2中称为presentationLayer
,允许您在动画期间访问当前可见的属性值。)
如果您想要隐式动画,请按照this answer中的说明实施actionForKey
。