Swift 3.1 Matrix Screensaver effect

Created By: Debasis Das (16-May-2017)

In this post we will create a simple cocoa application in Swift 3.1 to generate the matrix screen saver effect.
MatrixScreenSaver

Swift 3.1 Matrix Screen Saver Sample Code

//  ViewController.swift
//  MatrixScreenSaverEffect
//  Created by Debasis Das on 5/15/17.
//  Copyright © 2017 Knowstack. All rights reserved.

import Cocoa

class ViewController: NSViewController {
    //To begin with, lets initialize an array of characters. A character from this array will be randomly selected to fall from top of the screen
    let characters = ["电","买","开","东","车","红","马","无","鸟","热","时","语","仮","缶","仏","拝"]
    override func viewDidLoad() {
        super.viewDidLoad()
//Create a root layer and set the background color to black
        let rootLayer = CALayer()
        rootLayer.frame = self.view.frame
        rootLayer.backgroundColor = NSColor.black.cgColor 
        self.view.layer = rootLayer
        self.view.wantsLayer = true
        let offset = CGFloat(20.0) //The padding between two characters
        let noOfColumns = Int(self.view.frame.size.width/offset)
        let noOfRows = Int(self.view.frame.size.height/offset)

//Iterate through the number of rows and no of columns and generate CATextLayers
        for i in 0..< noOfRows{
            for _ in 0..< noOfColumns{
                let textLayer = CATextLayer()
                textLayer.foregroundColor = NSColor.green.cgColor
                let index = Int(arc4random() % UInt32(characters.count))
                textLayer.frame = CGRect(x: CGFloat(i*Int(offset) + Int(offset)), y: rootLayer.frame.size.height, width: CGFloat(20.0), height: CGFloat(20.0))
                textLayer.string = characters[index]
                textLayer.fontSize = CGFloat(Float.random(min: 10, max: 23))
                textLayer.opacity = Float.random(min: 0.5, max: 1.0)
                rootLayer.addSublayer(textLayer)
                
//Now that we have created Text layers and have added the same to our root layers, lets add animation to each text layer
                let positionAnimation = CABasicAnimation(keyPath: "position")
                let point1 = CGPoint(x: textLayer.frame.origin.x, y: textLayer.frame.origin.y)
                let point2 = CGPoint(x: textLayer.frame.origin.x, y: 0)
                positionAnimation.fromValue = NSValue(point: point1)
                positionAnimation.toValue = NSValue(point: point2)
//Lets randomize the duration of each fall
                positionAnimation.duration = CFTimeInterval(Float.random(min: 4, max: 10))
                positionAnimation.repeatCount = .infinity
                textLayer.add(positionAnimation, forKey: nil)
            }
        }
    }
    
    /*
     Enhancements to this can be
     1. Full Screen Mode
     2. Leaving a trail as the letters fall
     3. Flipping the letters on the Y Axis occasionally
     */
}

public extension Float {
    public static var random:Float {
        get {
            return Float(arc4random()) / 0xFFFFFFFF
        }
    }
    public static func random(min min: Float, max: Float) -> Float {
        return Float.random * (max - min) + min
    }
    
}

Download the sample code here Swift 3.1 MatrixScreenSaver Effect

Posted in CoreAnimation, Mac OSX Animation, Swift 3.1 Tagged with: , ,

Leave a Reply

Your email address will not be published. Required fields are marked *

*