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

}

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容