《最美有物》中的點贊效果大家可以看下,在簡書上也看到過安卓版本的。分析它的動畫效果划乖,最近,利用自己閑暇時間用OC做了個Demo挤土,先看下Demo運行效果:
頁面展示及注意:
- 默認都是白色琴庵,并且也都是默認圖片。
- 當點擊某一個視圖時候仰美,兩個表情都要上升迷殿,利用時間也一樣。下降也一樣咖杂。
- 點擊一個視圖庆寺,背景設置為黃色,另一個表情圖片還原為默認圖片诉字,背景設置成白色懦尝。
- 點擊之后再下降到最初位置的image是動畫中最后一張image。
- 占比發(fā)生改變壤圃,占比字樣隨著PLSmileView高度變化而變化陵霉,其字樣透明度也在不斷發(fā)生變化。占比字樣的NSTextAlignmentCenter設置埃唯。
- 大背景PLBackView的透明度也在變化撩匕。
- “喜歡”被點擊之后,上升到最高點時候墨叛,會有個星星閃爍止毕。
大背景文件: PLBackView.h 和 PLBackView.m
笑臉的封裝文件:PLSmileView.h 和 PLSmileView.m
引用:(兩步即可)
1、在控制器視圖添加:
就按例子所說漠趁,計算比例之前就先知道無感人數(shù) \ 喜歡人數(shù) \ 總人數(shù)(無感 + 喜歡)扁凛。
DislikeCount:無感人數(shù)
likeCount:喜歡人數(shù),比例值在內(nèi)部計算闯传。
-
[[UIColor blackColor] colorWithAlphaComponent:0] 背景透明谨朝,而子視圖不透明。參照:iOS 父子視圖的hidden\Alpha\Opaque\clearColor影響簡介
// 添加視圖 24是無感的人數(shù) 75是喜歡的人數(shù) PLBackView *backView = [PLBackView backViewWithDislikeCount:24 likeCount: 75]; backView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0]; backView.frame = self.view.bounds; [self.view addSubview:backView];
2、設置屬性:
因為backView.frame = self.view.bounds;所以字币,相對于控制器view的frame值则披,就是在backView中真正位置。
tf: 是添加在控制器view上的文本框
disLikeFrame:“無感”frame
-
likeFrame: “喜歡”frame
// 傳入“無感”視圖的frame 30是tf與“無感”的間距 20是大圖片與“無感”的x方向間距 backView.disLikeFrame = CGRectMake(CGRectGetMaxX(tf.frame) + 30, CGRectGetMaxY(bgIV.frame) + 20, 0, 0); // 傳入“喜歡”視圖的frame 30是“無感”與“喜歡”之間間距 20是大圖片與“喜歡”的x方向間距 backView.likeFrame = CGRectMake(CGRectGetMaxX(backView.disLikeFrame)+ 30, CGRectGetMaxY(bgIV.frame) + 20, 0, 0);
demo地址:PLSmileViewDemo
部分注意點: (具體請看demo代碼)
1洗出、占比計算
在創(chuàng)建PLBackView實例視圖時候士复,傳入了無感 喜歡人數(shù),暫且翩活,用成員變量保存起來阱洪,先不計算各自固定占比。等到菠镇,任何一個笑臉被點擊(點擊那個笑臉人數(shù)+1)的時候冗荸,真正用到動態(tài)占比的時候,直接計算動態(tài)占比利耍。懶加載蚌本!
1.1 保存原始人數(shù)
+ (instancetype)backViewWithDislikeCount:(NSUInteger)disLikeCount likeCount:(NSUInteger)likeCount
{
PLBackView *bv = [[[NSBundle mainBundle] loadNibNamed:@"PLBackView" owner:nil options:nil] lastObject];
bv.disLikeCount = disLikeCount;
bv.likeCount = likeCount;
bv.clickEnable = YES;
return bv;
}
1.2 在點擊了任何一個笑臉,或者來回多次點擊時候隘梨,占比要設置為0魂毁,之后 重新獲取。
// 1出嘹、比例清空 從懶加載中 獲取最新的比例,防止 來回點擊喜歡與不喜歡 視圖時候咬崔,占比發(fā)生相應的變化
self.disLikeScale = 0.0;
self.likeScale = 0.0;
// 2税稼、判斷點擊的是無感 還是 喜歡 視圖,相應的人數(shù)+1垮斯,同時郎仆,非點擊的那個視圖 背景填充設置為非黃色,且兜蠕,圖片賦值成最初圖片扰肌。
if (smileView.type == PLSmileViewDislikeType) {
_likeIV.fillYellowColor = NO;
// 點擊的是“不喜歡” 人數(shù)加1
self.disLikeCountMut = self.disLikeCount+1;
self.likeCountMut = self.likeCount;
_dislikeIV.maxScaleValue = self.disLikeScale; // 最大值
// 另一個圖片 還原最初的圖片
_likeIV.imageName = @"like_normal";
}else
{
_dislikeIV.fillYellowColor = NO;
// 點擊的是“喜歡”人數(shù)加1
self.likeCountMut = self.likeCount+1;
self.disLikeCountMut = self.disLikeCount;
_likeIV.maxScaleValue = self.likeScale; // 最大值
_dislikeIV.imageName = @"dislike_normal";
}
// 3、 懶加載---比例小數(shù)點第三位要滿5進1熊杨,0.2475 約等于 0.25
#pragma - lazy
- (CGFloat)disLikeScale
{
if (!_disLikeScale) {
_disLikeScale = ((CGFloat)_disLikeCountMut / (_disLikeCountMut + _likeCountMut))+0.005; // 0.2475 約等于 0.25
}
return _disLikeScale;
}
- (CGFloat)likeScale
{
if (!_likeScale) {
_likeScale = ((CGFloat)_likeCountMut / (_disLikeCountMut + _likeCountMut))+0.005; // 0.2475 約等于 0.25
}
return _likeScale;
}
2曙旭、上升動畫--定時器
通過定時器使PLSmileView實例視圖的占比scale,從0增加到對應的maxScaleValue(無感maxScaleValue為 _disLikeScale晶府, 喜歡maxScaleValue為_likeScale)桂躏。上升是共同的時間,下降也是川陆,利用時間相同剂习,這就需要算出,各自變化的幅度是多少。
1鳞绕、找出高低各自對應的幅度值
CGFloat addOffsetMin = 0.01;
CGFloat addOffsetMax = 0.0;
// 循環(huán)次數(shù)
NSUInteger count = 0;
CGFloat minScale = MIN(self.disLikeScale, self.likeScale);
count = minScale / addOffsetMin;
addOffsetMax = (1 - minScale) / count;
self.count = count;
self.addOffsetMax = addOffsetMax;
self.addOffsetMin = addOffsetMin;
//開始上升 傳scale
__block CGFloat disLikeScale0 = 0.0;
__block CGFloat likeScale0 = 0.0;
[NSTimer scheduledTimerWithTimeInterval:0.01 repeats:YES block:^(NSTimer * _Nonnull timer) {
if (self.disLikeScale < self.likeScale) { // 喜歡較高 addOffsetMax屬于喜歡
disLikeScale0 += addOffsetMin;
likeScale0 += addOffsetMax;
}else{ // 不喜歡較高 addOffsetMax屬于不喜歡
disLikeScale0 += addOffsetMax;
likeScale0 += addOffsetMin;
}
// 傳遞比例 不斷上升
_dislikeIV.scale = disLikeScale0;
_likeIV.scale = likeScale0;
// 字體的alpha變化
self.fontAlpha += (CGFloat)1/count;
// 不斷上升的過程中 比例字數(shù)位置 也在不斷上升
[self setNeedsDisplay];
// 上升到最高點就停止計時器
if (disLikeScale0 >= _disLikeScale && [timer isValid]) {
[timer invalidate];
timer = nil;
}
}];
2失仁、在PLSmileView.m內(nèi)
/// 不斷改變的比例
- (void)setScale:(CGFloat)scale
{
_scale = scale;
// 高度 y值隨著變化
self.height = (scale <= 0?_originalH:_originalH + MAXHEIGHT * scale);
self.y = _originalY - MAXHEIGHT * scale;
// 繪制
[self setNeedsDisplay];
}
3、PLsmileView實例視圖上升--[self setNeedsDisplay];
1们何,畫背景圓角矩形框 self.color指填充的顏色
if (_scale == 0) {
self.color = [UIColor whiteColor];
}
// 畫實心背景 圓角邊框
UIBezierPath *borderB = [UIBezierPath bezierPathWithRoundedRect:self.bounds cornerRadius:self.width * 0.5];
borderB.lineWidth = 5; // 邊框?qū)挾?[self.color setFill];
[[UIColor greenColor] setStroke]; // 描邊顏色
[borderB fill];
[borderB stroke];
// 哭臉 與 笑臉 imageView 始終處在頂端 2.5是表情imageView 與 其父視圖self的y值差距(imageView是addSubview到self上的)
self.imageIv.centerX = self.width * 0.5;
self.imageIv.y = 2.5;
4萄焦、 imageView圖片改變
imageView圖片不斷改變形成動畫,圖片不多的情況下可以使用animationImages垂蜗,在圖片比較多的情況下楷扬,這種方式不會自動清理image,所以 使用了了NSTimer
// “喜歡”的動畫 總27張
__block int i = 0;
[NSTimer scheduledTimerWithTimeInterval:0.02 repeats:YES block:^(NSTimer * _Nonnull timer) {
i++;
self.imageIv.image = [UIImage imageNamed:[NSString stringWithFormat:@"like_%d", (i + 1)]];
if ((i+1 == 27) && [timer isValid]) { // NStimer停止
[timer invalidate];
timer = nil;
}
}];