ios - Creating raining code Matrix effect -
created sub class of catextlayer within attached fadein animation, add catextlayer have attached dropthru animation. goal try , create matrix movie raining code effect. works reasonably fact surely drives ground, suspect cause keep adding more , more layers. how can detect when layer had left screen may delete it.
here code...
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" 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 = "" _ in 0 ..< length { let rand = arc4random_uniform(len) var nextchar = letters.character(at: int(rand)) randomstring += nsstring(characters: &nextchar, length: 1) 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() } } with outer loop/view controller ..
class viewcontroller: uiviewcontroller, caanimationdelegate { var beeb: catextsublayer! var meeb: catextlayer! var lines = [int]() override func viewdidload() { super.viewdidload() view.backgroundcolor = uicolor.black // additional setup after loading view, typically nib. meeb = catextlayer() bing in stride(from:0, to: int(view.bounds.width), by: 16) { lines.append(bing) } _ 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 resources can recreated. } }
as far understand code can remove layer, when it's position animation ends. in moment should have left bounds of parent view.
btw. removing , adding layers costs performance. instead removing should reuse layer next animation.
Comments
Post a Comment