├── .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 - [](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 |
--------------------------------------------------------------------------------