两条Bézier路径形状之间的动画 [英] Animating between two bezier path shapes
问题描述
我觉得棘手的动画一个的UIImageView
两者之间的状态:原来的矩形边框,并用创造了一个新的形状 UIBezierPath
。有提到很多不同的技术,其中大部分并没有为我工作。
I found it tricky to animate a UIImageView
between two states: its original rectangle frame, and a new shape created with a UIBezierPath
. There are many different techniques mentioned, most of which did not work for me.
首先是实现了使用的UIView动画块是行不通的;显然一个人不能在一个 animateWithDuration执行子层动画:
块。 (请参见这里和的here )
First was the realization that using UIView block animation would not work; evidently one can't perform sublayer animations in an animateWithDuration:
block. (see here and here)
这让 CAAnimation
,像 CABasicAnimation
的具体子类。我很快意识到,一个人不能从没有一个 CAShapeLayer
一,它(请参阅<一个视图动画href=\"http://stackoverflow.com/questions/11463438/cabasicanimation-with-calayer-path-doesnt-animate\">here,例如)。
That left CAAnimation
, with the concrete subclasses like CABasicAnimation
. I soon realized that one can't animate from a view that doesn't have a CAShapeLayer
to one that does (see here, for example).
他们不能只是任何两个形状图层路径,而是动画形状图层的路径,才能保证当您从动画一样喜欢的工作(见的here )
And they can't be just any two shape layer paths, but rather "Animating the path of a shape layer is only guaranteed to work when you are animating from like to like" (see here)
通过在地方,来了更现实的问题,如怎样使用 fromValue
和 toValue
(应他们是一个 CAShapeLayer
或 CGPath
?),有什么动画添加到(在层
或屏蔽
?)等。
With that in place, comes the more mundane problems, like what to use for fromValue
and toValue
(should they be a CAShapeLayer
, or a CGPath
?), what to add the animation to (the layer
, or the mask
?), etc.
似乎有这么多的变数;该组合会给我我一直在寻找的动画?
It seemed there were so many variables; which combination would give me the animation I was looking for?
推荐答案
首先重要的一点是相似的构造两个贝塞尔路径,所以矩形是一个(简单)模拟向更复杂的形状。
The first important point is to construct the two bezier paths similarly, so the rectangle is a (trivial) analogue to the more complex shape.
// 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)
在简单的'小事'贝塞尔路径,即创建一个矩形,是完全一样的,但的ControlPoint
设置,以便它似乎不应该存在:
The simpler 'trivial' bezier path, that creates a rectangle, is exactly the same but the controlPoint
is set so that it appears to not be there:
let curveControl = CGPoint(x: 0, y: (rect.size.height) * (0.5))
(尝试删除 addQuadCurveToPoint
线得到一个很奇怪的动画!)
( Try removing the addQuadCurveToPoint
line to get a very strange animation! )
最后,动画命令:
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")
如果有人有兴趣,该项目是这里。
If anyone is interested, the project is here.
这篇关于两条Bézier路径形状之间的动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!