iOS 利用動(dòng)畫和貝塞爾實(shí)現(xiàn)咻咻效果
先上效果圖:

圓形

方形
思路分析:
這四種風(fēng)格其實(shí)就是兩種, 一種是動(dòng)畫效果在視圖View的內(nèi)部, 另一種是在視圖的外部! 我們可以嘗試封裝自定義 View 設(shè)置相關(guān)屬性去實(shí)現(xiàn)這兩個(gè)風(fēng)格. 點(diǎn)擊時(shí)候觸及動(dòng)畫, 說明要在這個(gè) View 上添加手勢! 分析動(dòng)畫效果其實(shí)是兩種, 第一種是視圖的比例由小到大,第二種是動(dòng)畫顯示效果是漸漸變暗! 那么我們可以把兩種效果寫到一個(gè)動(dòng)畫組中!還有一個(gè)問題是效果的形狀, 也就是 Layer 動(dòng)畫展示的形狀有方形有圓形, 這個(gè)形狀就需要我們思考如何去繪制和判斷!
代碼分析:
首先要?jiǎng)?chuàng)建自定義一個(gè) View 類去實(shí)現(xiàn)點(diǎn)擊有動(dòng)畫的效果! 因?yàn)榉治鲇袃煞N風(fēng)格(在外在內(nèi))的動(dòng)畫, 因此要在. h 文件中聲明屬性去接收外界告知的風(fēng)格! 我們還可以添加一些供外界修改的值, 比如動(dòng)畫的邊界粗細(xì), 填充顏色, 動(dòng)畫時(shí)間等等這里我用一個(gè)顏色舉例! 外界可提供一個(gè)顏色, 怎么用具體代碼中有!
typedef NS_ENUM(NSUInteger, FlashButtonType){
# 風(fēng)格定義一個(gè)枚舉類型的去表示 分別是代表動(dòng)畫在里面和外面 (便于理解)
DDFlashButtonInner = 0,
DDFlashButtonOuter = 1
};
# 定義的兩個(gè)屬性
@property (strong, nonatomic) UIColor *flashColor;
@property (assign, nonatomic) FlashButtonType buttonType;
# 寫這個(gè)方法可以對 View 的子視圖上的子控件進(jìn)行操作, 可以不把子控件都暴露出去
- (void)setText:(NSString *)text withTextColor:(UIColor *)textColor;
第 2 步: 在初始化方法中,我們可以給這個(gè) view 加一些子視圖比如 UILabel 去顯示一些想表達(dá)的文字(這里還可以寫個(gè)方法去改變 label上 text 的屬性,)! 還需要給 View 添加點(diǎn)擊手勢!
- (instancetype) initWithFrame:(CGRect)frame{
if (self = [super initWithFrame:frame]) {
# 創(chuàng)建手勢 并添加到 View 上
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTap:)];
[self addGestureRecognizer:tap];
self.textLabel = [[UILabel alloc] initWithFrame:self.bounds];
self.textLabel.backgroundColor = [UIColor clearColor];
[self.textLabel setTextAlignment:NSTextAlignmentCenter];
[self addSubview:self.textLabel];
self.backgroundColor = [UIColor cyanColor];
# 給一個(gè)默認(rèn)的風(fēng)格 不設(shè)置就是代表 動(dòng)畫在里面
self.buttonType = DDFlashButtonInner;
}
return self;
}
第 3 步: 可以給子控件給一些屬性 這里有 label 還寫了個(gè)方法
- (void)setText:(NSString *)text withTextColor:(UIColor *)textColor
{
# 就是給 Label 賦外界傳來的值 若有其他的控件可以改一些參數(shù)用此方法
if (text)
{
[self.textLabel setText:text];
}
if (textColor)
{
[self.textLabel setTextColor:textColor];
}
}
第 4 步: 根據(jù)風(fēng)格的不同我們要控制動(dòng)畫展示的范圍, 也就是加入動(dòng)畫在內(nèi)部就不能超過 View 的范圍
# 這里就是重寫了ButtonType setter方法,同時(shí)判斷一下風(fēng)格根據(jù)風(fēng)格選擇是否把超過視圖 View 的部分裁剪掉
- (void)setButtonType:(FlashButtonType)buttonType
{
_buttonType = buttonType;
if (buttonType == DDFlashButtonInner)
{
// 內(nèi)容和子視圖是夾在視圖的邊界內(nèi) ( 只允許 view范圍內(nèi)有子視圖和類容可以顯示 )
self.clipsToBounds = 1;
}else
{// 外面可以顯示
self.clipsToBounds = 0;
}
}
第 5 步: 準(zhǔn)備工作做好后, 一個(gè)思路就是去寫點(diǎn)擊事件, 需要什么就去創(chuàng)建什么! 這先去思考點(diǎn)擊事件中需要的東西, 都滿足之后再去寫完善點(diǎn)擊事件! 動(dòng)畫效果首先需要?jiǎng)赢? 另外還需要能添加動(dòng)畫的 Layer;首先寫個(gè)得到動(dòng)畫的方法!
- (CAAnimationGroup *)createFlashAnimationWisthScale:(CGFloat)scale
duration:(CGFloat)duratiton
{
# 創(chuàng)建按比例收縮變大的動(dòng)畫
// 指定要在渲染動(dòng)畫性能時(shí)的關(guān)鍵路徑 也就是圖形轉(zhuǎn)換的方式 這里是按收縮比例 這里也可以不用.scale 因?yàn)槲覀兂跏贾翟O(shè)置是根據(jù)CATransform3D
CABasicAnimation *scaleAnnimation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
// 動(dòng)畫開始點(diǎn)
// 這個(gè)動(dòng)畫效果初值 就是本身的原始的位置
scaleAnnimation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
// 等價(jià) scaleAnnimation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1, 1, 1)];
// 動(dòng)畫結(jié)束點(diǎn)
// 在 x 軸和 y 軸的變化比例
scaleAnnimation.toValue = [NSValue valueWithCATransform3D:(CATransform3DMakeScale(scale, scale, 1))];
# 創(chuàng)建透明度變換的動(dòng)畫
CABasicAnimation *alphaAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
alphaAnimation.fromValue = @1;
alphaAnimation.toValue = @0;
# 創(chuàng)建動(dòng)畫組把上面兩個(gè)動(dòng)畫加進(jìn)去
CAAnimationGroup *animation = [CAAnimationGroup new];
animation.animations = @[scaleAnnimation,alphaAnimation];
// 動(dòng)畫效果 (節(jié)奏, Timing Function的會(huì)被用于變化起點(diǎn)和終點(diǎn)之間的插值計(jì)算.形象點(diǎn)說是Timing Function決定了動(dòng)畫運(yùn)行的節(jié)奏(Pacing),比如是均勻變化(相同時(shí)間變化量相同),先快后慢,先慢后快還是先慢再快再慢.)
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
# 返回我們想要的動(dòng)畫效果組
return animation;
}
第 6 步: 得到一個(gè)CAShapeLayer 類型的圖層(因?yàn)橐Y(jié)合貝塞爾曲線得到形狀路徑), 畫一個(gè)形狀那么就需要有位置
- (CAShapeLayer *)creatCircleShapWithPostion:(CGPoint)position
pathRect:(CGRect)rect
radius:(CGFloat)radius
{
CAShapeLayer *circleShap = [CAShapeLayer layer];
// 從貝塞爾曲線取到形狀
circleShap.path = [UIBezierPath bezierPathWithRoundedRect:frame cornerRadius:radius].CGPath;
// 雖然得到了形狀, 但是并沒有得到具體的 frame(bounds) 也就是實(shí)際上并沒有范圍 只是可以展現(xiàn)動(dòng)畫的效果 那么錨點(diǎn)其實(shí)就是設(shè)置的位置點(diǎn)
circleShap.position = position;
if (self.buttonType == DDFlashButtonInner)
{
# 在這里設(shè)置 frame 就是為了滿足我們想要的錨點(diǎn)位置讓動(dòng)畫效果動(dòng)起來, 下面也一樣, 可以不設(shè)置試試效果就明白了!
// circleShap.bounds = CGRectMake(0, 0, radius *2, radius *2);
circleShap.frame = CGRectMake(position.x-radius, position.y-radius, radius*2, radius*2);
// 線寬
circleShap.lineWidth = 1;
// 填充的顏色 不設(shè)置默認(rèn)就給黃色
circleShap.fillColor = self.flashColor ? self.flashColor.CGColor:[UIColor yellowColor].CGColor;
}else
{
circleShap.frame = self.bounds;
// 線寬
circleShap.lineWidth = 5;
circleShap.fillColor = [UIColor clearColor].CGColor;
// 邊緣線的顏色 不設(shè)置就默認(rèn)給個(gè)紫色
circleShap.strokeColor = self.flashColor ? self.flashColor.CGColor:[UIColor purpleColor].CGColor;
}
// 不透明度 要設(shè)置成透明的 不然內(nèi)部風(fēng)格的時(shí)候會(huì)畫出來圖案點(diǎn)點(diǎn)
circleShap.opacity = 0;
return circleShap;
}
第 7 步 : 把點(diǎn)擊的事件完成就 OK 了
- (void)didTap:(UITapGestureRecognizer *)tapGesture
{
// 獲取點(diǎn)擊點(diǎn)的位置
CGPoint tapLocation = [tapGesture locationInView:self];
// 定義一個(gè)圖層 下面分情況去給予不同形狀
CAShapeLayer *circleShape = nil;
// 默認(rèn)一個(gè)變化比例 1 倍
CGFloat scale = 1.0f;
// 獲取 View 的寬和高
CGFloat width = self.bounds.size.width, height = self.bounds.size.height;
if (self.buttonType == DDFlashButtonInner)
{
# 這里就是在視圖內(nèi)部效果, 就是以點(diǎn)擊的點(diǎn)為圓心 畫一個(gè)小圓(這里是半徑為1) 然后讓它動(dòng)畫起來 (不斷的變大并變透明) 所以放大倍數(shù)只要能到最大的變就行了 不一定非要這樣寫, 你開心就好!
CGFloat biggerEdge = width > height ? width :height;
CGFloat radius = 1
scale = biggerEdge / radius + 0.5;
# 調(diào)用方法獲得圖層 錨點(diǎn)位置就是點(diǎn)擊的位置
circleShape = [self creatCircleShapWithPostion:CGPointMake(tapLocation.x , tapLocation.y ) pathRect:CGRectMake(0, 0, radius * 2, radius * 2) radius:radius];
}else
{
# 這個(gè)是外部動(dòng)畫效果 設(shè)置能放大5.5倍
scale = 5.5f;
# 錨點(diǎn)位置在 View 的中心 這個(gè)圖層和 View 是一樣的形狀范圍
circleShape = [self creatCircleShapWithPostion:CGPointMake(width /2 , height / 2) pathRect:self.bounds radius:self.layer.cornerRadius];
}
// view圖層 上添加 有形狀的自定義圖層
[self.layer addSublayer:circleShape];
# 給自定義圖層添加動(dòng)畫
[circleShape addAnimation:[self createFlashAnimationWisthScale:scale duration:1.0f] forKey:nil];
}
最后說一句: 用的時(shí)候在 viewController 中引入, 創(chuàng)建自定義的 View 實(shí)例對象, 改變傳入的風(fēng)格和顏色就可以展示效果了!
iOS基礎(chǔ)-動(dòng)畫效果的總結(jié)--(CALayer — 粉骨碎身全不怕,要留清白在人間!<小拳石>動(dòng)畫的思維導(dǎo)圖基礎(chǔ)知識:iOS能夠?qū)崿F(xiàn)動(dòng)畫的方式:(如上圖)UIView基礎(chǔ)實(shí)現(xiàn)方式一UIView基礎(chǔ)實(shí)現(xiàn)方式二CoreAnimation實(shí)現(xiàn)方式動(dòng)畫的效果簡述:傳達(dá)狀態(tài)提高用戶對直接操作的感知幫助用戶可視化操作的結(jié)果UIVIew的基礎(chǔ)動(dòng)畫:UIKit直接將動(dòng)畫繼承到UIView類中,當(dāng)內(nèi)部的一些屬性發(fā)生改變時(shí),UIView將為這些改變提供動(dòng)畫支持.執(zhí)行動(dòng)畫的工作由UIView類自動(dòng)完成,但希望在...
原文鏈接:http://www.jianshu.com/p/c187c7005ce1
著作權(quán)歸作者所有,轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),并標(biāo)注“簡書作者”。
- iOS利用CALayer實(shí)現(xiàn)動(dòng)畫加載的效果
- iOS仿支付寶芝麻信用分?jǐn)?shù)儀表盤動(dòng)畫效果
- IOS 波紋進(jìn)度(waveProgress)動(dòng)畫實(shí)現(xiàn)
- IOS 圓球沿著橢圓軌跡做動(dòng)畫
- iOS實(shí)現(xiàn)知乎和途家導(dǎo)航欄漸變的文字動(dòng)畫效果
- iOS實(shí)現(xiàn)滾動(dòng)字幕的動(dòng)畫特效
- IOS實(shí)現(xiàn)視頻動(dòng)畫效果的啟動(dòng)圖
- iOS UITableView展開縮放動(dòng)畫實(shí)例代碼
- iOS動(dòng)畫之向右拉的抽屜3D效果
- iOS 基本動(dòng)畫、關(guān)鍵幀動(dòng)畫、利用緩動(dòng)函數(shù)實(shí)現(xiàn)物理動(dòng)畫效果
相關(guān)文章
淺談iOS開發(fā)如何適配暗黑模式(Dark Mode)
這篇文章主要介紹了淺談iOS開發(fā)如何適配暗黑模式(Dark Mode),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
iOS倒計(jì)時(shí)的實(shí)現(xiàn)方法
這篇文章主要為大家詳細(xì)介紹了iOS倒計(jì)時(shí)的實(shí)現(xiàn)方法,點(diǎn)擊進(jìn)行倒計(jì)時(shí)準(zhǔn)備,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03
IOS LaunchScreen設(shè)置啟動(dòng)圖片與啟動(dòng)頁停留時(shí)間詳解
這篇文章主要介紹了IOS LaunchScreen設(shè)置啟動(dòng)圖片與啟動(dòng)頁停留時(shí)間詳解的相關(guān)資料,需要的朋友可以參考下2017-02-02
iOS App中實(shí)現(xiàn)播放音效和音樂功能的簡單示例
這篇文章主要介紹了iOS App中實(shí)現(xiàn)播放音效和音樂功能的簡單示例,示例代碼為傳統(tǒng)的Objective-C,需要的朋友可以參考下2016-03-03
解決Xcode 8構(gòu)建版本iTunes Connect獲取不到應(yīng)用程序狀態(tài)的辦法
這篇文章主要介紹了關(guān)于解決Xcode 8構(gòu)建版本iTunes Connect獲取不到應(yīng)用程序狀態(tài)的辦法,需要的朋友可以參考下2017-03-03

