《最美有物》中的點(diǎn)贊效果大家可以看下,在簡(jiǎn)書(shū)上也看到過(guò)安卓版本的。分析它的動(dòng)畫(huà)效果,最近,利用自己閑暇時(shí)間用OC做了個(gè)Demo,先看下Demo運(yùn)行效果:

頁(yè)面展示及注意:
- 默認(rèn)都是白色,并且也都是默認(rèn)圖片。
- 當(dāng)點(diǎn)擊某一個(gè)視圖時(shí)候,兩個(gè)表情都要上升,利用時(shí)間也一樣。下降也一樣。
- 點(diǎn)擊一個(gè)視圖,背景設(shè)置為黃色,另一個(gè)表情圖片還原為默認(rèn)圖片,背景設(shè)置成白色。
- 點(diǎn)擊之后再下降到最初位置的image是動(dòng)畫(huà)中最后一張image。
- 占比發(fā)生改變,占比字樣隨著PLSmileView高度變化而變化,其字樣透明度也在不斷發(fā)生變化。占比字樣的NSTextAlignmentCenter設(shè)置。
- 大背景PLBackView的透明度也在變化。
- “喜歡”被點(diǎn)擊之后,上升到最高點(diǎn)時(shí)候,會(huì)有個(gè)星星閃爍。
大背景文件: PLBackView.h 和 PLBackView.m
笑臉的封裝文件:PLSmileView.h 和 PLSmileView.m
引用:(兩步即可)
1、在控制器視圖添加:
就按例子所說(shuō),計(jì)算比例之前就先知道無(wú)感人數(shù) \ 喜歡人數(shù) \ 總?cè)藬?shù)(無(wú)感 + 喜歡)。
DislikeCount:無(wú)感人數(shù)
likeCount:喜歡人數(shù),比例值在內(nèi)部計(jì)算。
-
[[UIColor blackColor] colorWithAlphaComponent:0] 背景透明,而子視圖不透明。參照:iOS 父子視圖的hidden\Alpha\Opaque\clearColor影響簡(jiǎn)介
// 添加視圖 24是無(wú)感的人數(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、設(shè)置屬性:
因?yàn)閎ackView.frame = self.view.bounds;所以,相對(duì)于控制器view的frame值,就是在backView中真正位置。
tf: 是添加在控制器view上的文本框
disLikeFrame:“無(wú)感”frame
-
likeFrame: “喜歡”frame
// 傳入“無(wú)感”視圖的frame 30是tf與“無(wú)感”的間距 20是大圖片與“無(wú)感”的x方向間距 backView.disLikeFrame = CGRectMake(CGRectGetMaxX(tf.frame) + 30, CGRectGetMaxY(bgIV.frame) + 20, 0, 0); // 傳入“喜歡”視圖的frame 30是“無(wú)感”與“喜歡”之間間距 20是大圖片與“喜歡”的x方向間距 backView.likeFrame = CGRectMake(CGRectGetMaxX(backView.disLikeFrame)+ 30, CGRectGetMaxY(bgIV.frame) + 20, 0, 0);
demo地址:PLSmileViewDemo
部分注意點(diǎn): (具體請(qǐng)看demo代碼)
1、占比計(jì)算
在創(chuàng)建PLBackView實(shí)例視圖時(shí)候,傳入了無(wú)感 喜歡人數(shù),暫且,用成員變量保存起來(lái),先不計(jì)算各自固定占比。等到,任何一個(gè)笑臉被點(diǎn)擊(點(diǎn)擊那個(gè)笑臉人數(shù)+1)的時(shí)候,真正用到動(dòng)態(tài)占比的時(shí)候,直接計(jì)算動(dòng)態(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 在點(diǎn)擊了任何一個(gè)笑臉,或者來(lái)回多次點(diǎn)擊時(shí)候,占比要設(shè)置為0,之后 重新獲取。
// 1、比例清空 從懶加載中 獲取最新的比例,防止 來(lái)回點(diǎn)擊喜歡與不喜歡 視圖時(shí)候,占比發(fā)生相應(yīng)的變化
self.disLikeScale = 0.0;
self.likeScale = 0.0;
// 2、判斷點(diǎn)擊的是無(wú)感 還是 喜歡 視圖,相應(yīng)的人數(shù)+1,同時(shí),非點(diǎn)擊的那個(gè)視圖 背景填充設(shè)置為非黃色,且,圖片賦值成最初圖片。
if (smileView.type == PLSmileViewDislikeType) {
_likeIV.fillYellowColor = NO;
// 點(diǎn)擊的是“不喜歡” 人數(shù)加1
self.disLikeCountMut = self.disLikeCount+1;
self.likeCountMut = self.likeCount;
_dislikeIV.maxScaleValue = self.disLikeScale; // 最大值
// 另一個(gè)圖片 還原最初的圖片
_likeIV.imageName = @"like_normal";
}else
{
_dislikeIV.fillYellowColor = NO;
// 點(diǎn)擊的是“喜歡”人數(shù)加1
self.likeCountMut = self.likeCount+1;
self.disLikeCountMut = self.disLikeCount;
_likeIV.maxScaleValue = self.likeScale; // 最大值
_dislikeIV.imageName = @"dislike_normal";
}
// 3、 懶加載---比例小數(shù)點(diǎn)第三位要滿(mǎn)5進(jìn)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、上升動(dòng)畫(huà)--定時(shí)器
通過(guò)定時(shí)器使PLSmileView實(shí)例視圖的占比scale,從0增加到對(duì)應(yīng)的maxScaleValue(無(wú)感maxScaleValue為 _disLikeScale, 喜歡maxScaleValue為_(kāi)likeScale)。上升是共同的時(shí)間,下降也是,利用時(shí)間相同,這就需要算出,各自變化的幅度是多少。
1、找出高低各自對(duì)應(yīng)的幅度值
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;
//開(kāi)始上升 傳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;
// 不斷上升的過(guò)程中 比例字?jǐn)?shù)位置 也在不斷上升
[self setNeedsDisplay];
// 上升到最高點(diǎn)就停止計(jì)時(shí)器
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實(shí)例視圖上升--[self setNeedsDisplay];
1,畫(huà)背景圓角矩形框 self.color指填充的顏色
if (_scale == 0) {
self.color = [UIColor whiteColor];
}
// 畫(huà)實(shí)心背景 圓角邊框
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圖片不斷改變形成動(dòng)畫(huà),圖片不多的情況下可以使用animationImages,在圖片比較多的情況下,這種方式不會(huì)自動(dòng)清理image,所以 使用了了NSTimer
// “喜歡”的動(dòng)畫(huà) 總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;
}
}];