最近在寫(xiě)一個(gè)相冊(cè)的demo狠裹,偶爾看到了美拍的相機(jī)過(guò)載動(dòng)畫(huà)覺(jué)得很有意思,就想在我的相冊(cè)demo中加入一個(gè)這種特效官辽,下面把我的想法和實(shí)現(xiàn)過(guò)程給大家分享一下
先上效果圖:(demo地址)
步驟分析
這個(gè)動(dòng)效看起來(lái)很有特色但是實(shí)現(xiàn)起來(lái)是非常簡(jiǎn)單的汛聚,只需要用到CALayer
和CAShapeLayer
做為展示層,然后通過(guò)CABasicAnimation
實(shí)現(xiàn)動(dòng)畫(huà)就行了~
- 用兩個(gè)
CALayer
來(lái)呈現(xiàn)啟動(dòng)的image - 通過(guò)
UIBezierPath
和CAShapeLayer
來(lái)畫(huà)出具有曲線的CAShapeLayer - 然后將曲線的
CAShapeLayer
做為CALayer
的mask - 最后通過(guò)
CABasicAnimation
做一個(gè)簡(jiǎn)單的位移動(dòng)畫(huà)
先繪制上半部分的layer
/**
繪制上半部分的layer
*/
private func configTopShapeLayer() {
//繪制貝斯?fàn)柷€
let topBezier:UIBezierPath = UIBezierPath()
topBezier.moveToPoint(CGPointMake(-1, -1))
topBezier.addLineToPoint(CGPointMake(bounds.width+1, -1))
topBezier.addCurveToPoint(CGPointMake(bounds.width/2.0+1, bounds.height/2.0+1), controlPoint1: CGPointMake(bounds.width+1, 0+1), controlPoint2: CGPointMake(343.5+1, 242.5+1))
topBezier.addCurveToPoint(CGPointMake(-1, bounds.height+2), controlPoint1: CGPointMake(31.5+2, 424.5+2), controlPoint2: CGPointMake(0+2, bounds.height+2))
topBezier.addLineToPoint(CGPointMake(-1, -1))
topBezier.closePath()
//創(chuàng)建一個(gè)CAShapeLayer畅买,將繪制的貝斯?fàn)柷€的path給CAShapeLayer
let topShape = CAShapeLayer()
topShape.path = topBezier.CGPath
//給topLayer設(shè)置contents為啟動(dòng)圖
topLayer.contents = launchImage?.CGImage
topLayer.frame = bounds
layer.addSublayer(topLayer)
//將繪制后的CAShapeLayer做為topLayer的mask
topLayer.mask = topShape
}
繪制后的結(jié)果是這樣的:
然后以同樣的原理繪制下半部分的layer
/**
繪制下半部分的layer
*/
private func configBottomShapeLayer() {
//繪制貝斯?fàn)柷€
let bottomBezier:UIBezierPath = UIBezierPath()
bottomBezier.moveToPoint(CGPointMake(bounds.width, 0))
bottomBezier.addCurveToPoint(CGPointMake(bounds.width/2.0, bounds.height/2.0), controlPoint1: CGPointMake(bounds.width, 0), controlPoint2: CGPointMake(343.5, 242.5))
bottomBezier.addCurveToPoint(CGPointMake(0, bounds.height), controlPoint1: CGPointMake(31.5, 424.5), controlPoint2: CGPointMake(0, bounds.height))
bottomBezier.addLineToPoint(CGPointMake(bounds.width, bounds.height))
bottomBezier.addLineToPoint(CGPointMake(bounds.width, 0))
bottomBezier.closePath()
//創(chuàng)建一個(gè)CAShapeLayer并闲,將繪制的貝斯?fàn)柷€的path給CAShapeLayer
let bottomShape = CAShapeLayer()
bottomShape.path = bottomBezier.CGPath
//給bottomLayer設(shè)置contents為啟動(dòng)圖
bottomLayer.contents = launchImage?.CGImage
bottomLayer.frame = bounds
layer.addSublayer(bottomLayer)
//將繪制后的CAShapeLayer做為bottomLayer的mask
bottomLayer.mask = bottomShape
}
這里注意的是畫(huà)的貝斯?fàn)柷€上半部分的要整體向下平移1到2個(gè)像素,為了防止貝斯?fàn)柷€畫(huà)曲線導(dǎo)致的鋸齒效果谷羞,下面是下半部分完成后的效果圖:
最后給兩個(gè)layer一個(gè)位移動(dòng)畫(huà)
/**
展開(kāi)的動(dòng)畫(huà)
*/
func starAnimation() {
//創(chuàng)建一個(gè)CABasicAnimation作用于CALayer的anchorPoint
let topAnimation = CABasicAnimation.init(keyPath: "anchorPoint")
//設(shè)置移動(dòng)路徑
topAnimation.toValue = NSValue.init(CGPoint: CGPointMake(1, 1))
//動(dòng)畫(huà)時(shí)間
topAnimation.duration = 0.6
//設(shè)置代理帝火,方便完成動(dòng)畫(huà)后移除當(dāng)前view
topAnimation.delegate = self
//設(shè)置動(dòng)畫(huà)速度為勻速
topAnimation.timingFunction = CAMediaTimingFunction.init(name: kCAMediaTimingFunctionLinear)
//設(shè)置動(dòng)畫(huà)結(jié)束后不移除點(diǎn),保持移動(dòng)后的位置
topAnimation.removedOnCompletion = false
topAnimation.fillMode = kCAFillModeForwards
topLayer.addAnimation(topAnimation, forKey: "topAnimation")
//創(chuàng)建一個(gè)CABasicAnimation作用于CALayer的anchorPoint
let bottomAnimation = CABasicAnimation.init(keyPath: "anchorPoint")
//設(shè)置移動(dòng)路徑
bottomAnimation.toValue = NSValue.init(CGPoint: CGPointMake(0, 0))
//動(dòng)畫(huà)時(shí)間
bottomAnimation.duration = 0.6
//設(shè)置動(dòng)畫(huà)速度為勻速
bottomAnimation.timingFunction = CAMediaTimingFunction.init(name: kCAMediaTimingFunctionLinear)
//設(shè)置動(dòng)畫(huà)結(jié)束后不移除點(diǎn)湃缎,保持移動(dòng)后的位置
bottomAnimation.removedOnCompletion = false
bottomAnimation.fillMode = kCAFillModeForwards
bottomLayer.addAnimation(bottomAnimation, forKey: "topAnimation")
}
/**
動(dòng)畫(huà)完成后移除當(dāng)前view
*/
internal override func animationDidStop(anim: CAAnimation, finished flag: Bool)
{
if flag {
removeFromSuperview()
}
}
這里為了方便觀察犀填,我將動(dòng)畫(huà)時(shí)間變長(zhǎng)了,下面是完成后的效果圖:
到這里這個(gè)動(dòng)效就完成的差不多了嗓违,希望大家能學(xué)到東西九巡,如果大家有更好的實(shí)現(xiàn)辦法也可以給我提意見(jiàn),我學(xué)習(xí)學(xué)習(xí)蹂季,謝謝大家觀看冕广,另外附加demo地址,喜歡的可以關(guān)注一下