//
|
// TreeTeskVC.swift
|
// XQMuse
|
//
|
// Created by 无故事王国 on 2024/8/23.
|
//
|
|
import UIKit
|
import AVKit
|
import JQTools
|
import APNGKit
|
import UserDefaultsStore
|
|
let TreeTaskUpdate_Noti = Notification.Name.init(rawValue: "TreeTaskUpdate_Noti")
|
|
class TreeTeskVC: BaseVC {
|
|
private let cacheTreeInfoModel = UserDefaultsStore<TreeInfoModel>(uniqueIdentifier: "cacheTreeInfoModel")!
|
|
@IBOutlet weak var view_energy: UIView!
|
@IBOutlet weak var icon_energy: UILabel!
|
@IBOutlet weak var btn_exchange: TapBtn!
|
@IBOutlet weak var btn_watering: UIButton!
|
@IBOutlet weak var view_group: UIView!
|
@IBOutlet weak var view_group_inner: UIView!
|
@IBOutlet weak var btn_seedingAgain: UIButton!
|
@IBOutlet weak var view_progressTotal: UIView!
|
@IBOutlet weak var view_progress: UIView!
|
@IBOutlet weak var cons_progressHei: NSLayoutConstraint!
|
@IBOutlet weak var label_progress: UILabel!
|
|
private lazy var player:AVPlayer = {
|
let bgPath = Bundle.main.url(forResource: "bg", withExtension: "mov")
|
let p = AVPlayer(url: bgPath!)
|
p.isMuted = true
|
return p
|
}()
|
|
private lazy var playerLayer:AVPlayerLayer = {
|
let pLayer = AVPlayerLayer()
|
pLayer.videoGravity = .resize
|
return pLayer
|
}()
|
|
private lazy var taskListView:TreeTeskListView = {
|
let view = TreeTeskListView.jq_loadNibView()
|
return view
|
}()
|
|
private var treeTeskListSwipe:TreeTeskListSwipe = .down
|
private var settingModel = UserDefaultSettingViewModel.getSetting()
|
|
private var treeImage = UIImageView()
|
private var aPNGTreeImageView:APNGImageView?
|
private var aPNGSunImageView:APNGImageView?
|
private var aPNGActionImageView:APNGImageView?
|
|
private var treeInfoModel:TreeInfoModel?
|
|
private lazy var voicePlayer:AVPlayer = {
|
let p = AVPlayer()
|
return p
|
}()
|
|
override func viewDidDisappear(_ animated: Bool) {
|
super.viewDidDisappear(animated)
|
player.pause()
|
aPNGSunImageView?.stopAnimating()
|
aPNGTreeImageView?.stopAnimating()
|
}
|
|
override func viewDidAppear(_ animated: Bool) {
|
player.play()
|
aPNGSunImageView?.startAnimating()
|
aPNGTreeImageView?.startAnimating()
|
}
|
|
override func viewDidLayoutSubviews() {
|
super.viewDidLayoutSubviews()
|
playerLayer.frame = view.frame
|
|
view.bringSubviewToFront(self.view_energy)
|
view.bringSubviewToFront(self.btn_exchange)
|
view.bringSubviewToFront(self.btn_watering)
|
view.bringSubviewToFront(self.view_group)
|
view.bringSubviewToFront(self.btn_seedingAgain)
|
view.bringSubviewToFront(self.taskListView)
|
|
btn_seedingAgain.jq_borderWidth = 1
|
btn_seedingAgain.jq_borderColor = UIColor(hexString: "#8AAE65")
|
btn_seedingAgain.jq_addShadows(shadowColor: .white, corner: 20, radius: 5, offset: CGSize(width: 0, height: 0), opacity: 1)
|
|
taskListView.jq_addCorners(corner: [.topLeft,.topRight], radius: 20)
|
}
|
|
override func viewDidLoad() {
|
super.viewDidLoad()
|
title = "树苗打卡站"
|
btn_seedingAgain.isHidden = true
|
|
if settingModel!.userFirstOpenTreeTask{
|
DispatchQueue.main.asyncAfter(delay: 2.0) {
|
let h = (JQ_ScreenW - 90) * 0.8766
|
TreeTeskFirstRuleView.show(title: "心泉之树", content:"亲爱的家人,感谢您用心的交流。\n现在,您心灵之树的种子已经植入这片沃土,请以农夫的心态用心浇灌,不久的将来,将会长成苍天大树,结出丰硕的果实。加油哦!",textAlignment: .left,height: h,textTopOffset: 22)
|
self.voicePlayer.replaceCurrentItem(with: AVPlayerItem(url: URL(string: TreeLevel.level_1.sound)!))
|
self.voicePlayer.play()
|
}
|
}
|
|
getTreeData()
|
}
|
|
override func setUI() {
|
|
let btn = UIButton(type: .custom)
|
btn.setTitle("规则说明", for: .normal)
|
btn.setTitleColor(.black.withAlphaComponent(0.55), for: .normal)
|
btn.titleLabel?.font = .systemFont(ofSize: 14, weight: .medium)
|
btn.addTarget(self, action: #selector(ruleAction), for: .touchUpInside)
|
|
navigationItem.rightBarButtonItem = UIBarButtonItem(customView: btn)
|
|
btn_exchange.jq_cornerPartWithNib(byRoundingCorners: [.topLeft,.bottomLeft], radii: 17.5, size: CGSizeMake(98, 35))
|
|
playerLayer.player = player
|
view.layer.addSublayer(playerLayer)
|
player.play()
|
|
view_group_inner.jq_addCorners(corner: [.topLeft,.bottomRight], radius: 8)
|
|
|
if let sunApngImage = try? APNGImage(fileURL: Bundle.main.url(forResource: "apngb-animated_sun", withExtension: "png")!){
|
sunApngImage.numberOfPlays = 2
|
aPNGSunImageView = APNGImageView(image: sunApngImage)
|
view.addSubview(aPNGSunImageView!)
|
aPNGSunImageView?.layer.zPosition = -998
|
aPNGSunImageView!.snp.makeConstraints { make in
|
make.edges.equalToSuperview()
|
}
|
aPNGSunImageView!.startAnimating()
|
}
|
updateAni()
|
|
view.addSubview(taskListView)
|
taskListView.snp.makeConstraints { make in
|
make.left.right.equalToSuperview()
|
make.bottom.equalToSuperview().offset((JQ_ScreenW * 0.655 - 50))
|
make.height.equalTo(JQ_ScreenW * 0.655)
|
}
|
}
|
|
|
private func getTreeData(){
|
|
//缓存的树苗信息
|
if let cacheModel = cacheTreeInfoModel.allObjects().first{
|
treeInfoModel = cacheModel
|
updateTreeInfo()
|
}
|
|
Services.treeInfo().subscribe(onNext: {data in
|
if let m = data.data{
|
self.taskListView.setTreeInfoModel(m)
|
|
//检查hash,进行同步
|
// if m.toJSON()?.jq_hash() != self.treeInfoModel?.toJSON()?.jq_hash(){
|
self.treeInfoModel = m
|
self.updateTreeInfo()
|
self.updateAni(false)
|
try? self.cacheTreeInfoModel.save(m)
|
// }
|
}
|
}).disposed(by: disposeBag)
|
}
|
|
private func updateTreeInfo(){
|
btn_seedingAgain.isHidden = treeInfoModel!.treeLevelType != .level_10
|
|
// if treeLevel.rawValue != treeInfoModel?.treeLevelType.rawValue{
|
// treeLevel = treeInfoModel!.treeLevelType
|
// }
|
icon_energy.text = String(format: "当前能量值:%ld", treeInfoModel!.energyValue)
|
setProgress(current: treeInfoModel!.growthValue, total: treeInfoModel!.nextLevel)
|
}
|
|
@IBAction func sowAgainAction(_ sender: UIButton) {
|
Services.sowAgain().subscribe(onNext: {[weak self] _ in
|
self?.getTreeData()
|
if let soundURL = URL(string:TreeLevel.level_1.sound){
|
self?.voicePlayer.replaceCurrentItem(with: AVPlayerItem(url: soundURL))
|
self?.voicePlayer.play()
|
}
|
}).disposed(by: disposeBag)
|
}
|
|
override func setRx() {
|
NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, object: nil, queue: nil) { [weak self] _ in
|
self?.player.seek(to: CMTime.zero)
|
self?.player.play()
|
}
|
|
NotificationCenter.default.addObserver(forName: UIApplication.didEnterBackgroundNotification, object: nil, queue: nil) { [weak self] _ in
|
self?.player.pause()
|
self?.aPNGSunImageView?.stopAnimating()
|
self?.aPNGTreeImageView?.stopAnimating()
|
}
|
|
NotificationCenter.default.addObserver(forName: UIApplication.didBecomeActiveNotification, object: nil, queue: nil) { [weak self] _ in
|
if self?.navigationController?.tabBarController?.selectedIndex == 2{
|
self?.player.play()
|
self?.aPNGSunImageView?.startAnimating()
|
self?.aPNGTreeImageView?.startAnimating()
|
}
|
}
|
|
NotificationCenter.default.rx.notification(TreeTaskUpdate_Noti).take(until: self.rx.deallocated).subscribe(onNext: {[weak self] _ in
|
self?.getTreeData()
|
}).disposed(by: disposeBag)
|
|
taskListView.swipeClouse {[unowned self] dirition in
|
guard self.treeTeskListSwipe != dirition else {return}
|
self.treeTeskListSwipe = dirition
|
switch dirition{
|
case .down:
|
UIView.animate(withDuration: 0.3) {
|
self.taskListView.snp.updateConstraints { make in
|
make.left.right.equalToSuperview()
|
make.bottom.equalToSuperview().offset((JQ_ScreenW * 0.655 - 50))
|
make.height.equalTo(JQ_ScreenW * 0.655)
|
}
|
self.view.layoutIfNeeded()
|
}
|
case .up:
|
UIView.animate(withDuration: 0.3) {
|
self.taskListView.snp.updateConstraints { make in
|
make.left.right.equalToSuperview()
|
make.bottom.equalToSuperview()
|
make.height.equalTo(JQ_ScreenW * 0.655)
|
}
|
self.view.layoutIfNeeded()
|
}
|
}
|
}
|
|
taskListView.signSuccess {[weak self] in
|
self?.getTreeData()
|
}
|
}
|
|
// 0 - 100
|
private func setProgress(current:Int,total:Int){
|
guard total != 0 else {
|
self.label_progress.attributedText = AttributedStringbuilder.build().add(string: "0", withFont: .systemFont(ofSize: 12, weight: .bold), withColor: .white, indent: 0, lineSpace: 0).add(string: "\n/NAN", withFont: .systemFont(ofSize: 11,weight: .thin), withColor: .white).mutableAttributedString
|
return
|
}
|
|
let pix = view_progressTotal.height / Double(total)
|
let px = Double(current) * pix
|
let max = view_progressTotal.height - 5
|
cons_progressHei.constant = min(px,max)
|
|
self.label_progress.attributedText = AttributedStringbuilder.build().add(string: "\(current)", withFont: .systemFont(ofSize: 12, weight: .bold), withColor: .white, indent: 0, lineSpace: 0).add(string: "\n/\(total)", withFont: .systemFont(ofSize: 11,weight: .thin), withColor: .white).mutableAttributedString
|
self.label_progress.textAlignment = .center
|
|
UIView.animate(withDuration: 1.5) {
|
self.view_progressTotal.layoutIfNeeded()
|
self.view_progress.jq_gradientColor(colorArr: [UIColor(hexString: "#FCFECA")!.cgColor,UIColor(hexString: "#3CB56A")!.cgColor], cornerRadius: 2.5,startPoint: CGPoint(x: 0, y: 0),endPoint: CGPoint(x: 1, y: 1),clear: true)
|
}
|
}
|
|
//能量明细
|
@IBAction func energyDetailAction(_ sender: TapBtn) {
|
guard sceneDelegate!.checkisLoginState() else {return}
|
let vc = TreeTeskDetailVC()
|
push(vc: vc)
|
}
|
|
//兑换
|
@IBAction func exchangeAction(_ sender: TapBtn) {
|
guard sceneDelegate!.checkisLoginState() else {return}
|
let vc = TreeTeskEnergyExchangeVC()
|
push(vc: vc)
|
}
|
|
@IBAction func wateringAction(_ sender: UIButton) {
|
guard sceneDelegate!.checkisLoginState() else {return}
|
|
sender.isUserInteractionEnabled = false
|
|
if treeInfoModel == nil {return}
|
|
guard treeInfoModel!.energyValue != 0 else{
|
alert(msg: "已经没有能量值了,快去做任务吧");
|
sender.isUserInteractionEnabled = true
|
return
|
}
|
|
Services.watering().subscribe(onNext: {[weak self] data in
|
guard let weakSelf = self else { return }
|
if let m = data.data{
|
sender.isUserInteractionEnabled = true
|
if m.isNext{
|
let type = weakSelf.treeInfoModel?.treeLevelType ?? .level_1
|
weakSelf.treeInfoModel!.treeLevelType = TreeLevel(rawValue: type.rawValue + 1) ?? .level_1
|
|
let h = (JQ_ScreenW - 90) * 0.7729
|
TreeTeskFirstRuleView.show(title: "升级", content:"恭喜!你的树苗已升级为\(weakSelf.treeInfoModel!.treeLevelType.title)阶段!",textAlignment: .center,height: h,textTopOffset: 57)
|
|
if let soundURL = URL(string:weakSelf.treeInfoModel?.treeLevelType.sound){
|
weakSelf.voicePlayer.replaceCurrentItem(with: AVPlayerItem(url: soundURL))
|
weakSelf.voicePlayer.play()
|
}
|
weakSelf.updateAni()
|
weakSelf.getTreeData()
|
return
|
}
|
|
weakSelf.treeInfoModel?.growthValue = m.growthValue
|
weakSelf.treeInfoModel?.energyValue = 0
|
weakSelf.treeInfoModel?.nextLevel = m.nextLevel
|
weakSelf.updateTreeInfo()
|
NotificationCenter.default.post(name: UpdateUserProfile_Noti, object: nil)
|
}
|
}).disposed(by: disposeBag)
|
|
if let waterApngImage = try? APNGImage(fileURL: Bundle.main.url(forResource: "apngb-animated-flow", withExtension:"png")!){
|
waterApngImage.numberOfPlays = 2
|
aPNGActionImageView = APNGImageView(image: waterApngImage)
|
aPNGActionImageView!.alpha = 0
|
aPNGSunImageView?.contentMode = .scaleToFill
|
view.addSubview(aPNGActionImageView!)
|
aPNGActionImageView!.snp.makeConstraints { make in
|
make.center.equalToSuperview().inset(UIEdgeInsets(top: 90, left: 140, bottom: 0, right: 0))
|
make.width.equalTo(200)
|
make.height.equalTo(150)
|
}
|
UIView.animate(withDuration: 0.5) {
|
self.aPNGActionImageView!.alpha = 1.0
|
}
|
aPNGActionImageView!.startAnimating()
|
|
aPNGActionImageView!.onOnePlayDone.delegate(on: self) {[unowned self] a,b in
|
if b == 2{
|
sender.isUserInteractionEnabled = true
|
UIView.animate(withDuration: 0.5) {
|
self.aPNGActionImageView!.alpha = 0
|
}completion: { _ in
|
self.aPNGActionImageView!.removeFromSuperview()
|
}
|
}
|
}
|
}
|
}
|
|
@objc func jumpAction(){
|
// treeLevel = TreeLevel(rawValue: treeLevel.rawValue + 1) ?? TreeLevel.level_1
|
}
|
|
@objc func ruleAction(){
|
let vc = WebVC(type: .treeRule)
|
vc.title = "规则说明"
|
push(vc: vc)
|
}
|
|
private func updateAni(_ needAni:Bool = true){
|
let treeLevel = treeInfoModel?.treeLevelType ?? .level_1
|
|
guard let animateUrl = Bundle.main.url(forResource: treeLevel.aniResource, withExtension: "png") else {return}
|
guard let staticDroopUrl = Bundle.main.url(forResource: treeLevel.staticDroopResource, withExtension: "png") else {return}
|
|
if let treeApngImage = try? APNGImage(fileURL: animateUrl){
|
|
if treeLevel == .level_1{
|
treeApngImage.numberOfPlays = 1
|
}else{
|
treeApngImage.numberOfPlays = 0
|
}
|
|
if aPNGTreeImageView == nil{
|
aPNGTreeImageView = APNGImageView(image: treeApngImage)
|
aPNGTreeImageView?.tag = 10101
|
aPNGTreeImageView!.contentMode = .redraw
|
let tap = UITapGestureRecognizer(target: self, action: #selector(jumpAction))
|
aPNGTreeImageView!.addGestureRecognizer(tap)
|
}
|
|
if view.viewWithTag(10101) == nil{
|
view.addSubview(aPNGTreeImageView!)
|
}
|
|
let scale:Double = 0.55 //放大倍数
|
|
aPNGTreeImageView!.snp.remakeConstraints { make in
|
make.centerX.equalToSuperview().offset(-10)
|
make.bottom.equalToSuperview().offset(-220)
|
make.width.equalTo(642 * scale)
|
make.height.equalTo(731 * scale)
|
}
|
|
let duration = needAni ? 0.6:0
|
UIView.animate(withDuration: duration) {
|
self.aPNGTreeImageView?.alpha = 0
|
|
}completion: { state in
|
if state{
|
self.aPNGTreeImageView!.image = treeApngImage
|
UIView.animate(withDuration: 0.5, delay: 0.2) {
|
self.aPNGTreeImageView?.alpha = 1
|
}completion: { _ in
|
self.aPNGTreeImageView!.startAnimating()
|
|
if self.treeInfoModel?.status == .yes{
|
self.aPNGTreeImageView?.stopAnimating()
|
self.aPNGTreeImageView?.image = nil
|
self.aPNGTreeImageView?.staticImage = UIImage(contentsOfFile: staticDroopUrl.droppedScheme()!.absoluteString)
|
}
|
}
|
}
|
}
|
}
|
}
|
}
|
|
extension TreeTeskVC:CAAnimationDelegate{
|
func animationDidStart(_ anim: CAAnimation) {
|
print("开始动画")
|
treeImage.isUserInteractionEnabled = false
|
}
|
|
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
|
print("结束动画")
|
if anim.value(forKey: "customType") as! String == "ani_flower"{
|
|
|
}
|
}
|
}
|