Skip to content

Instantly share code, notes, and snippets.

@twodayslate
Created October 14, 2016 13:55
Show Gist options
  • Save twodayslate/28aa87dc8e0fcf047b44f9127252c561 to your computer and use it in GitHub Desktop.
Save twodayslate/28aa87dc8e0fcf047b44f9127252c561 to your computer and use it in GitHub Desktop.
//
// ShinyTextView.swift
//
import Foundation
import Cocoa
class ShimmerTextView : NSTextView {
// define your colors and locations
var count = 0
var wait = false
var colors = [NSColor.white.cgColor, NSColor.white.cgColor, NSColor.black.cgColor, NSColor.white.cgColor, NSColor.white.cgColor]
var locs:[CGFloat] = [0.0, 0.4, 0.5, 0.6, 1.0]
override var allowsVibrancy: Bool { return true }
override func draw(_ dirtyRect: NSRect) {
NSGraphicsContext.saveGraphicsState()
// set the image context
let colorSpace:CGColorSpace = CGColorSpaceCreateDeviceRGB()
let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue)
var ctx = CGContext(data: nil, width: Int(self.bounds.size.width), height: Int(self.bounds.size.height), bitsPerComponent: 8, bytesPerRow: 0, space: colorSpace, bitmapInfo: bitmapInfo.rawValue)
let ngc = NSGraphicsContext(cgContext: ctx!, flipped: true)
NSGraphicsContext.setCurrent(ngc)
// flip context
ctx!.scaleBy(x: 1, y: -1)
ctx!.translateBy(x: 0, y: -bounds.size.height)
// get the superclass to draw text
super.draw(dirtyRect)
// get image and end context
let img = NSGraphicsContext.current()?.cgContext.makeImage()
NSGraphicsContext.restoreGraphicsState()
// get drawRect context
ctx = NSGraphicsContext.current()?.cgContext
// flip context
ctx!.scaleBy(x: 1, y: -1)
ctx!.translateBy(x: 0, y: -bounds.size.height)
// clip context to image
ctx!.clip(to: bounds, mask: img!)
// create your gradient
let grad = CGGradient(colorsSpace: CGColorSpaceCreateDeviceRGB(), colors: colors as CFArray, locations: locs)
// draw gradient
ctx!.drawLinearGradient(grad!, start: CGPoint(x: 0, y:bounds.size.height*0.5), end: CGPoint(x:bounds.size.width, y:bounds.size.height*0.5), options: CGGradientDrawingOptions(rawValue: 0))
}
func shimmer() {
let runner = Timer(fireAt: Date(), interval: 0.1, target: self, selector: #selector(drawShimmer), userInfo: nil, repeats: true)
RunLoop.current .add(runner, forMode: RunLoopMode.defaultRunLoopMode)
}
func drawShimmer() {
if self.wait {
if count % 20 == 0 {
self.wait = false
}
} else {
locs[1] = locs[1]+0.05
locs[2] = locs[2]+0.05
locs[3] = locs[3]+0.05
if locs[3] >= 1.0 {
locs[1] = 0.1
locs[2] = 0.2
locs[3] = 0.3
self.wait = true
}
// force redraw
self.needsDisplay = true
}
count = count + 1
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment