创建雨码矩阵效果
Creating raining code Matrix effect
创建了一个 CATextLayer 的子 class,我在其中附加了淡入动画,然后将其添加到附加了 dropThru 动画的 CATextLayer。尝试创建矩阵电影下雨代码效果的目标。工作得相当好,但事实上它缓慢但肯定会把自己推入地下,我怀疑是因为我不断添加越来越多的层。如何检测图层何时离开屏幕以便我可以将其删除。
这是代码...
class CATextSubLayer: CATextLayer, CAAnimationDelegate {
private var starter:Float!
private var ender:Float!
required override init(layer: Any) {
super.init(layer: layer)
//UIFont.availableFonts()
self.string = randomString(length: 1)
self.backgroundColor = UIColor.black.cgColor
self.foregroundColor = UIColor.white.cgColor
self.alignmentMode = kCAAlignmentCenter
self.font = CTFontCreateWithName("AvenirNextCondensed-BoldItalic" as CFString?, fontSize, nil)
self.fontSize = 16
self.opacity = 0.0
makeFade()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
fatalError("init(coder:) has not been implemented")
}
func randomString(length: Int) -> String {
let letters : NSString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
let len = UInt32(letters.length)
var randomString = ""
for _ in 0 ..< length {
let rand = arc4random_uniform(len)
var nextChar = letters.character(at: Int(rand))
randomString += NSString(characters: &nextChar, length: 1) as String
}
return randomString
}
func makeFade() {
let rands = Double(arc4random_uniform(UInt32(4)))
let fadeInAndOut = CABasicAnimation(keyPath: "opacity")
fadeInAndOut.duration = 16.0;
fadeInAndOut.repeatCount = 1
fadeInAndOut.fromValue = 0.0
fadeInAndOut.toValue = 1
fadeInAndOut.isRemovedOnCompletion = true
fadeInAndOut.fillMode = kCAFillModeForwards;
fadeInAndOut.delegate = self
fadeInAndOut.beginTime = CACurrentMediaTime() + rands
self.add(fadeInAndOut, forKey: "opacity")
}
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
self.removeAllAnimations()
}
}
与外部 loop/View 控制器..
class ViewController: UIViewController, CAAnimationDelegate {
var beeb: CATextSubLayer!
var meeb: CATextLayer!
var lines = [Int]()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.black
// Do any additional setup after loading the view, typically from a nib.
meeb = CATextLayer()
for bing in stride(from:0, to: Int(view.bounds.width), by: 16) {
lines.append(bing)
}
for _ in 0 ..< 9 {
Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(makeBeeb), userInfo: nil, repeats: true)
}
}
func makeBeeb() {
let rands = Double(arc4random_uniform(UInt32(4)))
let beeb = CATextSubLayer(layer: meeb)
let randx = Int(arc4random_uniform(UInt32(lines.count)))
let monkey = lines[randx]
beeb.frame = CGRect(x: monkey, y: 0, width: 16, height: 16)
let dropThru = CABasicAnimation(keyPath: "position.y")
dropThru.duration = 12.0;
dropThru.repeatCount = 1
dropThru.fromValue = 1
dropThru.toValue = view.bounds.maxY
dropThru.isRemovedOnCompletion = true
dropThru.fillMode = kCAFillModeForwards;
dropThru.beginTime = CACurrentMediaTime() + rands
dropThru.delegate = self
beeb.add(dropThru, forKey: "position.y")
self.view.layer.addSublayer(beeb)
}
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
self.view.layer.removeAllAnimations()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
How can I detect when an layer had left the screen so I may delete it
您已经为 CABasicAnimation 提供了一个委托,它会在动画结束时调用。那是你移除图层的信号。 (您正在删除动画而不是图层本身。)
据我了解您的代码,您可以在位置动画结束时删除图层。此时它应该已经离开了父视图的边界。
顺便说一句。删除和添加层会降低性能。相反,您应该将图层重新用于下一个动画。
创建了一个 CATextLayer 的子 class,我在其中附加了淡入动画,然后将其添加到附加了 dropThru 动画的 CATextLayer。尝试创建矩阵电影下雨代码效果的目标。工作得相当好,但事实上它缓慢但肯定会把自己推入地下,我怀疑是因为我不断添加越来越多的层。如何检测图层何时离开屏幕以便我可以将其删除。
这是代码...
class CATextSubLayer: CATextLayer, CAAnimationDelegate {
private var starter:Float!
private var ender:Float!
required override init(layer: Any) {
super.init(layer: layer)
//UIFont.availableFonts()
self.string = randomString(length: 1)
self.backgroundColor = UIColor.black.cgColor
self.foregroundColor = UIColor.white.cgColor
self.alignmentMode = kCAAlignmentCenter
self.font = CTFontCreateWithName("AvenirNextCondensed-BoldItalic" as CFString?, fontSize, nil)
self.fontSize = 16
self.opacity = 0.0
makeFade()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
fatalError("init(coder:) has not been implemented")
}
func randomString(length: Int) -> String {
let letters : NSString = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
let len = UInt32(letters.length)
var randomString = ""
for _ in 0 ..< length {
let rand = arc4random_uniform(len)
var nextChar = letters.character(at: Int(rand))
randomString += NSString(characters: &nextChar, length: 1) as String
}
return randomString
}
func makeFade() {
let rands = Double(arc4random_uniform(UInt32(4)))
let fadeInAndOut = CABasicAnimation(keyPath: "opacity")
fadeInAndOut.duration = 16.0;
fadeInAndOut.repeatCount = 1
fadeInAndOut.fromValue = 0.0
fadeInAndOut.toValue = 1
fadeInAndOut.isRemovedOnCompletion = true
fadeInAndOut.fillMode = kCAFillModeForwards;
fadeInAndOut.delegate = self
fadeInAndOut.beginTime = CACurrentMediaTime() + rands
self.add(fadeInAndOut, forKey: "opacity")
}
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
self.removeAllAnimations()
}
}
与外部 loop/View 控制器..
class ViewController: UIViewController, CAAnimationDelegate {
var beeb: CATextSubLayer!
var meeb: CATextLayer!
var lines = [Int]()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.black
// Do any additional setup after loading the view, typically from a nib.
meeb = CATextLayer()
for bing in stride(from:0, to: Int(view.bounds.width), by: 16) {
lines.append(bing)
}
for _ in 0 ..< 9 {
Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(makeBeeb), userInfo: nil, repeats: true)
}
}
func makeBeeb() {
let rands = Double(arc4random_uniform(UInt32(4)))
let beeb = CATextSubLayer(layer: meeb)
let randx = Int(arc4random_uniform(UInt32(lines.count)))
let monkey = lines[randx]
beeb.frame = CGRect(x: monkey, y: 0, width: 16, height: 16)
let dropThru = CABasicAnimation(keyPath: "position.y")
dropThru.duration = 12.0;
dropThru.repeatCount = 1
dropThru.fromValue = 1
dropThru.toValue = view.bounds.maxY
dropThru.isRemovedOnCompletion = true
dropThru.fillMode = kCAFillModeForwards;
dropThru.beginTime = CACurrentMediaTime() + rands
dropThru.delegate = self
beeb.add(dropThru, forKey: "position.y")
self.view.layer.addSublayer(beeb)
}
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
self.view.layer.removeAllAnimations()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
How can I detect when an layer had left the screen so I may delete it
您已经为 CABasicAnimation 提供了一个委托,它会在动画结束时调用。那是你移除图层的信号。 (您正在删除动画而不是图层本身。)
据我了解您的代码,您可以在位置动画结束时删除图层。此时它应该已经离开了父视图的边界。
顺便说一句。删除和添加层会降低性能。相反,您应该将图层重新用于下一个动画。