例如: 秀场应用
因为秀场里面的动画,打赏主播,为了体现土豪,需要来一个游艇动画
是用户驱动的。
用户送了礼物,就得播放动画效果。
先送,先播放,
体现了队列的特性
本文介绍,屏幕上的飘屏动画例如,游戏获奖等
本文来一个,简单的 demo,留言飘屏
类似d幕,比d幕简单
基本实现: 分为动画视图,和动画队列视图 1, 动画视图 , FloatingView 动画, 从左往右拉,并,有些不同
动画使用 CAKeyframeAnimation
放在动画视图 , FloatingView 的
- (void)layoutSubviews
方法中,
- (void)layoutSubviews
的方法
有 [self setNeedsLayout];
也有 FloatingView 添加子视图,
( 第一次添加 UILabel )
为了配合,下面的动画队列视图,使用 CAKeyframeAnimation
的代理方法,
动画开始:
- (void)animationDidStart:(CAAnimation *)anim;
动画结束:
- (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;
这样,对于动画队列,
一个结束了,就开始下一个动画
2, 动画队列视图 , FloatingLabel继承自上面的动画视图,
实现了动画队列,和具体的动画视图 UILabel
动画队列的删队列,关键在于增删
一个结束,就开始删
// 当前队列有元素
if (weakSelf.attributeArr.count) {
// 删一个动画内容
[weakSelf.attributeArr removeObject:weakSelf.attributeArr.firstObject];
if (weakSelf.attributeArr.count != 0) {
// 驱动动画
[weakSelf addTrotAttribute:nil];
}
}
// 移除id
if (weakSelf.tipIdList.count) {
// 删一个
[weakSelf.tipIdList removeObjectAtIndex:0];
}
// 当无id时 说明已全部播放完
// 动画队列结束
if (weakSelf.tipIdList.count == 0) {
dispatch_async(dispatch_get_main_queue(), ^{
if (weakSelf.giftStopBlock) {
weakSelf.giftStopBlock();
}
});
}
队列的元素添加
- (void)addTrotAttribute:(FloatingAttribute *)attribute {
if (attribute) {
// 添加动画内容
[self.attributeArr addObject:attribute];
}
FloatingAttribute *trotingAtt = self.attributeArr[self.index];
if (!_currentLabel) {
// 第一次,创建展示的视图
_currentLabel = [[UILabel alloc] init];
_currentLabel.font = [UIFont systemFontOfSize:14];
_currentLabel.textColor = UIColor.redColor;
[self trotingWithAttribute:trotingAtt];
[self addTrotView:_currentLabel];
} else if (!self.isTroting) {
// 状态管理
// 当前没动画,才驱动新增加的
[self trotingWithAttribute:trotingAtt];
[self updateTroting];
}
}
注意点:
1, 动画的时长控制
就是修改 CAKeyframeAnimation
实例的 duration
字段
计算逻辑
// 文本宽度
CGSize textSize = [att.text sizeWithAttributes:@{NSFontAttributeName: _currentLabel.font}];
_currentLabel.frame = CGRectMake(0, 0, textSize.width, textSize.height);
__weak typeof(self) weakSelf = self;
[self troting:^{
// 文本宽度 + 动画容器的宽度
// 因为文本从容器的右边,整体移动到左边,消失
// 速度是,一秒钟前进 40 个 pt
CGSize trotContrinerSize = weakSelf.trotContaierView.frame.size;
weakSelf.duration = (trotContrinerSize.width + textSize.width) / 40;
}];
2, 动画停顿
文本的左边,从容器的右边出发,抵达容器的左边后,
停顿 3 秒
// 容器宽度 + 文本宽度
CGFloat len = (trotContainerSize.width + trotSize.width);
// 开始在容器右边, 抵达容器左边, 抵达容器左边,
// 文本的右边, 从容器的左边消失
self.flyingXAnimation.values = @[@(0), @(- trotContainerSize.width), @(- trotContainerSize.width), @(- len)];
// 停顿三秒
NSTimeInterval pause = 3.0;
// 总的时间:每秒跑 40 个 pt + 停顿的时间
NSTimeInterval total = _duration + pause;
// 容器的宽度 / 总长度
NSTimeInterval percent = trotContainerSize.width / len;
NSTimeInterval widthTime = percent * _duration /total ;
// 出发的时刻,
// 文本左边抵达,容器左边,开始停顿
// 文本再次出发
// 文本的右边,消失于容器的左边, 动画结束
self.flyingXAnimation.keyTimes = @[@0, @(widthTime), @(pause / total + widthTime), @(1)];
github repo
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)