swift-05.01

礼物连击动画

基础知识

digitalLable:1.画文字  2.lable动画回调

channelView:0.几种状态 1.当执行完(lable动画回调)--检测是否有缓存数量-有就递归执行-count==0   2.单模型缓存--数量  3.动画  chanel回调 4.提供对外函数--增加正在执行动画的数量---number

containnerView:0.当执行chanel回调-检测多模型缓存--数量和类型--如果有就赋值数量和第一个模型--执行动画  1.提供对外插入模型方法:1.1检测是否和正在执行的相同--如果有增加chinel缓存数量--没有执行1.2   1.2检测是否有空通道有就直接赋值执行动画---没有执行1.3  1.3前两部没有加入到 模型缓存中

try处理

return try! userInfo.build()

userInfo.build()返回值中有throw  需要进行 try!处理

0.层级 关系 view  containView  channelView digitalview HYGiftModel

view: 只传入model就可以

containView: 1.判断是否有闲置通道  2.是否礼物模型相同 3.单通道的缓存数量

channelView: 对单个礼物的状态  和 缓存数量的执行 和 给模型赋值后执行动画

HYGiftModel: 判断礼物是否相同(重写isEqual 根据giftname 和发送者name )

1.HYDigitLabel  

1.0画出数字text   1.1设置开始动画方法----结束并且有回调

func startScaleAnimating(_ complection : (() -> Void)? = nil) {

UIView.animateKeyframes(withDuration: 1, delay: 0, options: [], animations: {

UIView.addKeyframe(withRelativeStartTime: 0, relativeDuration: 0.4, animations: {

self.transform = CGAffineTransform(scaleX: 3.0, y: 3.0)

})

UIView.addKeyframe(withRelativeStartTime: 0.4, relativeDuration: 0.8, animations: {

self.transform = CGAffineTransform(scaleX: 0.7, y: 0.7)

})

UIView.addKeyframe(withRelativeStartTime: 0.8, relativeDuration: 1, animations: {

self.transform = CGAffineTransform.identity

})

}) { (_) in

complection?()

}

}

2.HYGiftChannelView  通道view

class HYGiftChannelView: UIView {

// MARK: 控件属性

@IBOutlet weak var bgView: UIView!

@IBOutlet weak var iconImageView: UIImageView!

@IBOutlet weak var senderLabel: UILabel!

@IBOutlet weak var giftDescLabel: UILabel!

@IBOutlet weak var giftImageView: UIImageView!

@IBOutlet weak var digitLabel: HYDigitLabel!

// MARK: 定义属性

var finishedCallback : ((HYGiftChannelView) -> Void)?

var state : ChannerlViewState = .idle

var cacheNumber : Int = 0

fileprivate var currentNumber : Int = 0

var giftModel : HYGiftModel?  {

didSet {

// 1.校验模型是否有值

guard let giftModel = giftModel else {

return

}

// 2.将giftModel中属性设置到控件中

iconImageView.image = UIImage(named: giftModel.senderIcon)

senderLabel.text = giftModel.senderName

giftDescLabel.text = "送出礼物【\(giftModel.giftName)"

giftImageView.image = UIImage(named: giftModel.giftIcon)

// 3.将channelView展示出来

performShowAnimating()

}

}

}

enum ChannerlViewState {

case idle  闲置

case animating  正在执行

case endWating 等待结束

case ending 结束

}

2.1

fileprivate func performShowAnimating() {

状态改变

state = .animating

UIView.animate(withDuration: 0.25, animations: {

self.frame.origin.x = 0

self.alpha = 1.0

}) { (_) in

横条停到位置后----开始执行数字弹跳动画

self.performDigitAnimating()

}}

数字弹跳动画

fileprivate func performDigitAnimating() {

// 1.将digitLabel的alpha值设置为1

digitLabel.alpha = 1

// 2.设置digitLabel上面显示的数字

currentNumber += 1

digitLabel.text = " x\(currentNumber)"

// 3.执行动画

digitLabel.startScaleAnimating {

if self.cacheNumber > 0 {

self.cacheNumber -= 1

self.performDigitAnimating()

相当于递归执行 直到self.cacheNumber = 0

} else {

如果没有self.cacheNumber 状态就改变

self.state = .endWating

等待执行结束动画

self.perform(#selector(self.performEndAnimating), with: nil, afterDelay: 3.0)

}

}

@objc fileprivate func performEndAnimating() {

状态改变--正在结束  往右走的过程

self.state = .ending

UIView.animate(withDuration: 1, animations: {

self.frame.origin.x = UIScreen.main.bounds.width

}) { (_) in

self.alpha = 0.0

self.state = .idle

self.digitLabel.alpha = 0

self.currentNumber = 0

self.cacheNumber = 0

self.frame.origin.x = -self.frame.width

self.giftModel = nil

结束完成通知控制器,看是否还有任务需要执行

self.finishedCallback?(self)

}

}

// MARK:- 对外提供的函数---对单一通道的处理

extension HYGiftChannelView {

func addOnceToCache() {

若果正在等待结束----让其取消等待--立即执行-改变状态

if state == .endWating {

NSObject.cancelPreviousPerformRequests(withTarget: self)

self.state = .animating

performDigitAnimating()

} else {

其他情况就让其缓存+1

cacheNumber += 1

}

}

}

对containView处理

extension HYGiftContainerView {

fileprivate func setupUI() {

// 1.根据当前的渠道数,创建HYGiftChannelView

let w : CGFloat = frame.width

let h : CGFloat = 40

let x : CGFloat = -w

for i in 0..<2 {

let y : CGFloat = (h + 10) * CGFloat(i)

let channelView = HYGiftChannelView.loadChannelView()

channelView.frame = CGRect(x: x, y: y, width: w, height: h)

channelView.alpha = 0.0

addSubview(channelView)

channelViews.append(channelView)

channelView.finishedCallback = {[unowned self] (channelView) in

// 1.检查缓存中是否有内容

guard self.cacheGiftModels.count != 0 else {

return

}

// 2.取出模型

let firstGiftModel = self.cacheGiftModels.first!

self.cacheGiftModels.removeFirst()

// 3.取出和giftModel相同模型的个数

var cacheNumber = 0

for i in (0..<self.cacheGiftModels.count).reversed() {

if self.cacheGiftModels[i].isEqual(firstGiftModel) {

cacheNumber += 1

self.cacheGiftModels.remove(at: i)

}

}

// 4.让闲置的channelView执行缓存中礼物模型的动画

channelView.cacheNumber = cacheNumber

channelView.giftModel = firstGiftModel

}

}

}

}

对外提供的函数--如何调用

extension HYGiftContainerView {

func insertGiftModel(_ giftModel : HYGiftModel) {

// 1.判断是否有正在执行动画的渠道的模型和新插入的模型一致

if let channelView = checkModelInChannerView(giftModel) {

channelView.addOnceToCache()

return

}

// 2.有没有闲置的channelView可以用于展示的礼物

if let channelView = checkIdleChannelView() {

channelView.giftModel = giftModel

return

}

// 3.将模型添加到缓存中

cacheGiftModels.append(giftModel)

}

fileprivate func checkModelInChannerView(_ newGiftModel : HYGiftModel) -> HYGiftChannelView? {

// return channelViews.filter({ newGiftModel.isEqual($0.giftModel) }).first

for channelView in channelViews {

if newGiftModel.isEqual(channelView.giftModel) && channelView.state != .ending {

return channelView

}

}

return nil

}

fileprivate func checkIdleChannelView() -> HYGiftChannelView? {

// return channelViews.filter({ $0.state == .idle }).first

for channelView in channelViews {

if channelView.state == .idle {

return channelView

}

}

return nil

}

}

模型的处理

class HYGiftModel : NSObject {

var senderName : String = ""

var senderIcon : String = ""

var giftIcon : String = ""

var giftName : String = ""

init(senderName : String, senderIcon : String, giftIcon : String, giftName : String) {

self.senderName = senderName

self.senderIcon = senderIcon

self.giftIcon = giftIcon

self.giftName = giftName

}

override func isEqual(_ object: Any?) -> Bool {

// 1.判断传入的内容是否有值

guard let object = object as? HYGiftModel else {

return false

}

// 2.判断赠送者和赠送的礼物名称是否相同

return object.senderName == senderName && object.giftName == giftName

}

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,817评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,329评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,354评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,498评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,600评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,829评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,979评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,722评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,189评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,519评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,654评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,329评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,940评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,762评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,993评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,382评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,543评论 2 349

推荐阅读更多精彩内容