ปัญหา
ฉันทริกเกอร์ภาพเคลื่อนไหวแบบสุ่มบน UIViews ที่เลือกโดยใช้ตัวจับเวลา แอนิเมชั่นทั้งหมดทำงานตามที่ตั้งใจไว้ แต่เป็นอันหนึ่งที่มีการเรียกวิธีการวาดของ CALayer หลังจากออกจากตัวเลือกตัวจับเวลา
คำอธิบายโดยละเอียด
เพื่อความชัดเจนและง่ายขึ้น ผมขอแผนผังการดำเนินการที่ทำไปแล้ว
แอนิเมชั่นทั้งหมดที่ฉันสร้างจนถึงตอนนี้ทำงานได้ตามที่ตั้งใจไว้: เป็นการผสมผสานระหว่าง CABasicAnimations บนมุมมองย่อย/เลเยอร์ย่อยที่มีอยู่ หรืออันใหม่ที่เพิ่มเข้าไปในลำดับชั้นการดูที่เลือก พวกมันถูกเข้ารหัสเป็นส่วนขยาย UIView เพื่อให้สามารถเรียกพวกมันในมุมมองใดก็ได้ โดยไม่คำนึงถึงมุมมองหรือตัวควบคุมมุมมองที่มีมุมมองนั้นอยู่ ก็ใช้งานได้ทั้งหมดยกเว้นมุมมองเดียว
ฉันได้สร้างคลาส CALayer แบบกำหนดเองซึ่งประกอบด้วยรูปแบบการวาดบน CALayer ในส่วนขยายของคลาสที่กำหนดเองนี้ มีวิธีทำให้รูปแบบเหล่านั้นเคลื่อนไหว (ดูโค้ดต่อไปนี้) โดยรวมแล้ว เมื่อฉันไปถึงขั้นตอน/วิธีการ animate selected view
และเรียกใช้ภาพเคลื่อนไหวนี้ นี่คือสิ่งที่ควรเกิดขึ้น:
- วิธีการชื่อ animatePattern เรียกว่า
- เมธอดนี้จะเพิ่มคลาส CALayer แบบกำหนดเองให้กับมุมมองที่เลือก จากนั้นเรียกส่วนขยายภาพเคลื่อนไหวของเลเยอร์นี้
ปัญหา: หากภาพเคลื่อนไหวอื่นๆ ทั้งหมด การวาดภาพทั้งหมดจะดำเนินการก่อนออกจากขั้นตอน/วิธีการ animate selected view
ในกรณีดังกล่าว วิธีการวาดคลาส CALayer แบบกำหนดเองจะเรียกว่า หลัง ทางออกของเมธอด performAnimation
ซึ่งจะส่งผลให้ภาพเคลื่อนไหวเสียหาย
ฉันควรเพิ่มว่าฉันได้ลองใช้แอนิเมชั่นคลาส CALayer ที่กำหนดเองในสนามเด็กเล่นที่แยกจากกันและง่ายขึ้นและทำงานได้ดี (ฉันเพิ่มเลเยอร์ที่กำหนดเองให้กับ UIView
ในวิธี viewDidLoad
ของ UIViewController จากนั้นฉันจะเรียกภาพเคลื่อนไหวของเลเยอร์ในวิธี viewDidAppear
ของ UIViewController)
รหัส
วิธีการที่ถูกเรียกโดย
animate selected view
step/method:func animatePattern(for duration: TimeInterval = 1) { let patternLayer = PatternLayer(effectType: .dark) patternLayer.frame = self.bounds self.layer.addSublayer(patternLayer) patternLayer.play(for: duration) }
(โปรดทราบว่าวิธีนี้อยู่ในส่วนขยาย UIView ดังนั้น self
ที่นี่จึงแสดงถึง UIView ที่มีการเรียกภาพเคลื่อนไหว)
คลาส CALayer แบบกำหนดเองที่เรียบง่าย:
override var bounds: CGRect { didSet { self.setNeedsDisplay() } // Initializers override init() { super.init() self.setNeedsDisplay() } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } init(effectType: EffectType){ super.init() // sets various properties self.setNeedsDisplay() } // Drawing override func draw(in ctx: CGContext) { super.draw(in: ctx) guard self.frame != CGRect.zero else { return } self.masksToBounds = true // do the drawings }
ส่วนขยายภาพเคลื่อนไหวของคลาส CALayer ที่กำหนดเอง:
func play(for duration: Double, removeAfterCompletion: RemoveAfterCompletion = .no) { guard self.bounds != CGRect.zero else { print("Cannot animate nil layer") return } CATransaction.begin() CATransaction.setCompletionBlock { if removeAfterCompletion.removeStatus { if case RemoveAfterCompletion.yes = removeAfterCompletion { self.fadeOutDuration = 0.0 } self.fadeToDisappear(duration: &self.fadeOutDuration) } } // perform animations CATransaction.commit() }
ความพยายามจนถึงขณะนี้
ฉันได้พยายามบังคับวาดเลเยอร์โดยการแทรก setNeedsDisplay
/ setNeedsLayout
ที่ตำแหน่งต่างๆ ในโค้ด แต่มันไม่ทำงาน: การดีบักเมธอด draw
ของคลาส CALayer แบบกำหนดเองนั้นเข้าถึงอย่างต่อเนื่องหลังจากออกจากเมธอด performAnimation
ในขณะที่มันควรจะถูกเรียกเมื่อ เฟรมของเลเยอร์ได้รับการแก้ไขในวิธี animatePattern
ฉันต้องพลาดบางสิ่งบางอย่างที่ค่อนข้างชัดเจน แต่ตอนนี้ฉันกำลังวิ่งวนเป็นวงกลม และฉันจะซาบซึ้งกับสายตาคู่ใหม่ที่ได้จ้องมองมัน
ขอขอบคุณล่วงหน้าที่สละเวลาพิจารณาปัญหานี้! ดีที่สุด,