Created
December 10, 2015 16:55
-
-
Save eonist/520fa35958c123ad6840 to your computer and use it in GitHub Desktop.
Quartz Inner Shadow (playground)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Cocoa | |
import XCPlayground | |
import XCTest | |
/* | |
shadow.shadowColor = NSColor.blackColor().colorWithAlphaComponent(1.0) | |
shadow.shadowOffset = NSMakeSize(0.1, 0.1) | |
shadow.shadowBlurRadius = 15 | |
*/ | |
extension NSShadow{ | |
convenience init(_ color:NSColor,_ offsetX:CGFloat,_ offsetY:CGFloat,_ blurRadius:CGFloat){ | |
self.init() | |
self.shadowColor = color | |
self.shadowOffset = NSMakeSize(offsetX,offsetY) | |
self.shadowBlurRadius = blurRadius | |
} | |
} | |
extension NSColor{ | |
/** | |
* EXAMPLE: :NSColor(NSColor.blackColor(),0.5)//outputs a black color with 50% transparancy | |
*/ | |
convenience init(_ color:NSColor,_ alpha:CGFloat/*0.0 - 1.0*/){ | |
let ciColor:CIColor = CIColor(color: color)! | |
self.init(red: ciColor.red, green: ciColor.green, blue: ciColor.blue, alpha: alpha) | |
} | |
/** | |
* EXAMPLE: NSColor.redColor().alpha(0.5) | |
*/ | |
func alpha(alpha:CGFloat)->NSColor{ | |
return NSColor(self,alpha) | |
} | |
} | |
class FlippedView:NSView {//Organizes your view from top to bottom | |
override var flipped:Bool {return true} | |
} | |
class Container:FlippedView{ | |
var color:NSColor = NSColor.blueColor() | |
override var wantsDefaultClipping:Bool{return false}//avoids clipping the view | |
override var wantsUpdateLayer:Bool {return true} | |
init(_ width:Int = 400, _ height:Int = 400, _ color:NSColor = NSColor.blueColor() ) { | |
Swift.print("Container.init()") | |
self.color = color | |
let frame = NSRect(x: 0, y: 0, width: width, height: height) | |
super.init(frame: frame) | |
self.wantsLayer = false | |
} | |
/** | |
* NOTE: One can also use NSShadow(shadow.shadowColor!.colorWithAlphaComponent(1.0),shadow.shadowOffset.width,shadow.shadowOffset.height,shadow.shadowBlurRadius).set() instead of CGContextSetShadowWithColor | |
*/ | |
override func drawRect(dirtyRect: NSRect) { | |
//Swift.print("drawRect()") | |
//// General Declarations | |
let context = NSGraphicsContext.currentContext()!.CGContext | |
/*Draw first shapes:*/ | |
let path:CGMutablePathRef = CGPathCreateMutable(); | |
let rectangle:CGRect = CGRectMake(10.0, 10.0,200.0, 200.0); | |
let roundRectPath:CGMutablePathRef = CGPathCreateWithRoundedRect(rectangle, 20, 20, nil) as! CGMutablePathRef/* Add the roundRectangle to the roundRectPath*/ | |
CGPathAddPath(path, nil, roundRectPath)/*Adds the roundRectPath to the path*/ | |
/*draw second shape*/ | |
let rect:CGRect = CGRectMake(210.0, 210.0,100.0, 100.0) | |
let rectPath:CGMutablePathRef = CGPathCreateWithRect(rect, nil) as! CGMutablePathRef | |
CGPathAddPath(path, nil, rectPath)/*Adds the rectPath to the path*/ | |
/*Add,fill and draw path to the context*/ | |
CGContextAddPath(context,path)/* Add the path to the context*/ | |
CGContextSetFillColorWithColor(context,NSColor.cyanColor().CGColor) | |
//CGContextDrawPath(context, CGPathDrawingMode.Fill)/*draw the path with a fill*/ // | |
CGContextDrawPath(context, CGPathDrawingMode.Fill) | |
/*Init the inset dropshadow scheme*/ | |
CGContextSaveGState(context);/*init the gState*/ | |
CGContextAddPath(context, path);/*add The clipping path to the context*/ | |
CGContextClip(context);/*The clipping ensures that the shadow is within its shape that it tries to cast an inset shadow on*/ | |
/*Stores data about the Shadow*/ | |
let shadow = NSShadow(NSColor.blackColor().alpha(1.0),0.1,0.1,15) | |
let opaqueShadowColor:CGColorRef = CGColorCreateCopyWithAlpha(shadow.shadowColor!.CGColor, 1.0)!/*We need a copy of the shadow color as CGColor with alpha set to 1*/ | |
CGContextSetAlpha(context, CGColorGetAlpha(shadow.shadowColor!.CGColor)); | |
CGContextBeginTransparencyLayer(context, nil); | |
CGContextSetShadowWithColor(context, shadow.shadowOffset, shadow.shadowBlurRadius, opaqueShadowColor);/*This is where the setting of the shadow happens*/ | |
CGContextSetBlendMode(context, CGBlendMode.SourceOut);/*The blend mode creates the hole in the shadow so that it appears like an inner shadow*/ | |
CGContextSetFillColorWithColor(context, opaqueShadowColor); | |
CGContextAddPath(context, path); | |
CGContextFillPath(context); | |
CGContextEndTransparencyLayer(context); | |
CGContextRestoreGState(context);/*end the gState*/ | |
/*end the inset dropshadow scheme*/ | |
/*Continue drawing regular stuff here, like stroke*/ | |
CGContextAddPath(context, path);/*The clipping path*/ | |
CGContextSetStrokeColorWithColor(context, NSColor.magentaColor().CGColor) | |
CGContextSetLineWidth(context, 10)//set the stroke width! | |
CGContextDrawPath(context, CGPathDrawingMode.Stroke) | |
} | |
/** | |
* Required by super class | |
*/ | |
required init?(coder: NSCoder) {fatalError("init(coder:) has not been implemented")} | |
} | |
let container = Container() | |
XCPlaygroundPage.currentPage.liveView = container | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Example: