coc*_*oco 7 animation caanimation ios uibezierpath swift
我发现UIImageView在两个状态之间设置动画是很棘手的:它的原始矩形框架和用a创建的新形状UIBezierPath.提到了许多不同的技术,其中大部分对我不起作用.
首先是认识到使用UIView块动画不起作用; 显然,无法在animateWithDuration:块中执行子图层动画.(见这里和这里)
剩下的CAAnimation就是具体的子类CABasicAnimation.我很快就意识到,一个人不能从一个没有一个的视图中动画CAShapeLayer(例如,见这里).
并且它们不能只是任何两个形状层路径,而是"动画形状层的路径只能保证在你喜欢的时候动画"(见这里)
有了它,就会出现更普通的问题,例如使用什么fromValue和toValue(它们应该是a CAShapeLayer还是a CGPath?),将动画添加到(layer或者mask?)等等.
似乎有很多变数; 哪个组合会给我我想要的动画?
coc*_*oco 16
第一个重点是类似地构造两个贝塞尔曲线路径,因此矩形是一个(平凡的)类似于更复杂的形状.
// the complex bezier path
let initialPoint = CGPoint(x: 0, y: 0)
let curveStart = CGPoint(x: 0, y: (rect.size.height) * (0.2))
let curveControl = CGPoint(x: (rect.size.width) * (0.6), y: (rect.size.height) * (0.5))
let curveEnd = CGPoint(x: 0, y: (rect.size.height) * (0.8))
let firstCorner = CGPoint(x: 0, y: rect.size.height)
let secondCorner = CGPoint(x: rect.size.width, y: rect.size.height)
let thirdCorner = CGPoint(x: rect.size.width, y: 0)
var myBezierArc = UIBezierPath()
myBezierArc.moveToPoint(initialPoint)
myBezierArc.addLineToPoint(curveStart)
myBezierArc.addQuadCurveToPoint(curveEnd, controlPoint: curveControl)
myBezierArc.addLineToPoint(firstCorner)
myBezierArc.addLineToPoint(secondCorner)
myBezierArc.addLineToPoint(thirdCorner)
Run Code Online (Sandbox Code Playgroud)
创建一个矩形的更简单的"平凡"bezier路径完全相同,但是它controlPoint被设置为看起来不存在:
let curveControl = CGPoint(x: 0, y: (rect.size.height) * (0.5))
Run Code Online (Sandbox Code Playgroud)
(尝试删除该addQuadCurveToPoint行以获得一个非常奇怪的动画!)
最后,动画命令:
let myAnimation = CABasicAnimation(keyPath: "path")
if (isArcVisible == true) {
myAnimation.fromValue = myBezierArc.CGPath
myAnimation.toValue = myBezierTrivial.CGPath
} else {
myAnimation.fromValue = myBezierTrivial.CGPath
myAnimation.toValue = myBezierArc.CGPath
}
myAnimation.duration = 0.4
myAnimation.fillMode = kCAFillModeForwards
myAnimation.removedOnCompletion = false
myImageView.layer.mask.addAnimation(myAnimation, forKey: "animatePath")
Run Code Online (Sandbox Code Playgroud)
如果有人有兴趣,项目就在这里.
另一种方法是使用显示链接.它就像一个计时器,除了它与显示器的更新协调.然后,您可以使用显示链接的处理程序根据动画的任何特定点的外观修改视图.
例如,如果您想要将蒙版的圆角从0到50点设置为动画,则可以执行以下操作,其中percent值介于0.0和1.0之间,表示动画的百分比:
let path = UIBezierPath(rect: imageView.bounds)
let mask = CAShapeLayer()
mask.path = path.CGPath
imageView.layer.mask = mask
let animation = AnimationDisplayLink(duration: 0.5) { percent in
let cornerRadius = percent * 50.0
let path = UIBezierPath(roundedRect: self.imageView.bounds, cornerRadius: cornerRadius)
mask.path = path.CGPath
}
Run Code Online (Sandbox Code Playgroud)
哪里:
class AnimationDisplayLink : NSObject {
var animationDuration: CGFloat
var animationHandler: (percent: CGFloat) -> ()
var completionHandler: (() -> ())?
private var startTime: CFAbsoluteTime!
private var displayLink: CADisplayLink!
init(duration: CGFloat, animationHandler: (percent: CGFloat)->(), completionHandler: (()->())? = nil) {
animationDuration = duration
self.animationHandler = animationHandler
self.completionHandler = completionHandler
super.init()
startDisplayLink()
}
private func startDisplayLink () {
startTime = CFAbsoluteTimeGetCurrent()
displayLink = CADisplayLink(target: self, selector: "handleDisplayLink:")
displayLink.addToRunLoop(NSRunLoop.currentRunLoop(), forMode: NSRunLoopCommonModes)
}
private func stopDisplayLink() {
displayLink.invalidate()
displayLink = nil
}
func handleDisplayLink(displayLink: CADisplayLink) {
let elapsed = CFAbsoluteTimeGetCurrent() - startTime
var percent = CGFloat(elapsed) / animationDuration
if percent >= 1.0 {
stopDisplayLink()
animationHandler(percent: 1.0)
completionHandler?()
} else {
animationHandler(percent: percent)
}
}
}
Run Code Online (Sandbox Code Playgroud)
显示链接方法的优点在于它可以用于动画一些无法动画的属性.它还允许您在动画期间精确地指示临时状态.
如果您可以使用CAAnimation或UIKit基于块的动画,那可能就是这样.但显示链接有时可能是一个很好的后备方法.
| 归档时间: |
|
| 查看次数: |
8924 次 |
| 最近记录: |