├── .github └── FUNDING.yml ├── .gitignore ├── Images ├── shiny-black.gif ├── shiny-rainbow.gif └── shiny-iridescent.gif ├── Tests ├── LinuxMain.swift └── ShinyTests │ ├── XCTestManifests.swift │ └── ShinyTests.swift ├── .swiftpm └── xcode │ └── package.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ └── IDEWorkspaceChecks.plist ├── LICENSE ├── Package.swift ├── Docs ├── examples.md └── reference.md ├── README.md └── Sources └── Shiny ├── ShinyView.swift ├── MotionManager.swift └── Gradient.swift /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [maustinstar] 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | /.build 3 | /Packages 4 | /*.xcodeproj 5 | xcuserdata/ 6 | -------------------------------------------------------------------------------- /Images/shiny-black.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maustinstar/shiny/HEAD/Images/shiny-black.gif -------------------------------------------------------------------------------- /Images/shiny-rainbow.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maustinstar/shiny/HEAD/Images/shiny-rainbow.gif -------------------------------------------------------------------------------- /Images/shiny-iridescent.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/maustinstar/shiny/HEAD/Images/shiny-iridescent.gif -------------------------------------------------------------------------------- /Tests/LinuxMain.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | import ShinyTests 4 | 5 | var tests = [XCTestCaseEntry]() 6 | tests += ShinyTests.allTests() 7 | XCTMain(tests) 8 | -------------------------------------------------------------------------------- /.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Tests/ShinyTests/XCTestManifests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | 3 | #if !canImport(ObjectiveC) 4 | public func allTests() -> [XCTestCaseEntry] { 5 | return [ 6 | testCase(ShinyTests.allTests), 7 | ] 8 | } 9 | #endif 10 | -------------------------------------------------------------------------------- /.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Tests/ShinyTests/ShinyTests.swift: -------------------------------------------------------------------------------- 1 | import XCTest 2 | @testable import Shiny 3 | 4 | final class ShinyTests: XCTestCase { 5 | func testExample() { 6 | // This is an example of a functional test case. 7 | // Use XCTAssert and related functions to verify your tests produce the correct 8 | // results. 9 | // XCTAssertEqual(Shiny().text, "Hello, World!") 10 | } 11 | 12 | static var allTests = [ 13 | ("testExample", testExample), 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Michael Verges 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.3 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "Shiny", 8 | platforms: [ 9 | .iOS(.v14), 10 | .macOS(.v11) 11 | ], 12 | products: [ 13 | // Products define the executables and libraries produced by a package, and make them visible to other packages. 14 | .library( 15 | name: "Shiny", 16 | targets: ["Shiny"]), 17 | ], 18 | dependencies: [ 19 | // Dependencies declare other packages that this package depends on. 20 | // .package(url: /* package url */, from: "1.0.0"), 21 | ], 22 | targets: [ 23 | // Targets are the basic building blocks of a package. A target can define a module or a test suite. 24 | // Targets can depend on other targets in this package, and on products in packages which this package depends on. 25 | .target( 26 | name: "Shiny", 27 | dependencies: []), 28 | .testTarget( 29 | name: "ShinyTests", 30 | dependencies: ["Shiny"]), 31 | ] 32 | ) 33 | -------------------------------------------------------------------------------- /Docs/examples.md: -------------------------------------------------------------------------------- 1 | # Examples 2 | 3 | Examples for `.shiny()` 4 | 5 | #### Rainbow text on silver card 6 | 7 | 8 | 9 | ```swift 10 | Text("shiny") 11 | .font(.largeTitle) 12 | .fontWeight(.bold).shiny() 13 | .background( 14 | RoundedRectangle(cornerRadius: 14.0) 15 | .frame(width: 200.0, height: 70.0) 16 | .shiny(.hyperGlossy(UIColor.systemGray5))) 17 | ``` 18 | 19 | #### Glossy text on matte card 20 | 21 | 22 | 23 | ```swift 24 | Text("shiny") 25 | .font(.largeTitle) 26 | .fontWeight(.bold).shiny(.glossy(.black)) 27 | .background( 28 | RoundedRectangle(cornerRadius: 14.0) 29 | .frame(width: 200.0, height: 70.0) 30 | .shiny(.matte(.black)) 31 | ``` 32 | 33 | #### Iridescent text on glossy card 34 | 35 | 36 | 37 | ```swift 38 | Text("shiny") 39 | .font(.largeTitle) 40 | .fontWeight(.bold).shiny(.iridescent) 41 | .background( 42 | RoundedRectangle(cornerRadius: 14.0) 43 | .frame(width: 200.0, height: 70.0) 44 | .shiny(.glossy(.black)) 45 | ``` 46 | -------------------------------------------------------------------------------- /Docs/reference.md: -------------------------------------------------------------------------------- 1 | # Reference 2 | 3 | Usage details for `.shiny()` 4 | 5 | ## Contents 6 | - [Basic Usage](#usage) 7 | - [Gradients](#gradients) 8 | - [`.rainbow`](#rainbow) 9 | - [`.iridescent`](#iridescent) 10 | - [`.matte`](#matte) 11 | - [`.glossy`](#glossy) 12 | - [`.hyperGlossy`](#hyper-glossy) 13 | - [`Custom`](#custom) 14 | 15 | ## Usage 16 | 17 | Just import Shiny and modify your view with `.shiny()` to get started. 18 | 19 | ```swift 20 | Import Shiny 21 | ... 22 | Text("Hello, shiny world! ✨").shiny() 23 | ``` 24 | 25 | ## Gradients 26 | 27 | The `.shiny()` view modifier takes a gradient parameter to define the shiny surface. By default, `.shiny()` uses `Gradient.rainbow`. 28 | 29 | ### Rainbow 30 | 31 | #### 🌈 `.shiny(.rainbow)` 32 | 33 | Cycles through the system colors in rainbow order. 34 | 35 | ### Iridescent 36 | 37 | #### 💎 `.shiny(.iridescent)` 38 | 39 | Cycles through translucent blues and purples that add an extra sparkle to your views. 40 | 41 | ### Matte 42 | 43 | #### 🟨 `.shiny(.matte(UIColor))` 44 | 45 | Generates a matte surface from a given color, modeling a dispersed light source. 46 | 47 | ### Glossy 48 | 49 | #### 🔵 `.shiny(.glossy(UIColor))` 50 | 51 | Generates a matte surface from a given color, modeling a focused light source. 52 | 53 | ### Hyper Glossy 54 | 55 | #### 🔦 `.shiny(.hyperGlossy(UIColor))` 56 | 57 | Generates a matte surface from a given color, modeling an intense light source. 58 | 59 | ### Custom 60 | 61 | #### ⚙️ `.shiny(Gradient(...))` 62 | 63 | Write your own gradient for a shiny view. 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Shiny 2 | 3 | 4 | 5 | #### Add motion-based texture to your SwiftUI views 6 | 7 | Draw attention to important interface elements with `.shiny()`. Shiny uses your gyroscope to simulate lighting and motion effects on colors. It works on almost every native SwiftUI View. Try it on Text, Toggle, or a VStack. Just add `.shiny()` to get started! 8 | 9 | #### 💳 Inspired by the Apple Cash Card 10 | 11 | ## Contents 12 | 13 | - [Add the Package](#package) 14 | - [Basic Usage](#basic-usage) 15 | - [Example](#example) 16 | - [More](#more) 17 | - [Credits](#credits) 18 | 19 | ## Package 20 | 21 | ### For Xcode Projects 22 | 23 | File > Swift Packages > Add Package Dependency: https://github.com/maustinstar/shiny 24 | 25 | ### For Swift Packages 26 | 27 | Add a dependency in your your `Package.swift` 28 | 29 | ```swift 30 | .package(url: "https://github.com/maustinstar/shiny.git", from: "0.0.1"), 31 | ``` 32 | 33 | ## Basic Usage 34 | 35 | Just import Shiny and modify your view with `.shiny()` to get started. 36 | 37 | ```swift 38 | import Shiny 39 | ... 40 | Text("Hello, shiny world! ✨").shiny() 41 | ``` 42 | 43 | **See the full [Reference Guide](https://github.com/maustinstar/shiny/blob/master/Docs/reference.md).** 44 | 45 | ## Example 46 | 47 | #### Rainbow text on silver card 48 | 49 | 50 | 51 | ```swift 52 | Text("shiny") 53 | .font(.largeTitle) 54 | .fontWeight(.bold).shiny() 55 | .background( 56 | RoundedRectangle(cornerRadius: 14.0) 57 | .frame(width: 200.0, height: 70.0) 58 | .shiny(.hyperGlossy(UIColor.systemGray5))) 59 | ``` 60 | 61 | **See more [Examples](https://github.com/maustinstar/shiny/blob/master/Docs/examples.md).** 62 | 63 | ## More 64 | 65 | ### 🚀 Looking for more fun SwiftUI Packages? 66 | 67 | 68 | 69 | 70 | 71 | ## Credits 72 | 73 | * [**Michael Verges**](https://github.com/maustinstar) - *Initial work* - mverges3@gatech.edu - [![Follow on Linkedin](https://img.shields.io/badge/Follow%20on-Linkedin-5176B1.svg)](https://www.linkedin.com/in/michaelverges) 74 | 75 | 76 | -------------------------------------------------------------------------------- /Sources/Shiny/ShinyView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ShinyView.swift 3 | // 4 | // 5 | // Created by Michael Verges on 7/31/20. 6 | // 7 | 8 | import SwiftUI 9 | import CoreMotion 10 | #if os(macOS) 11 | import AppKit 12 | #endif 13 | 14 | public extension View { 15 | func shiny(_ surface: Gradient = .rainbow) -> some View { 16 | return ShinyView(surface, content: self).environmentObject(MotionManager.main) 17 | } 18 | } 19 | 20 | internal struct ShinyView: View where Content: View { 21 | 22 | @EnvironmentObject var model: MotionManager 23 | 24 | init(_ surface: Gradient = .rainbow, content: Content) { 25 | self.surface = surface 26 | self.content = content 27 | } 28 | 29 | init(_ surface: Gradient = .rainbow, @ViewBuilder content: () -> Content) { 30 | self.surface = surface 31 | self.content = content() 32 | } 33 | 34 | var content: Content 35 | 36 | var position: CGSize { 37 | #if os(iOS) 38 | let x = 0 - (CGFloat(model.roll) / .pi * 4) * UIScreen.main.bounds.height 39 | let y = 0 - (CGFloat(model.pitch) / .pi * 4) * UIScreen.main.bounds.height 40 | #elseif os(macOS) 41 | let x = 0 - (model.locationX / .pi * 4) * (NSScreen.main?.frame.height ?? 1080) 42 | let y = 0 - (model.locationY / .pi * 4) * (NSScreen.main?.frame.height ?? 1080) 43 | #endif 44 | return CGSize(width: x, height: y) 45 | } 46 | 47 | func scale(_ proxy: GeometryProxy) -> CGFloat { 48 | #if os(iOS) 49 | return UIScreen.main.bounds.height / radius(proxy) * 2 50 | #elseif os(macOS) 51 | return (NSScreen.main?.frame.height ?? 1080) / radius(proxy) * 2 52 | #endif 53 | } 54 | 55 | func radius(_ proxy: GeometryProxy) -> CGFloat { 56 | return min(proxy.frame(in: .global).width / 2, proxy.frame(in: .global).height / 2) 57 | } 58 | 59 | var surface: Gradient 60 | 61 | var body: some View { 62 | 63 | self.content 64 | .foregroundColor(.clear) 65 | .background( GeometryReader { (proxy) in 66 | ZStack { 67 | self.surface.stops.last?.color 68 | .scaleEffect(self.scale(proxy)) 69 | RadialGradient( 70 | gradient: self.surface, 71 | center: .center, 72 | startRadius: 1, 73 | endRadius: self.radius(proxy)) 74 | .scaleEffect(self.scale(proxy)) 75 | .offset(self.position) 76 | .animation(.default) 77 | } 78 | .mask(self.content) 79 | }) 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /Sources/Shiny/MotionManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MotionManager.swift 3 | // 4 | // 5 | // Created by Michael Verges on 7/31/20. 6 | // 7 | 8 | import SwiftUI 9 | import CoreMotion 10 | #if os(macOS) 11 | import AppKit 12 | #endif 13 | 14 | internal class MotionManager: ObservableObject { 15 | #if os(iOS) 16 | @Published var yaw: CGFloat = 0 17 | @Published var pitch: CGFloat = 0 18 | @Published var roll: CGFloat = 0 19 | 20 | var motionInput = CMMotionManager() 21 | #elseif os(macOS) 22 | @Published var locationX: CGFloat = 0 23 | @Published var locationY: CGFloat = 0 24 | 25 | var motionInput = NSEvent() 26 | #endif 27 | 28 | static var main = MotionManager() 29 | 30 | init() { 31 | #if os(iOS) 32 | motionInput.deviceMotionUpdateInterval = 0.2; 33 | motionInput.startDeviceMotionUpdates() 34 | motionInput.startDeviceMotionUpdates(to: OperationQueue.current!) { _,_ in 35 | 36 | if let yaw = self.motionInput.yaw, 37 | let pitch = self.motionInput.pitch, 38 | let roll = self.motionInput.roll 39 | { 40 | self.yaw = CGFloat(yaw) 41 | self.pitch = CGFloat(pitch) 42 | self.roll = CGFloat(roll) 43 | } 44 | } 45 | #elseif os(macOS) 46 | NSEvent.addLocalMonitorForEvents(matching: [.mouseMoved]) { 47 | let screenWidth = NSScreen.main?.frame.width ?? 1920 48 | let screenHeight = NSScreen.main?.frame.height ?? 1080 49 | self.locationX = -self.motionInput.locationX.remap(origFrom: 0, origTo: screenWidth, targetFrom: -.pi, targetTo: .pi) / 4 50 | self.locationY = self.motionInput.locationY.remap(origFrom: 0, origTo: screenHeight, targetFrom: -.pi, targetTo: .pi) / 4 51 | return $0 52 | } 53 | #endif 54 | } 55 | } 56 | 57 | #if os(iOS) 58 | internal extension CMMotionManager { 59 | var yaw: Double? { 60 | get { 61 | return deviceMotion?.attitude.yaw 62 | } 63 | } 64 | 65 | var pitch: Double? { 66 | get { 67 | return deviceMotion?.attitude.pitch 68 | } 69 | } 70 | 71 | var roll: Double? { 72 | get { 73 | return deviceMotion?.attitude.roll 74 | } 75 | } 76 | } 77 | 78 | #elseif os(macOS) 79 | 80 | internal extension NSEvent { 81 | var locationX: CGFloat { 82 | return NSEvent.mouseLocation.x 83 | } 84 | 85 | var locationY: CGFloat { 86 | return NSEvent.mouseLocation.y 87 | } 88 | } 89 | 90 | internal extension CGFloat { 91 | func lerp(from: CGFloat, to: CGFloat, rel: CGFloat) -> CGFloat { 92 | return ((1 - rel) * from) + (rel * to) 93 | } 94 | 95 | func invLerp(from: CGFloat, to: CGFloat, value: CGFloat) -> CGFloat { 96 | return (value - from) / (to - from) 97 | } 98 | 99 | func remap(origFrom: CGFloat, origTo: CGFloat, targetFrom: CGFloat, targetTo: CGFloat) -> CGFloat { 100 | let rel = invLerp(from: origFrom, to: origTo, value: self) 101 | return lerp(from: targetFrom, to: targetTo, rel: rel) 102 | } 103 | } 104 | #endif 105 | -------------------------------------------------------------------------------- /Sources/Shiny/Gradient.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Gradient.swift 3 | // 4 | // 5 | // Created by Michael Verges on 7/31/20. 6 | // 7 | 8 | import SwiftUI 9 | 10 | #if os(iOS) 11 | internal extension UIColor { 12 | var redValue: CGFloat{ return CIColor(color: self).red } 13 | var greenValue: CGFloat{ return CIColor(color: self).green } 14 | var blueValue: CGFloat{ return CIColor(color: self).blue } 15 | var alphaValue: CGFloat{ return CIColor(color: self).alpha } 16 | } 17 | 18 | public extension Gradient { 19 | 20 | static var iridescent: Gradient { 21 | Gradient(colors: [ 22 | Color(red: 0.5, green: 0.5, blue: 0.5, opacity: 0.2), 23 | Color(red: 0.0, green: 0.5, blue: 1.0, opacity: 0.2), 24 | Color(red: 1.0, green: 0.5, blue: 1.0, opacity: 0.4), 25 | Color(red: 0.5, green: 1.0, blue: 1.0, opacity: 0.6), 26 | Color(red: 0.5, green: 1.0, blue: 1.0, opacity: 0.6), 27 | Color(red: 1.0, green: 0.5, blue: 1.0, opacity: 0.4), 28 | Color(red: 0.0, green: 0.5, blue: 1.0, opacity: 0.2), 29 | Color(red: 0.5, green: 0.5, blue: 0.5, opacity: 0.2), 30 | Color.clear 31 | ]) 32 | } 33 | 34 | static var rainbow: Gradient { 35 | Gradient(colors: [ 36 | .red, .red, .red, 37 | .red, .orange, .yellow, .green, .blue, .purple, .pink, 38 | .red, .orange, .yellow, .green, .blue, .purple, .pink, 39 | .red, .orange, .yellow, .green, .blue, .purple, .pink 40 | ]) 41 | } 42 | 43 | static func matte(_ color: UIColor, intensity: CGFloat = 0.5) -> Gradient { 44 | let i = min(max(intensity, 0), 1) 45 | 46 | let red = color.redValue 47 | let green = color.greenValue 48 | let blue = color.blueValue 49 | 50 | let newRed = red+(1-red)*(0.7) 51 | let newGreen = green+(1-green)*(0.7) 52 | let newBlue = blue+(1-blue)*(0.7) 53 | 54 | let colors = [ 55 | UIColor(red: newRed, green: newGreen, blue: newBlue, alpha: 1.0 * i), 56 | UIColor(red: newRed, green: newGreen, blue: newBlue, alpha: 0.85 * i), 57 | UIColor(red: newRed, green: newGreen, blue: newBlue, alpha: 0.6 * i), 58 | UIColor(red: newRed, green: newGreen, blue: newBlue, alpha: 0.3 * i), 59 | UIColor(red: newRed, green: newGreen, blue: newBlue, alpha: 0.0 * i), 60 | color 61 | ] 62 | 63 | return Gradient(colors: colors.map { Color($0) }) 64 | } 65 | 66 | static func glossy(_ color: UIColor, intensity: CGFloat = 0.5) -> Gradient { 67 | 68 | let i = min(max(intensity, 0), 1) 69 | 70 | let colors = [ 71 | UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.90 * i), 72 | UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.90 * i), 73 | UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.80 * i), 74 | UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.50 * i), 75 | UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.10 * i), 76 | UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.00 * i), 77 | UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.00 * i), 78 | UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.00 * i), 79 | UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.00 * i), 80 | color 81 | ] 82 | 83 | return Gradient(colors: colors.map { Color($0) }) 84 | } 85 | 86 | static func hyperGlossy(_ color: UIColor, intensity: CGFloat = 1.0) -> Gradient { 87 | 88 | let i = min(max(intensity, 0), 1) 89 | 90 | let colors = [ 91 | UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.90 * i), 92 | UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.70 * i), 93 | UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.00), 94 | color 95 | ] 96 | 97 | return Gradient(colors: colors.map { Color($0) }) 98 | } 99 | } 100 | #elseif os(macOS) 101 | internal extension NSColor { 102 | var redValue: CGFloat{ return CIColor(color: self)?.red ?? 0 } 103 | var greenValue: CGFloat{ return CIColor(color: self)?.green ?? 0 } 104 | var blueValue: CGFloat{ return CIColor(color: self)?.blue ?? 0 } 105 | var alphaValue: CGFloat{ return CIColor(color: self)?.alpha ?? 0 } 106 | } 107 | 108 | public extension Gradient { 109 | 110 | static var iridescent: Gradient { 111 | Gradient(colors: [ 112 | Color(red: 0.5, green: 0.5, blue: 0.5, opacity: 0.2), 113 | Color(red: 0.0, green: 0.5, blue: 1.0, opacity: 0.2), 114 | Color(red: 1.0, green: 0.5, blue: 1.0, opacity: 0.4), 115 | Color(red: 0.5, green: 1.0, blue: 1.0, opacity: 0.6), 116 | Color(red: 0.5, green: 1.0, blue: 1.0, opacity: 0.6), 117 | Color(red: 1.0, green: 0.5, blue: 1.0, opacity: 0.4), 118 | Color(red: 0.0, green: 0.5, blue: 1.0, opacity: 0.2), 119 | Color(red: 0.5, green: 0.5, blue: 0.5, opacity: 0.2), 120 | Color.clear 121 | ]) 122 | } 123 | 124 | static var rainbow: Gradient { 125 | Gradient(colors: [ 126 | .red, .red, .red, 127 | .red, .orange, .yellow, .green, .blue, .purple, .pink, 128 | .red, .orange, .yellow, .green, .blue, .purple, .pink, 129 | .red, .orange, .yellow, .green, .blue, .purple, .pink 130 | ]) 131 | } 132 | 133 | static func matte(_ color: NSColor, intensity: CGFloat = 0.5) -> Gradient { 134 | let i = min(max(intensity, 0), 1) 135 | 136 | let red = color.redValue 137 | let green = color.greenValue 138 | let blue = color.blueValue 139 | 140 | let newRed = red+(1-red)*(0.7) 141 | let newGreen = green+(1-green)*(0.7) 142 | let newBlue = blue+(1-blue)*(0.7) 143 | 144 | let colors = [ 145 | NSColor(red: newRed, green: newGreen, blue: newBlue, alpha: 1.0 * i), 146 | NSColor(red: newRed, green: newGreen, blue: newBlue, alpha: 0.85 * i), 147 | NSColor(red: newRed, green: newGreen, blue: newBlue, alpha: 0.6 * i), 148 | NSColor(red: newRed, green: newGreen, blue: newBlue, alpha: 0.3 * i), 149 | NSColor(red: newRed, green: newGreen, blue: newBlue, alpha: 0.0 * i), 150 | color 151 | ] 152 | 153 | return Gradient(colors: colors.map { Color($0) }) 154 | } 155 | 156 | static func glossy(_ color: NSColor, intensity: CGFloat = 0.5) -> Gradient { 157 | 158 | let i = min(max(intensity, 0), 1) 159 | 160 | let colors = [ 161 | NSColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.90 * i), 162 | NSColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.90 * i), 163 | NSColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.80 * i), 164 | NSColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.50 * i), 165 | NSColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.10 * i), 166 | NSColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.00 * i), 167 | NSColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.00 * i), 168 | NSColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.00 * i), 169 | NSColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.00 * i), 170 | color 171 | ] 172 | 173 | return Gradient(colors: colors.map { Color($0) }) 174 | } 175 | 176 | static func hyperGlossy(_ color: NSColor, intensity: CGFloat = 1.0) -> Gradient { 177 | 178 | let i = min(max(intensity, 0), 1) 179 | 180 | let colors = [ 181 | NSColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.90 * i), 182 | NSColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.70 * i), 183 | NSColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 0.00), 184 | color 185 | ] 186 | 187 | return Gradient(colors: colors.map { Color($0) }) 188 | } 189 | } 190 | #endif 191 | --------------------------------------------------------------------------------