├── README.md ├── Sliders Media ├── ActivityRings.MP4 ├── ActivityRings.gif ├── DefaultRSlider.MP4 ├── DefaultRSlider.gif ├── DefaultRadialSlider.gif ├── Joystick.gif ├── JoystickDefault.MP4 ├── KnobRSlider.gif ├── KnobStyleRSlider.MP4 ├── LSlider.gif ├── LSlider.mov ├── OverflowSlider.MP4 ├── OverflowSlider.gif ├── PSlider.MP4 ├── PSliderExample.gif ├── RGBColorPick.MP4 ├── RGBColorPicker.gif ├── RadialPadDefault.MP4 ├── RadialPadHSBPicker.MP4 ├── RadialPadHSBPicker.gif ├── SlidersCollage.PNG ├── TrackPadGraphStyle.MP4 ├── TrackPadGraphStyle.gif ├── TrackPadHSBColorPicker.gif └── TrackPadHSBPicker.MP4 ├── SlidersExamples.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcuserdata │ └── kieran.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist └── SlidersExamples ├── AppDelegate.swift ├── Assets.xcassets ├── AppIcon.appiconset │ ├── Contents.json │ ├── Icon-App-20x20@1x.png │ ├── Icon-App-20x20@2x.png │ ├── Icon-App-20x20@3x.png │ ├── Icon-App-29x29@1x.png │ ├── Icon-App-29x29@2x.png │ ├── Icon-App-29x29@3x.png │ ├── Icon-App-40x40@1x.png │ ├── Icon-App-40x40@2x.png │ ├── Icon-App-40x40@3x.png │ ├── Icon-App-60x60@2x.png │ ├── Icon-App-60x60@3x.png │ ├── Icon-App-76x76@1x.png │ ├── Icon-App-76x76@2x.png │ ├── Icon-App-83.5x83.5@2x.png │ └── ItunesArtwork@2x.png └── Contents.json ├── Base.lproj └── LaunchScreen.storyboard ├── ContentView.swift ├── Info.plist ├── JoystickExample.swift ├── LSliderExamples ├── LSliderExample.swift └── RGBColorPicker.swift ├── OverflowSliderExample.swift ├── Preview Content └── Preview Assets.xcassets │ └── Contents.json ├── RSliderExamples ├── ActivityRings.swift ├── DefaultRSlider.swift └── KnobStyleExample.swift ├── RadialPadExamples ├── DefaultRadialPad.swift ├── HueCircleView.swift └── RadialPadExample.swift ├── SceneDelegate.swift └── TrackpadExamples ├── DefaultTrackPadExample.swift ├── GraphingGrid.swift └── HSBColorPicker.swift /README.md: -------------------------------------------------------------------------------- 1 | # SlidersExamples 2 | A companion project to explore the [Sliders](https://github.com/kieranb662/Sliders) SwiftUI Library 3 | 4 |

5 | Activity Rings Gif 6 | RGB Color Picker 7 | LSlider Example 8 | RadialPad HSB Color Picker 9 | JoyStick 10 |

11 | 12 |

13 | KnobSlider 14 | OverflowSlider 15 | GraphStyle 16 | TrackPad HSB Color Picker 17 | DefaultRSlider 18 |

19 | -------------------------------------------------------------------------------- /Sliders Media/ActivityRings.MP4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/Sliders Media/ActivityRings.MP4 -------------------------------------------------------------------------------- /Sliders Media/ActivityRings.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/Sliders Media/ActivityRings.gif -------------------------------------------------------------------------------- /Sliders Media/DefaultRSlider.MP4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/Sliders Media/DefaultRSlider.MP4 -------------------------------------------------------------------------------- /Sliders Media/DefaultRSlider.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/Sliders Media/DefaultRSlider.gif -------------------------------------------------------------------------------- /Sliders Media/DefaultRadialSlider.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/Sliders Media/DefaultRadialSlider.gif -------------------------------------------------------------------------------- /Sliders Media/Joystick.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/Sliders Media/Joystick.gif -------------------------------------------------------------------------------- /Sliders Media/JoystickDefault.MP4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/Sliders Media/JoystickDefault.MP4 -------------------------------------------------------------------------------- /Sliders Media/KnobRSlider.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/Sliders Media/KnobRSlider.gif -------------------------------------------------------------------------------- /Sliders Media/KnobStyleRSlider.MP4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/Sliders Media/KnobStyleRSlider.MP4 -------------------------------------------------------------------------------- /Sliders Media/LSlider.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/Sliders Media/LSlider.gif -------------------------------------------------------------------------------- /Sliders Media/LSlider.mov: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/Sliders Media/LSlider.mov -------------------------------------------------------------------------------- /Sliders Media/OverflowSlider.MP4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/Sliders Media/OverflowSlider.MP4 -------------------------------------------------------------------------------- /Sliders Media/OverflowSlider.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/Sliders Media/OverflowSlider.gif -------------------------------------------------------------------------------- /Sliders Media/PSlider.MP4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/Sliders Media/PSlider.MP4 -------------------------------------------------------------------------------- /Sliders Media/PSliderExample.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/Sliders Media/PSliderExample.gif -------------------------------------------------------------------------------- /Sliders Media/RGBColorPick.MP4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/Sliders Media/RGBColorPick.MP4 -------------------------------------------------------------------------------- /Sliders Media/RGBColorPicker.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/Sliders Media/RGBColorPicker.gif -------------------------------------------------------------------------------- /Sliders Media/RadialPadDefault.MP4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/Sliders Media/RadialPadDefault.MP4 -------------------------------------------------------------------------------- /Sliders Media/RadialPadHSBPicker.MP4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/Sliders Media/RadialPadHSBPicker.MP4 -------------------------------------------------------------------------------- /Sliders Media/RadialPadHSBPicker.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/Sliders Media/RadialPadHSBPicker.gif -------------------------------------------------------------------------------- /Sliders Media/SlidersCollage.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/Sliders Media/SlidersCollage.PNG -------------------------------------------------------------------------------- /Sliders Media/TrackPadGraphStyle.MP4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/Sliders Media/TrackPadGraphStyle.MP4 -------------------------------------------------------------------------------- /Sliders Media/TrackPadGraphStyle.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/Sliders Media/TrackPadGraphStyle.gif -------------------------------------------------------------------------------- /Sliders Media/TrackPadHSBColorPicker.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/Sliders Media/TrackPadHSBColorPicker.gif -------------------------------------------------------------------------------- /Sliders Media/TrackPadHSBPicker.MP4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/Sliders Media/TrackPadHSBPicker.MP4 -------------------------------------------------------------------------------- /SlidersExamples.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 52; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 8967B0E024425025007173AF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8967B0DF24425025007173AF /* AppDelegate.swift */; }; 11 | 8967B0E224425025007173AF /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8967B0E124425025007173AF /* SceneDelegate.swift */; }; 12 | 8967B0E424425025007173AF /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8967B0E324425025007173AF /* ContentView.swift */; }; 13 | 8967B0E62442502A007173AF /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8967B0E52442502A007173AF /* Assets.xcassets */; }; 14 | 8967B0E92442502A007173AF /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8967B0E82442502A007173AF /* Preview Assets.xcassets */; }; 15 | 8967B0EC2442502A007173AF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8967B0EA2442502A007173AF /* LaunchScreen.storyboard */; }; 16 | 8967B0F52442508C007173AF /* Sliders in Frameworks */ = {isa = PBXBuildFile; productRef = 8967B0F42442508C007173AF /* Sliders */; }; 17 | 8967B0F7244250CE007173AF /* JoystickExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8967B0F6244250CE007173AF /* JoystickExample.swift */; }; 18 | 89ED1594244257950057DFBB /* LSliderExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89ED1593244257950057DFBB /* LSliderExample.swift */; }; 19 | 89ED1596244266E20057DFBB /* ActivityRings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89ED1595244266E20057DFBB /* ActivityRings.swift */; }; 20 | 89ED159824426DB10057DFBB /* HSBColorPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89ED159724426DB10057DFBB /* HSBColorPicker.swift */; }; 21 | 89ED159A24426F9D0057DFBB /* RadialPadExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89ED159924426F9C0057DFBB /* RadialPadExample.swift */; }; 22 | 89ED159D2442700D0057DFBB /* HueCircleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89ED159C2442700D0057DFBB /* HueCircleView.swift */; }; 23 | 89ED159F244272970057DFBB /* OverflowSliderExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89ED159E244272970057DFBB /* OverflowSliderExample.swift */; }; 24 | 89ED15A2244275B30057DFBB /* KnobStyleExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89ED15A1244275B30057DFBB /* KnobStyleExample.swift */; }; 25 | 89ED15A4244276AA0057DFBB /* DefaultRSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89ED15A3244276AA0057DFBB /* DefaultRSlider.swift */; }; 26 | 89ED15A7244277430057DFBB /* RGBColorPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89ED15A6244277430057DFBB /* RGBColorPicker.swift */; }; 27 | 89ED15AA24427A4D0057DFBB /* DefaultTrackPadExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89ED15A924427A4D0057DFBB /* DefaultTrackPadExample.swift */; }; 28 | 89ED15AC24427C9E0057DFBB /* GraphingGrid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89ED15AB24427C9E0057DFBB /* GraphingGrid.swift */; }; 29 | 89ED15AE24427E9F0057DFBB /* DefaultRadialPad.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89ED15AD24427E9F0057DFBB /* DefaultRadialPad.swift */; }; 30 | /* End PBXBuildFile section */ 31 | 32 | /* Begin PBXFileReference section */ 33 | 8967B0DC24425025007173AF /* SlidersExamples.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SlidersExamples.app; sourceTree = BUILT_PRODUCTS_DIR; }; 34 | 8967B0DF24425025007173AF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 35 | 8967B0E124425025007173AF /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; 36 | 8967B0E324425025007173AF /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; 37 | 8967B0E52442502A007173AF /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 38 | 8967B0E82442502A007173AF /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; 39 | 8967B0EB2442502A007173AF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 40 | 8967B0ED2442502A007173AF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 41 | 8967B0F6244250CE007173AF /* JoystickExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JoystickExample.swift; sourceTree = ""; }; 42 | 89ED1593244257950057DFBB /* LSliderExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LSliderExample.swift; sourceTree = ""; }; 43 | 89ED1595244266E20057DFBB /* ActivityRings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityRings.swift; sourceTree = ""; }; 44 | 89ED159724426DB10057DFBB /* HSBColorPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HSBColorPicker.swift; sourceTree = ""; }; 45 | 89ED159924426F9C0057DFBB /* RadialPadExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RadialPadExample.swift; sourceTree = ""; }; 46 | 89ED159C2442700D0057DFBB /* HueCircleView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HueCircleView.swift; sourceTree = ""; }; 47 | 89ED159E244272970057DFBB /* OverflowSliderExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverflowSliderExample.swift; sourceTree = ""; }; 48 | 89ED15A1244275B30057DFBB /* KnobStyleExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KnobStyleExample.swift; sourceTree = ""; }; 49 | 89ED15A3244276AA0057DFBB /* DefaultRSlider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultRSlider.swift; sourceTree = ""; }; 50 | 89ED15A6244277430057DFBB /* RGBColorPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RGBColorPicker.swift; sourceTree = ""; }; 51 | 89ED15A924427A4D0057DFBB /* DefaultTrackPadExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultTrackPadExample.swift; sourceTree = ""; }; 52 | 89ED15AB24427C9E0057DFBB /* GraphingGrid.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GraphingGrid.swift; sourceTree = ""; }; 53 | 89ED15AD24427E9F0057DFBB /* DefaultRadialPad.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultRadialPad.swift; sourceTree = ""; }; 54 | /* End PBXFileReference section */ 55 | 56 | /* Begin PBXFrameworksBuildPhase section */ 57 | 8967B0D924425025007173AF /* Frameworks */ = { 58 | isa = PBXFrameworksBuildPhase; 59 | buildActionMask = 2147483647; 60 | files = ( 61 | 8967B0F52442508C007173AF /* Sliders in Frameworks */, 62 | ); 63 | runOnlyForDeploymentPostprocessing = 0; 64 | }; 65 | /* End PBXFrameworksBuildPhase section */ 66 | 67 | /* Begin PBXGroup section */ 68 | 8967B0D324425024007173AF = { 69 | isa = PBXGroup; 70 | children = ( 71 | 8967B0DE24425025007173AF /* SlidersExamples */, 72 | 8967B0DD24425025007173AF /* Products */, 73 | ); 74 | sourceTree = ""; 75 | }; 76 | 8967B0DD24425025007173AF /* Products */ = { 77 | isa = PBXGroup; 78 | children = ( 79 | 8967B0DC24425025007173AF /* SlidersExamples.app */, 80 | ); 81 | name = Products; 82 | sourceTree = ""; 83 | }; 84 | 8967B0DE24425025007173AF /* SlidersExamples */ = { 85 | isa = PBXGroup; 86 | children = ( 87 | 8967B0DF24425025007173AF /* AppDelegate.swift */, 88 | 8967B0E124425025007173AF /* SceneDelegate.swift */, 89 | 8967B0E324425025007173AF /* ContentView.swift */, 90 | 89ED159E244272970057DFBB /* OverflowSliderExample.swift */, 91 | 8967B0F6244250CE007173AF /* JoystickExample.swift */, 92 | 89ED15A5244277250057DFBB /* LSliderExamples */, 93 | 89ED159B24426FFB0057DFBB /* RadialPadExamples */, 94 | 89ED15A824427A070057DFBB /* TrackpadExamples */, 95 | 89ED15A0244275570057DFBB /* RSliderExamples */, 96 | 8967B0E52442502A007173AF /* Assets.xcassets */, 97 | 8967B0EA2442502A007173AF /* LaunchScreen.storyboard */, 98 | 8967B0ED2442502A007173AF /* Info.plist */, 99 | 8967B0E72442502A007173AF /* Preview Content */, 100 | ); 101 | path = SlidersExamples; 102 | sourceTree = ""; 103 | }; 104 | 8967B0E72442502A007173AF /* Preview Content */ = { 105 | isa = PBXGroup; 106 | children = ( 107 | 8967B0E82442502A007173AF /* Preview Assets.xcassets */, 108 | ); 109 | path = "Preview Content"; 110 | sourceTree = ""; 111 | }; 112 | 89ED159B24426FFB0057DFBB /* RadialPadExamples */ = { 113 | isa = PBXGroup; 114 | children = ( 115 | 89ED159C2442700D0057DFBB /* HueCircleView.swift */, 116 | 89ED15AD24427E9F0057DFBB /* DefaultRadialPad.swift */, 117 | 89ED159924426F9C0057DFBB /* RadialPadExample.swift */, 118 | ); 119 | path = RadialPadExamples; 120 | sourceTree = ""; 121 | }; 122 | 89ED15A0244275570057DFBB /* RSliderExamples */ = { 123 | isa = PBXGroup; 124 | children = ( 125 | 89ED1595244266E20057DFBB /* ActivityRings.swift */, 126 | 89ED15A3244276AA0057DFBB /* DefaultRSlider.swift */, 127 | 89ED15A1244275B30057DFBB /* KnobStyleExample.swift */, 128 | ); 129 | path = RSliderExamples; 130 | sourceTree = ""; 131 | }; 132 | 89ED15A5244277250057DFBB /* LSliderExamples */ = { 133 | isa = PBXGroup; 134 | children = ( 135 | 89ED1593244257950057DFBB /* LSliderExample.swift */, 136 | 89ED15A6244277430057DFBB /* RGBColorPicker.swift */, 137 | ); 138 | path = LSliderExamples; 139 | sourceTree = ""; 140 | }; 141 | 89ED15A824427A070057DFBB /* TrackpadExamples */ = { 142 | isa = PBXGroup; 143 | children = ( 144 | 89ED159724426DB10057DFBB /* HSBColorPicker.swift */, 145 | 89ED15AB24427C9E0057DFBB /* GraphingGrid.swift */, 146 | 89ED15A924427A4D0057DFBB /* DefaultTrackPadExample.swift */, 147 | ); 148 | path = TrackpadExamples; 149 | sourceTree = ""; 150 | }; 151 | /* End PBXGroup section */ 152 | 153 | /* Begin PBXNativeTarget section */ 154 | 8967B0DB24425025007173AF /* SlidersExamples */ = { 155 | isa = PBXNativeTarget; 156 | buildConfigurationList = 8967B0F02442502A007173AF /* Build configuration list for PBXNativeTarget "SlidersExamples" */; 157 | buildPhases = ( 158 | 8967B0D824425025007173AF /* Sources */, 159 | 8967B0D924425025007173AF /* Frameworks */, 160 | 8967B0DA24425025007173AF /* Resources */, 161 | ); 162 | buildRules = ( 163 | ); 164 | dependencies = ( 165 | ); 166 | name = SlidersExamples; 167 | packageProductDependencies = ( 168 | 8967B0F42442508C007173AF /* Sliders */, 169 | ); 170 | productName = SlidersExamples; 171 | productReference = 8967B0DC24425025007173AF /* SlidersExamples.app */; 172 | productType = "com.apple.product-type.application"; 173 | }; 174 | /* End PBXNativeTarget section */ 175 | 176 | /* Begin PBXProject section */ 177 | 8967B0D424425025007173AF /* Project object */ = { 178 | isa = PBXProject; 179 | attributes = { 180 | LastSwiftUpdateCheck = 1140; 181 | LastUpgradeCheck = 1140; 182 | ORGANIZATIONNAME = BrownandSons; 183 | TargetAttributes = { 184 | 8967B0DB24425025007173AF = { 185 | CreatedOnToolsVersion = 11.4; 186 | }; 187 | }; 188 | }; 189 | buildConfigurationList = 8967B0D724425025007173AF /* Build configuration list for PBXProject "SlidersExamples" */; 190 | compatibilityVersion = "Xcode 9.3"; 191 | developmentRegion = en; 192 | hasScannedForEncodings = 0; 193 | knownRegions = ( 194 | en, 195 | Base, 196 | ); 197 | mainGroup = 8967B0D324425024007173AF; 198 | packageReferences = ( 199 | 8967B0F32442508C007173AF /* XCRemoteSwiftPackageReference "Sliders" */, 200 | ); 201 | productRefGroup = 8967B0DD24425025007173AF /* Products */; 202 | projectDirPath = ""; 203 | projectRoot = ""; 204 | targets = ( 205 | 8967B0DB24425025007173AF /* SlidersExamples */, 206 | ); 207 | }; 208 | /* End PBXProject section */ 209 | 210 | /* Begin PBXResourcesBuildPhase section */ 211 | 8967B0DA24425025007173AF /* Resources */ = { 212 | isa = PBXResourcesBuildPhase; 213 | buildActionMask = 2147483647; 214 | files = ( 215 | 8967B0EC2442502A007173AF /* LaunchScreen.storyboard in Resources */, 216 | 8967B0E92442502A007173AF /* Preview Assets.xcassets in Resources */, 217 | 8967B0E62442502A007173AF /* Assets.xcassets in Resources */, 218 | ); 219 | runOnlyForDeploymentPostprocessing = 0; 220 | }; 221 | /* End PBXResourcesBuildPhase section */ 222 | 223 | /* Begin PBXSourcesBuildPhase section */ 224 | 8967B0D824425025007173AF /* Sources */ = { 225 | isa = PBXSourcesBuildPhase; 226 | buildActionMask = 2147483647; 227 | files = ( 228 | 89ED159824426DB10057DFBB /* HSBColorPicker.swift in Sources */, 229 | 8967B0F7244250CE007173AF /* JoystickExample.swift in Sources */, 230 | 8967B0E024425025007173AF /* AppDelegate.swift in Sources */, 231 | 89ED1594244257950057DFBB /* LSliderExample.swift in Sources */, 232 | 8967B0E224425025007173AF /* SceneDelegate.swift in Sources */, 233 | 89ED15A4244276AA0057DFBB /* DefaultRSlider.swift in Sources */, 234 | 89ED159F244272970057DFBB /* OverflowSliderExample.swift in Sources */, 235 | 89ED15A2244275B30057DFBB /* KnobStyleExample.swift in Sources */, 236 | 89ED15AE24427E9F0057DFBB /* DefaultRadialPad.swift in Sources */, 237 | 89ED15AA24427A4D0057DFBB /* DefaultTrackPadExample.swift in Sources */, 238 | 89ED1596244266E20057DFBB /* ActivityRings.swift in Sources */, 239 | 89ED15A7244277430057DFBB /* RGBColorPicker.swift in Sources */, 240 | 89ED159D2442700D0057DFBB /* HueCircleView.swift in Sources */, 241 | 8967B0E424425025007173AF /* ContentView.swift in Sources */, 242 | 89ED159A24426F9D0057DFBB /* RadialPadExample.swift in Sources */, 243 | 89ED15AC24427C9E0057DFBB /* GraphingGrid.swift in Sources */, 244 | ); 245 | runOnlyForDeploymentPostprocessing = 0; 246 | }; 247 | /* End PBXSourcesBuildPhase section */ 248 | 249 | /* Begin PBXVariantGroup section */ 250 | 8967B0EA2442502A007173AF /* LaunchScreen.storyboard */ = { 251 | isa = PBXVariantGroup; 252 | children = ( 253 | 8967B0EB2442502A007173AF /* Base */, 254 | ); 255 | name = LaunchScreen.storyboard; 256 | sourceTree = ""; 257 | }; 258 | /* End PBXVariantGroup section */ 259 | 260 | /* Begin XCBuildConfiguration section */ 261 | 8967B0EE2442502A007173AF /* Debug */ = { 262 | isa = XCBuildConfiguration; 263 | buildSettings = { 264 | ALWAYS_SEARCH_USER_PATHS = NO; 265 | CLANG_ANALYZER_NONNULL = YES; 266 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 267 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 268 | CLANG_CXX_LIBRARY = "libc++"; 269 | CLANG_ENABLE_MODULES = YES; 270 | CLANG_ENABLE_OBJC_ARC = YES; 271 | CLANG_ENABLE_OBJC_WEAK = YES; 272 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 273 | CLANG_WARN_BOOL_CONVERSION = YES; 274 | CLANG_WARN_COMMA = YES; 275 | CLANG_WARN_CONSTANT_CONVERSION = YES; 276 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 277 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 278 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 279 | CLANG_WARN_EMPTY_BODY = YES; 280 | CLANG_WARN_ENUM_CONVERSION = YES; 281 | CLANG_WARN_INFINITE_RECURSION = YES; 282 | CLANG_WARN_INT_CONVERSION = YES; 283 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 284 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 285 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 286 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 287 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 288 | CLANG_WARN_STRICT_PROTOTYPES = YES; 289 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 290 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 291 | CLANG_WARN_UNREACHABLE_CODE = YES; 292 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 293 | COPY_PHASE_STRIP = NO; 294 | DEBUG_INFORMATION_FORMAT = dwarf; 295 | ENABLE_STRICT_OBJC_MSGSEND = YES; 296 | ENABLE_TESTABILITY = YES; 297 | GCC_C_LANGUAGE_STANDARD = gnu11; 298 | GCC_DYNAMIC_NO_PIC = NO; 299 | GCC_NO_COMMON_BLOCKS = YES; 300 | GCC_OPTIMIZATION_LEVEL = 0; 301 | GCC_PREPROCESSOR_DEFINITIONS = ( 302 | "DEBUG=1", 303 | "$(inherited)", 304 | ); 305 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 306 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 307 | GCC_WARN_UNDECLARED_SELECTOR = YES; 308 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 309 | GCC_WARN_UNUSED_FUNCTION = YES; 310 | GCC_WARN_UNUSED_VARIABLE = YES; 311 | IPHONEOS_DEPLOYMENT_TARGET = 13.4; 312 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 313 | MTL_FAST_MATH = YES; 314 | ONLY_ACTIVE_ARCH = YES; 315 | SDKROOT = iphoneos; 316 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 317 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 318 | }; 319 | name = Debug; 320 | }; 321 | 8967B0EF2442502A007173AF /* Release */ = { 322 | isa = XCBuildConfiguration; 323 | buildSettings = { 324 | ALWAYS_SEARCH_USER_PATHS = NO; 325 | CLANG_ANALYZER_NONNULL = YES; 326 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 327 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 328 | CLANG_CXX_LIBRARY = "libc++"; 329 | CLANG_ENABLE_MODULES = YES; 330 | CLANG_ENABLE_OBJC_ARC = YES; 331 | CLANG_ENABLE_OBJC_WEAK = YES; 332 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 333 | CLANG_WARN_BOOL_CONVERSION = YES; 334 | CLANG_WARN_COMMA = YES; 335 | CLANG_WARN_CONSTANT_CONVERSION = YES; 336 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 337 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 338 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 339 | CLANG_WARN_EMPTY_BODY = YES; 340 | CLANG_WARN_ENUM_CONVERSION = YES; 341 | CLANG_WARN_INFINITE_RECURSION = YES; 342 | CLANG_WARN_INT_CONVERSION = YES; 343 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 344 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 345 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 346 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 347 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 348 | CLANG_WARN_STRICT_PROTOTYPES = YES; 349 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 350 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 351 | CLANG_WARN_UNREACHABLE_CODE = YES; 352 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 353 | COPY_PHASE_STRIP = NO; 354 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 355 | ENABLE_NS_ASSERTIONS = NO; 356 | ENABLE_STRICT_OBJC_MSGSEND = YES; 357 | GCC_C_LANGUAGE_STANDARD = gnu11; 358 | GCC_NO_COMMON_BLOCKS = YES; 359 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 360 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 361 | GCC_WARN_UNDECLARED_SELECTOR = YES; 362 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 363 | GCC_WARN_UNUSED_FUNCTION = YES; 364 | GCC_WARN_UNUSED_VARIABLE = YES; 365 | IPHONEOS_DEPLOYMENT_TARGET = 13.4; 366 | MTL_ENABLE_DEBUG_INFO = NO; 367 | MTL_FAST_MATH = YES; 368 | SDKROOT = iphoneos; 369 | SWIFT_COMPILATION_MODE = wholemodule; 370 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 371 | VALIDATE_PRODUCT = YES; 372 | }; 373 | name = Release; 374 | }; 375 | 8967B0F12442502A007173AF /* Debug */ = { 376 | isa = XCBuildConfiguration; 377 | buildSettings = { 378 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 379 | CODE_SIGN_STYLE = Automatic; 380 | DEVELOPMENT_ASSET_PATHS = "\"SlidersExamples/Preview Content\""; 381 | DEVELOPMENT_TEAM = CJ3HCZ6WWQ; 382 | ENABLE_PREVIEWS = YES; 383 | INFOPLIST_FILE = SlidersExamples/Info.plist; 384 | LD_RUNPATH_SEARCH_PATHS = ( 385 | "$(inherited)", 386 | "@executable_path/Frameworks", 387 | ); 388 | PRODUCT_BUNDLE_IDENTIFIER = BrownandSons.SlidersExamples; 389 | PRODUCT_NAME = "$(TARGET_NAME)"; 390 | SWIFT_VERSION = 5.0; 391 | TARGETED_DEVICE_FAMILY = "1,2"; 392 | }; 393 | name = Debug; 394 | }; 395 | 8967B0F22442502A007173AF /* Release */ = { 396 | isa = XCBuildConfiguration; 397 | buildSettings = { 398 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 399 | CODE_SIGN_STYLE = Automatic; 400 | DEVELOPMENT_ASSET_PATHS = "\"SlidersExamples/Preview Content\""; 401 | DEVELOPMENT_TEAM = CJ3HCZ6WWQ; 402 | ENABLE_PREVIEWS = YES; 403 | INFOPLIST_FILE = SlidersExamples/Info.plist; 404 | LD_RUNPATH_SEARCH_PATHS = ( 405 | "$(inherited)", 406 | "@executable_path/Frameworks", 407 | ); 408 | PRODUCT_BUNDLE_IDENTIFIER = BrownandSons.SlidersExamples; 409 | PRODUCT_NAME = "$(TARGET_NAME)"; 410 | SWIFT_VERSION = 5.0; 411 | TARGETED_DEVICE_FAMILY = "1,2"; 412 | }; 413 | name = Release; 414 | }; 415 | /* End XCBuildConfiguration section */ 416 | 417 | /* Begin XCConfigurationList section */ 418 | 8967B0D724425025007173AF /* Build configuration list for PBXProject "SlidersExamples" */ = { 419 | isa = XCConfigurationList; 420 | buildConfigurations = ( 421 | 8967B0EE2442502A007173AF /* Debug */, 422 | 8967B0EF2442502A007173AF /* Release */, 423 | ); 424 | defaultConfigurationIsVisible = 0; 425 | defaultConfigurationName = Release; 426 | }; 427 | 8967B0F02442502A007173AF /* Build configuration list for PBXNativeTarget "SlidersExamples" */ = { 428 | isa = XCConfigurationList; 429 | buildConfigurations = ( 430 | 8967B0F12442502A007173AF /* Debug */, 431 | 8967B0F22442502A007173AF /* Release */, 432 | ); 433 | defaultConfigurationIsVisible = 0; 434 | defaultConfigurationName = Release; 435 | }; 436 | /* End XCConfigurationList section */ 437 | 438 | /* Begin XCRemoteSwiftPackageReference section */ 439 | 8967B0F32442508C007173AF /* XCRemoteSwiftPackageReference "Sliders" */ = { 440 | isa = XCRemoteSwiftPackageReference; 441 | repositoryURL = "https://github.com/kieranb662/Sliders.git"; 442 | requirement = { 443 | kind = upToNextMajorVersion; 444 | minimumVersion = 1.0.0; 445 | }; 446 | }; 447 | /* End XCRemoteSwiftPackageReference section */ 448 | 449 | /* Begin XCSwiftPackageProductDependency section */ 450 | 8967B0F42442508C007173AF /* Sliders */ = { 451 | isa = XCSwiftPackageProductDependency; 452 | package = 8967B0F32442508C007173AF /* XCRemoteSwiftPackageReference "Sliders" */; 453 | productName = Sliders; 454 | }; 455 | /* End XCSwiftPackageProductDependency section */ 456 | }; 457 | rootObject = 8967B0D424425025007173AF /* Project object */; 458 | } 459 | -------------------------------------------------------------------------------- /SlidersExamples.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SlidersExamples.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SlidersExamples.xcodeproj/xcuserdata/kieran.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SlidersExamples.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /SlidersExamples/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SlidersExamples 4 | // 5 | // Created by Kieran Brown on 4/11/20. 6 | // Copyright © 2020 BrownandSons. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | // MARK: UISceneSession Lifecycle 22 | 23 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 24 | // Called when a new scene session is being created. 25 | // Use this method to select a configuration to create the new scene with. 26 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 27 | } 28 | 29 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 30 | // Called when the user discards a scene session. 31 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 32 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 33 | } 34 | 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /SlidersExamples/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "Icon-App-20x20@2x.png", 5 | "idiom" : "iphone", 6 | "scale" : "2x", 7 | "size" : "20x20" 8 | }, 9 | { 10 | "filename" : "Icon-App-20x20@3x.png", 11 | "idiom" : "iphone", 12 | "scale" : "3x", 13 | "size" : "20x20" 14 | }, 15 | { 16 | "filename" : "Icon-App-29x29@1x.png", 17 | "idiom" : "iphone", 18 | "scale" : "1x", 19 | "size" : "29x29" 20 | }, 21 | { 22 | "filename" : "Icon-App-29x29@2x.png", 23 | "idiom" : "iphone", 24 | "scale" : "2x", 25 | "size" : "29x29" 26 | }, 27 | { 28 | "filename" : "Icon-App-29x29@3x.png", 29 | "idiom" : "iphone", 30 | "scale" : "3x", 31 | "size" : "29x29" 32 | }, 33 | { 34 | "filename" : "Icon-App-40x40@2x.png", 35 | "idiom" : "iphone", 36 | "scale" : "2x", 37 | "size" : "40x40" 38 | }, 39 | { 40 | "filename" : "Icon-App-40x40@3x.png", 41 | "idiom" : "iphone", 42 | "scale" : "3x", 43 | "size" : "40x40" 44 | }, 45 | { 46 | "filename" : "Icon-App-60x60@2x.png", 47 | "idiom" : "iphone", 48 | "scale" : "2x", 49 | "size" : "60x60" 50 | }, 51 | { 52 | "filename" : "Icon-App-60x60@3x.png", 53 | "idiom" : "iphone", 54 | "scale" : "3x", 55 | "size" : "60x60" 56 | }, 57 | { 58 | "filename" : "Icon-App-20x20@1x.png", 59 | "idiom" : "ipad", 60 | "scale" : "1x", 61 | "size" : "20x20" 62 | }, 63 | { 64 | "filename" : "Icon-App-20x20@2x.png", 65 | "idiom" : "ipad", 66 | "scale" : "2x", 67 | "size" : "20x20" 68 | }, 69 | { 70 | "filename" : "Icon-App-29x29@1x.png", 71 | "idiom" : "ipad", 72 | "scale" : "1x", 73 | "size" : "29x29" 74 | }, 75 | { 76 | "filename" : "Icon-App-29x29@2x.png", 77 | "idiom" : "ipad", 78 | "scale" : "2x", 79 | "size" : "29x29" 80 | }, 81 | { 82 | "filename" : "Icon-App-40x40@1x.png", 83 | "idiom" : "ipad", 84 | "scale" : "1x", 85 | "size" : "40x40" 86 | }, 87 | { 88 | "filename" : "Icon-App-40x40@2x.png", 89 | "idiom" : "ipad", 90 | "scale" : "2x", 91 | "size" : "40x40" 92 | }, 93 | { 94 | "filename" : "Icon-App-76x76@1x.png", 95 | "idiom" : "ipad", 96 | "scale" : "1x", 97 | "size" : "76x76" 98 | }, 99 | { 100 | "filename" : "Icon-App-76x76@2x.png", 101 | "idiom" : "ipad", 102 | "scale" : "2x", 103 | "size" : "76x76" 104 | }, 105 | { 106 | "filename" : "Icon-App-83.5x83.5@2x.png", 107 | "idiom" : "ipad", 108 | "scale" : "2x", 109 | "size" : "83.5x83.5" 110 | }, 111 | { 112 | "filename" : "ItunesArtwork@2x.png", 113 | "idiom" : "ios-marketing", 114 | "scale" : "1x", 115 | "size" : "1024x1024" 116 | }, 117 | { 118 | "filename" : "Icon-App-76x76@2x.png", 119 | "idiom" : "iphone", 120 | "scale" : "2x", 121 | "size" : "76x76" 122 | } 123 | ], 124 | "info" : { 125 | "author" : "xcode", 126 | "version" : 1 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /SlidersExamples/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/SlidersExamples/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /SlidersExamples/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/SlidersExamples/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /SlidersExamples/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/SlidersExamples/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /SlidersExamples/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/SlidersExamples/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /SlidersExamples/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/SlidersExamples/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /SlidersExamples/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/SlidersExamples/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /SlidersExamples/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/SlidersExamples/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /SlidersExamples/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/SlidersExamples/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /SlidersExamples/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/SlidersExamples/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /SlidersExamples/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/SlidersExamples/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /SlidersExamples/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/SlidersExamples/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /SlidersExamples/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/SlidersExamples/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /SlidersExamples/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/SlidersExamples/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /SlidersExamples/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/SlidersExamples/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /SlidersExamples/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kieranb662/SlidersExamples/f99d512fcc455fd8d9ddba489d6a2602f0b8d51f/SlidersExamples/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png -------------------------------------------------------------------------------- /SlidersExamples/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SlidersExamples/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /SlidersExamples/ContentView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView.swift 3 | // SlidersExamples 4 | // 5 | // Created by Kieran Brown on 4/11/20. 6 | // Copyright © 2020 BrownandSons. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | 11 | struct ContentView: View { 12 | var body: some View { 13 | NavigationView { 14 | List { 15 | Section(header: Text("LSlider")) { 16 | NavigationLink("LSlider", destination: LSliderExample()) 17 | NavigationLink("RGB Color Picker", destination: RGBColorPickerExample()) 18 | } 19 | Section(header: Text("RSlider")) { 20 | NavigationLink("Default Style", destination: DefaultRSlider()) 21 | NavigationLink("Knob Style", destination: KnobStyleExample()) 22 | NavigationLink("Activity Rings", destination: ActivityRingExample()) 23 | } 24 | Section(header: Text("OverflowSlider")) { 25 | NavigationLink("OverflowSlider", destination: OverflowSliderExample()) 26 | } 27 | 28 | Section(header: Text("TrackPad")) { 29 | NavigationLink("Default Style", destination: DefaultTrackPadExample()) 30 | NavigationLink("Graph Style", destination: GraphStyleExample()) 31 | NavigationLink("HSB Color Picker", destination: HSBColorPickerExample()) 32 | 33 | } 34 | Section(header: Text("RadialPad")) { 35 | NavigationLink("Default Style", destination: DefaultRadialPad()) 36 | NavigationLink("HSB Color Picker", destination: CircularHSBPickerExample()) 37 | } 38 | 39 | Section(header: Text("Joystick")) { 40 | NavigationLink("JoyStick", destination: JoystickExample()) 41 | } 42 | 43 | 44 | }.navigationBarTitle("Sliders Examples") 45 | } 46 | } 47 | } 48 | 49 | struct ContentView_Previews: PreviewProvider { 50 | static var previews: some View { 51 | ContentView() 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /SlidersExamples/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | UISceneConfigurations 28 | 29 | UIWindowSceneSessionRoleApplication 30 | 31 | 32 | UISceneConfigurationName 33 | Default Configuration 34 | UISceneDelegateClassName 35 | $(PRODUCT_MODULE_NAME).SceneDelegate 36 | 37 | 38 | 39 | 40 | UILaunchStoryboardName 41 | LaunchScreen 42 | UIRequiredDeviceCapabilities 43 | 44 | armv7 45 | 46 | UISupportedInterfaceOrientations 47 | 48 | UIInterfaceOrientationPortrait 49 | UIInterfaceOrientationLandscapeLeft 50 | UIInterfaceOrientationLandscapeRight 51 | 52 | UISupportedInterfaceOrientations~ipad 53 | 54 | UIInterfaceOrientationPortrait 55 | UIInterfaceOrientationPortraitUpsideDown 56 | UIInterfaceOrientationLandscapeLeft 57 | UIInterfaceOrientationLandscapeRight 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /SlidersExamples/JoystickExample.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JoystickExample.swift 3 | // SlidersExamples 4 | // 5 | // Created by Kieran Brown on 4/11/20. 6 | // Copyright © 2020 BrownandSons. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import Sliders 11 | import CGExtender 12 | 13 | 14 | struct JoystickExample: View { 15 | @State var state: JoyState = .inactive 16 | @State var rectOffset: CGSize = .zero 17 | @State var canLock: Bool = true 18 | @State var angle: Angle = .zero 19 | let timer = Timer.publish(every: 0.016, on: .main, in: .common).autoconnect() 20 | 21 | var overlay: some View { 22 | 23 | return VStack(alignment: .leading, spacing: 5){ 24 | Text("Drag Anywhere To Begin").font(.title) 25 | Text("The yellow/black circle is the") + Text(" lockbox.").italic() + 26 | Text(" Try releasing the gesture inside the yellow circle") 27 | 28 | Group { 29 | HStack { 30 | Spacer() 31 | Text("x").bold().frame(width: 100) 32 | Text("y").bold().frame(width: 100) 33 | } 34 | Divider() 35 | HStack { 36 | Text("Translation:").bold().fixedSize() 37 | Spacer() 38 | Text("\(String(format: "%.0f", state.translation.width))").frame(width: 100) 39 | Text("\(String(format: "%.0f", state.translation.height))").frame(width: 100) 40 | } 41 | Divider() 42 | HStack { 43 | Text("Velocity:").bold().fixedSize() 44 | Spacer() 45 | Text("\(String(format: "%.0f", state.velocity.width))").frame(width: 100) 46 | Text("\(String(format: "%.0f", state.velocity.height))").frame(width: 100) 47 | } 48 | Divider() 49 | HStack { 50 | Text("Acceleration:").bold().fixedSize() 51 | Spacer() 52 | Text("\(String(format: "%.0f", state.acceleration.width))").frame(width: 100) 53 | Text("\(String(format: "%.0f", state.acceleration.height))").frame(width: 100) 54 | } 55 | Divider() 56 | } 57 | 58 | HStack { 59 | Toggle(isOn: $canLock, label: {Text("Can Lock")}).frame(maxWidth: 150) 60 | Spacer() 61 | Text(self.state.isLocked ? "Locked" : "Not Locked") 62 | Spacer() 63 | } 64 | 65 | }.offset(x: 0, y: -200) 66 | .padding(.horizontal, 30) 67 | } 68 | var body: some View { 69 | Joystick(state: $state, radius: 50, canLock: canLock, isDisabled: false) 70 | .background(Rectangle() 71 | .fill(Color.red) 72 | .frame(width: 50, height: 50) 73 | .rotationEffect(angle) 74 | .offset(rectOffset) 75 | .onReceive(timer, perform: { (time) in 76 | if self.state.translation != .zero { 77 | let scale = 5*sqrt(self.state.translation.magnitudeSquared)/50.0 78 | let x = scale*cos(self.state.angle.radians) 79 | let y = scale*sin(self.state.angle.radians) 80 | self.rectOffset += CGSize(width: x, height: y) 81 | } 82 | 83 | if self.state.isLocked { 84 | self.angle += Angle(degrees: 1) 85 | } 86 | }) 87 | .animation(.linear)) 88 | .overlay(overlay) 89 | .navigationBarTitle("Joystick") 90 | } 91 | } 92 | 93 | struct JoystickExample_Previews: PreviewProvider { 94 | static var previews: some View { 95 | JoystickExample() 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /SlidersExamples/LSliderExamples/LSliderExample.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LSliderExample.swift 3 | // SlidersExamples 4 | // 5 | // Created by Kieran Brown on 4/11/20. 6 | // Copyright © 2020 BrownandSons. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import Sliders 11 | import Shapes 12 | 13 | struct AngleSliderStyle: RSliderStyle { 14 | func makeThumb(configuration: RSliderConfiguration) -> some View { 15 | GeometryReader { proxy in 16 | ZStack { 17 | Triangle() 18 | .fill(Color.white) 19 | .contentShape(Triangle()) 20 | .rotationEffect(Angle(degrees: 90)) 21 | .frame(width: proxy.size.height/2, height: proxy.size.height/3) 22 | .offset(x: -proxy.size.height/4) 23 | }.rotationEffect(configuration.angle ) 24 | } 25 | } 26 | func makeTrack(configuration: RSliderConfiguration) -> some View { 27 | Circle().fill(Color.gray) 28 | } 29 | } 30 | 31 | struct LengthSliderStyle: LSliderStyle { 32 | func makeThumb(configuration: LSliderConfiguration) -> some View { 33 | GeometryReader { proxy in 34 | ZStack { 35 | Pentagon().stroke(configuration.isActive ? Color.green : Color.blue) 36 | .frame(width: 30, height: 35) 37 | .offset(x: 0, y: 2.5) 38 | }.contentShape(Pentagon()) 39 | .rotationEffect(configuration.angle) 40 | } 41 | } 42 | func makeTrack(configuration: LSliderConfiguration) -> some View { 43 | GeometryReader { proxy in 44 | ZStack { 45 | TickMarks(spacing: abs(configuration.angle.degrees) == 90 ? proxy.size.height/20 : proxy.size.width/20, ticks: 20) 46 | .stroke(Color.white) 47 | .frame(width: abs(configuration.angle.degrees) == 90 ? proxy.size.height : proxy.size.width, height: abs(configuration.angle.degrees) == 90 ? proxy.size.width : proxy.size.height).clipped() 48 | }.overlay(RoundedRectangle(cornerRadius: 5).stroke(Color.gray)) 49 | .rotationEffect(configuration.angle) 50 | } 51 | } 52 | } 53 | 54 | 55 | struct LSliderExample: View { 56 | @State var value: Double = 0 57 | @State var angle: Double = 0 58 | @State var width: Double = 100 59 | @State var height: Double = -200 60 | let spacing: CGFloat = 30 61 | let angleSliderRadius: CGFloat = 90 62 | 63 | var body: some View { 64 | ZStack { 65 | Color(white: 0.2) 66 | VStack(alignment: .leading, spacing: 0) { 67 | HStack(alignment: .bottom, spacing: spacing) { 68 | LSlider($height, range: -400...(-1), angle: Angle(degrees: 90)) 69 | .frame(width: 40, height: 400) 70 | .linearSliderStyle(LengthSliderStyle()) 71 | LSlider($value, range: 0...1, angle: Angle(degrees: angle)) 72 | .padding(20) 73 | .frame(width: CGFloat(width), height: CGFloat(-height)) 74 | .border(Color.blue) 75 | 76 | }.offset(x: angleSliderRadius/4) 77 | HStack(spacing: 0) { 78 | RSlider($angle, range: 0...360) 79 | .frame(width: angleSliderRadius, height: angleSliderRadius).radialSliderStyle(AngleSliderStyle()) 80 | LSlider($width, range: 1...260, angle: .zero) 81 | .frame(height: 40) 82 | .linearSliderStyle(LengthSliderStyle()) 83 | } 84 | } 85 | .frame(width: 350) 86 | } 87 | .navigationBarTitle("LSlider") 88 | } 89 | } 90 | 91 | struct LSliderExample_Previews: PreviewProvider { 92 | static var previews: some View { 93 | LSliderExample() 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /SlidersExamples/LSliderExamples/RGBColorPicker.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RGBColorPicker.swift 3 | // SlidersExamples 4 | // 5 | // Created by Kieran Brown on 4/11/20. 6 | // Copyright © 2020 BrownandSons. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import Sliders 11 | import Shapes 12 | 13 | 14 | 15 | struct RGBSliderStyle: LSliderStyle { 16 | enum ColorType: String, CaseIterable { 17 | case red 18 | case green 19 | case blue 20 | } 21 | var strokeWidth: CGFloat 22 | var type: ColorType 23 | var color: (red: Double, green: Double, blue: Double) 24 | var colors: [Color] { 25 | switch type { 26 | case .red: 27 | return [Color(red: 0, green: color.green, blue: color.blue), 28 | Color(red: 1, green: color.green, blue: color.blue)] 29 | case .green: 30 | return [Color(red: color.red, green: 0, blue: color.blue), 31 | Color(red: color.red, green: 1, blue: color.blue)] 32 | case .blue: 33 | return [Color(red: color.red, green: color.green, blue: 0), 34 | Color(red: color.red, green: color.green, blue: 1)] 35 | } 36 | } 37 | 38 | func makeThumb(configuration: LSliderConfiguration) -> some View { 39 | let currentColor: Color = { 40 | switch type { 41 | case .red: 42 | return Color(red: Double(configuration.pctFill), green: 0, blue: 0) 43 | case .green: 44 | return Color(red: 0, green: Double(configuration.pctFill), blue: 0) 45 | case .blue: 46 | return Color(red: 0, green: 0, blue: Double(configuration.pctFill)) 47 | } 48 | }() 49 | 50 | 51 | return ZStack { 52 | Circle() 53 | .fill(Color.white) 54 | .shadow(radius: 2) 55 | Circle() 56 | .fill(currentColor) 57 | .scaleEffect(0.8) 58 | }.frame(width: strokeWidth, height: strokeWidth) 59 | } 60 | 61 | func makeTrack(configuration: LSliderConfiguration) -> some View { 62 | let style: StrokeStyle = .init(lineWidth: strokeWidth, lineCap: .round) 63 | let gradient = LinearGradient(gradient: Gradient(colors: colors), startPoint: .leading, endPoint: .trailing) 64 | return AdaptiveLine(angle: configuration.angle) 65 | .stroke(gradient, style: style) 66 | .overlay(GeometryReader { proxy in 67 | Capsule() 68 | .stroke(Color.white) 69 | .frame(width: proxy.size.width + self.strokeWidth) 70 | .rotationEffect(configuration.angle) 71 | }) 72 | } 73 | } 74 | 75 | struct RGBColorPicker: View { 76 | @Binding var red: Double 77 | @Binding var green: Double 78 | @Binding var blue: Double 79 | 80 | 81 | var sliderHeights: CGFloat = 40 82 | 83 | func makeSlider( _ color: RGBSliderStyle.ColorType) -> some View { 84 | let value: Binding = { 85 | switch color { 86 | case .red: return $red 87 | case .blue: return $blue 88 | case .green: return $green 89 | } 90 | }() 91 | 92 | return LSlider(value, range: 0...1, angle: .zero) 93 | .linearSliderStyle(RGBSliderStyle(strokeWidth: sliderHeights, type: color, color: (red, green, blue))) 94 | .frame(height: sliderHeights) 95 | } 96 | 97 | var body: some View { 98 | VStack(spacing: 20){ 99 | makeSlider( .red) 100 | makeSlider(.green) 101 | makeSlider(.blue) 102 | } 103 | } 104 | } 105 | 106 | struct RGBColorPickerExample: View { 107 | @State var red: Double = 0.2 108 | @State var green: Double = 0.5 109 | @State var blue: Double = 0.8 110 | var overlay: some View { 111 | VStack { 112 | Text("r: \(String(format: "%.0f", red*255))") 113 | Text("g: \(String(format: "%.0f", green*255))") 114 | Text("b: \(String(format: "%.0f", blue*255))") 115 | Text(Color(red: red, green: green, blue: blue).description) 116 | } 117 | } 118 | var body: some View { 119 | ZStack { 120 | Color(white: 0.2) 121 | 122 | VStack(spacing: 50) { 123 | RoundedRectangle(cornerRadius: 5) 124 | .fill(Color(red: red, green: green, blue: blue)) 125 | .frame(height: 300) 126 | .shadow(radius: 3) 127 | .overlay(self.overlay) 128 | 129 | RGBColorPicker(red: $red, green: $green, blue: $blue) 130 | 131 | }.padding(.horizontal, 40) 132 | }.navigationBarTitle("RGB Color Picker") 133 | } 134 | } 135 | 136 | struct RGBColorPicker_Previews: PreviewProvider { 137 | static var previews: some View { 138 | RGBColorPickerExample() 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /SlidersExamples/OverflowSliderExample.swift: -------------------------------------------------------------------------------- 1 | // 2 | // OverflowSliderExample.swift 3 | // SlidersExamples 4 | // 5 | // Created by Kieran Brown on 4/11/20. 6 | // Copyright © 2020 BrownandSons. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import Sliders 11 | 12 | struct OverflowSliderExample: View { 13 | @State var value: Double = 100 14 | var body: some View { 15 | VStack { 16 | Text("1. Try dragging the inside of the capsule and then release it as fast as you can ") 17 | .frame(height: 75) 18 | Text("2. After drag the blue thumb past the left or right edge of the capsule") 19 | .frame(height: 75) 20 | OverflowSlider(value: $value, range: -1000...1000, spacing: 20, isDisabled: false) 21 | .mask(Capsule()) 22 | .overlay(Capsule().stroke(Color.blue)) 23 | .frame(height: 50) 24 | .padding(.horizontal, 30) 25 | }.navigationBarTitle("Overflow Slider") 26 | } 27 | } 28 | 29 | struct OverflowSliderExample_Previews: PreviewProvider { 30 | static var previews: some View { 31 | OverflowSliderExample() 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /SlidersExamples/Preview Content/Preview Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /SlidersExamples/RSliderExamples/ActivityRings.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RSliderExample.swift 3 | // SlidersExamples 4 | // 5 | // Created by Kieran Brown on 4/11/20. 6 | // Copyright © 2020 BrownandSons. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import Sliders 11 | 12 | 13 | struct ActivityRingStyle: RSliderStyle { 14 | var width: CGFloat 15 | var color: Color 16 | func makeThumb(configuration: RSliderConfiguration) -> some View { 17 | ZStack { 18 | Circle() 19 | .fill(configuration.isActive ? color : Color.white) 20 | Circle() 21 | .stroke(configuration.isActive ? color : Color.gray) 22 | } 23 | .frame(width: width, height: width) 24 | } 25 | 26 | func makeTrack(configuration: RSliderConfiguration) -> some View { 27 | let strokeStyle = StrokeStyle(lineWidth: width, lineCap: .butt) 28 | 29 | return Circle().trim(from: 0, to: CGFloat(configuration.pctFill)) 30 | .stroke(color, style: strokeStyle) 31 | 32 | } 33 | } 34 | 35 | struct ActivityRingExample: View { 36 | @State var first: Double = 0.5 37 | @State var second: Double = 0.25 38 | @State var third: Double = 0.75 39 | let width: CGFloat = 60 40 | let startDiameter: CGFloat = 360 41 | 42 | var body: some View { 43 | ZStack { 44 | RSlider($first) 45 | .frame(width: startDiameter, height: startDiameter) 46 | .radialSliderStyle(ActivityRingStyle(width: width ,color: Color.green)) 47 | RSlider($second) 48 | .frame(width: startDiameter-(2*width), height: startDiameter-(2*width)) 49 | .radialSliderStyle(ActivityRingStyle(width: width, color: Color.blue)) 50 | RSlider($third) 51 | .frame(width: startDiameter-(4*width), height: startDiameter-(4*width)) 52 | .radialSliderStyle(ActivityRingStyle(width: width, color: Color.red)) 53 | }.navigationBarTitle("Activity Rings") 54 | } 55 | } 56 | 57 | struct RSliderExample_Previews: PreviewProvider { 58 | static var previews: some View { 59 | ActivityRingExample() 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /SlidersExamples/RSliderExamples/DefaultRSlider.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DefaultRSlider.swift 3 | // SlidersExamples 4 | // 5 | // Created by Kieran Brown on 4/11/20. 6 | // Copyright © 2020 BrownandSons. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import Sliders 11 | 12 | struct DefaultRSlider: View { 13 | @State var value: Double = 0.5 14 | var body: some View { 15 | ZStack { 16 | Color(white: 0.2) 17 | RSlider($value).frame(width: 200, height: 200) 18 | }.navigationBarTitle("Default RSlider Style") 19 | } 20 | } 21 | 22 | struct DefaultRSlider_Previews: PreviewProvider { 23 | static var previews: some View { 24 | DefaultRSlider() 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /SlidersExamples/RSliderExamples/KnobStyleExample.swift: -------------------------------------------------------------------------------- 1 | // 2 | // KnobStyleExample.swift 3 | // SlidersExamples 4 | // 5 | // Created by Kieran Brown on 4/11/20. 6 | // Copyright © 2020 BrownandSons. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import Sliders 11 | 12 | struct KnobStyleExample: View { 13 | @State var value: Double = 0.5 14 | var body: some View { 15 | ZStack { 16 | Color(white: 0.2) 17 | RSlider($value) 18 | .radialSliderStyle(KnobStyle()) 19 | }.navigationBarTitle("RSlider Knob Style") 20 | } 21 | } 22 | 23 | struct KnobStyleExample_Previews: PreviewProvider { 24 | static var previews: some View { 25 | KnobStyleExample() 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /SlidersExamples/RadialPadExamples/DefaultRadialPad.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DefaultRadialPad.swift 3 | // SlidersExamples 4 | // 5 | // Created by Kieran Brown on 4/11/20. 6 | // Copyright © 2020 BrownandSons. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import Sliders 11 | 12 | struct DefaultRadialPad: View { 13 | @State var radius: Double = 0.4 14 | @State var angle: Angle = .zero 15 | var body: some View { 16 | ZStack { 17 | Color(white: 0.2) 18 | RadialPad(offset: $radius, angle: $angle) 19 | .frame(width: 200, height: 200) 20 | }.navigationBarTitle("Default RadialPad Style") 21 | } 22 | } 23 | 24 | struct DefaultRadialPad_Previews: PreviewProvider { 25 | static var previews: some View { 26 | DefaultRadialPad() 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /SlidersExamples/RadialPadExamples/HueCircleView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HueCircleView.swift 3 | // MyExamples 4 | // 5 | // Created by Kieran Brown on 4/8/20. 6 | // Copyright © 2020 BrownandSons. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import UIKit 11 | import simd 12 | import MetalKit 13 | 14 | 15 | 16 | let shader = """ 17 | #include 18 | using namespace metal; 19 | 20 | struct Vertex { 21 | float4 position [[position]]; 22 | float4 color; 23 | }; 24 | 25 | struct Uniforms { 26 | float4x4 modelMatrix; 27 | }; 28 | 29 | vertex Vertex vertex_func(constant Vertex *vertices [[buffer(0)]], 30 | constant Uniforms &uniforms [[buffer(1)]], 31 | uint vid [[vertex_id]]) { 32 | float4x4 matrix = uniforms.modelMatrix; 33 | Vertex in = vertices[vid]; 34 | Vertex out; 35 | out.position = matrix * float4(in.position); 36 | out.color = in.color; 37 | return out; 38 | } 39 | 40 | fragment float4 fragment_func(Vertex vert [[stage_in]]) { 41 | return vert.color; 42 | } 43 | """ 44 | 45 | // FIXME: Shader Library needs to be created with the color picker 46 | public class MetalView: NSObject, MTKViewDelegate { 47 | 48 | public var device: MTLDevice! 49 | var queue: MTLCommandQueue! 50 | var vertexBuffer: MTLBuffer! 51 | var uniformBuffer: MTLBuffer! 52 | var rps: MTLRenderPipelineState! 53 | var vertexData: [Vertex] = [] 54 | 55 | 56 | override public init() { 57 | super.init() 58 | 59 | createVertexPoints() 60 | createBuffers() 61 | registerShaders() 62 | } 63 | 64 | func rgb(h: Float, s: Float, v: Float) -> (r: Float, g: Float, b: Float){ 65 | if s == 0 { return (r: v, g: v, b: v) } // Achromatic grey 66 | 67 | let angle = Float(Int(h)%360) 68 | let sector = angle / 60 // Sector 69 | let i = floor(sector) 70 | let f = sector - i // Factorial part of h 71 | 72 | let p = v * (1 - s) 73 | let q = v * (1 - (s * f)) 74 | let t = v * (1 - (s * (1 - f))) 75 | 76 | switch(i) { 77 | case 0: 78 | return (r: v, g: t, b: p) 79 | case 1: 80 | return (r: q, g: v, b: p) 81 | case 2: 82 | return (r: p, g: v, b: t) 83 | case 3: 84 | return (r: p, g: q, b: v) 85 | case 4: 86 | return (r: t, g: p, b: v) 87 | default: 88 | return (r: v, g: p, b: q) 89 | } 90 | } 91 | 92 | fileprivate func createVertexPoints() { 93 | func rads(forDegree d: Float)->Float32{ 94 | return (Float.pi*d)/180 95 | } 96 | var vertices: [Vertex] = [] 97 | 98 | let origin: vector_float4 = vector_float4([0, 0, 0, 1]) 99 | 100 | for i in 0..<720 { 101 | let position: vector_float4 = vector_float4([cos(rads(forDegree: Float(i)))*2,sin(rads(forDegree: Float(i)))*2, 0, 1]) 102 | let color = rgb(h: 720-Float(i), s: 1, v: 1) 103 | 104 | vertices.append(Vertex(pos: position, col: vector_float4([color.r, color.g, color.b, 1]))) 105 | if (i+1)%2 == 0 { 106 | let col = rgb(h: 720-Float(i), s: 0, v: 1) 107 | let c: vector_float4 = vector_float4([col.r, col.g, col.b, 1]) 108 | vertices.append(Vertex(pos: origin, col: c)) 109 | } 110 | } 111 | self.vertexData = vertices 112 | 113 | } 114 | 115 | func createBuffers() { 116 | device = MTLCreateSystemDefaultDevice() 117 | queue = device.makeCommandQueue() 118 | self.createVertexPoints() 119 | 120 | 121 | vertexBuffer = device!.makeBuffer(bytes: vertexData, length: MemoryLayout.size * vertexData.count , options:[]) 122 | uniformBuffer = device!.makeBuffer(length: MemoryLayout.size * 16, options: []) 123 | let bufferPointer = uniformBuffer.contents() 124 | memcpy(bufferPointer, Matrix().scalingMatrix(Matrix(), 0.5).m, MemoryLayout.size * 16) 125 | } 126 | 127 | func registerShaders() { 128 | let input: String? 129 | let vert_func: MTLFunction 130 | let frag_func: MTLFunction 131 | do { 132 | input = shader 133 | let library = try device.makeLibrary(source: input!, options: nil) 134 | let vert_func = library.makeFunction(name: "vertex_func")! 135 | let frag_func = library.makeFunction(name: "fragment_func")! 136 | let rpld = MTLRenderPipelineDescriptor() 137 | rpld.vertexFunction = vert_func 138 | rpld.fragmentFunction = frag_func 139 | rpld.colorAttachments[0].pixelFormat = .bgra8Unorm 140 | rps = try device!.makeRenderPipelineState(descriptor: rpld) 141 | } catch let e { 142 | Swift.print("\(e)") 143 | } 144 | } 145 | 146 | public func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {} 147 | 148 | public func draw(in view: MTKView) { 149 | if let rpd = view.currentRenderPassDescriptor, 150 | let drawable = view.currentDrawable, 151 | let commandBuffer = queue.makeCommandBuffer(), 152 | let commandEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: rpd) { 153 | rpd.colorAttachments[0].clearColor = MTLClearColor(red: 0, green: 0, blue: 0, alpha: 0) 154 | commandEncoder.setRenderPipelineState(rps) 155 | commandEncoder.setVertexBuffer(vertexBuffer, offset: 0, index: 0) 156 | commandEncoder.setVertexBuffer(uniformBuffer, offset: 0, index: 1) 157 | commandEncoder.drawPrimitives(type: .triangleStrip, vertexStart: 0, vertexCount: vertexData.count, instanceCount: 1) 158 | commandEncoder.endEncoding() 159 | commandBuffer.present(drawable) 160 | commandBuffer.commit() 161 | } 162 | } 163 | } 164 | 165 | struct Vertex { 166 | var position: vector_float4 167 | var color: vector_float4 168 | init(pos: vector_float4, col: vector_float4) { 169 | position = pos 170 | color = col 171 | } 172 | } 173 | struct Matrix { 174 | var m: [Float] 175 | 176 | init() { 177 | m = [1, 0, 0, 0, 178 | 0, 1, 0, 0, 179 | 0, 0, 1, 0, 180 | 0, 0, 0, 1 181 | ] 182 | } 183 | 184 | func translationMatrix(_ matrix: Matrix, _ position: float3) -> Matrix { 185 | var matrix = matrix 186 | matrix.m[12] = position.x 187 | matrix.m[13] = position.y 188 | matrix.m[14] = position.z 189 | return matrix 190 | } 191 | 192 | func scalingMatrix(_ matrix: Matrix, _ scale: Float) -> Matrix { 193 | var matrix = matrix 194 | matrix.m[0] = scale 195 | matrix.m[5] = scale 196 | matrix.m[10] = scale 197 | matrix.m[15] = 1.0 198 | return matrix 199 | } 200 | 201 | 202 | func rotationMatrix(_ matrix: Matrix, _ rot: float3) -> Matrix { 203 | var matrix = matrix 204 | matrix.m[0] = cos(rot.y) * cos(rot.z) 205 | matrix.m[4] = cos(rot.z) * sin(rot.x) * sin(rot.y) - cos(rot.x) * sin(rot.z) 206 | matrix.m[8] = cos(rot.x) * cos(rot.z) * sin(rot.y) + sin(rot.x) * sin(rot.z) 207 | matrix.m[1] = cos(rot.y) * sin(rot.z) 208 | matrix.m[5] = cos(rot.x) * cos(rot.z) + sin(rot.x) * sin(rot.y) * sin(rot.z) 209 | matrix.m[9] = -cos(rot.z) * sin(rot.x) + cos(rot.x) * sin(rot.y) * sin(rot.z) 210 | matrix.m[2] = -sin(rot.y) 211 | matrix.m[6] = cos(rot.y) * sin(rot.x) 212 | matrix.m[10] = cos(rot.x) * cos(rot.y) 213 | matrix.m[15] = 1.0 214 | return matrix 215 | } 216 | 217 | func modelMatrix(matrix: Matrix) -> Matrix { 218 | var matrix = matrix 219 | matrix = rotationMatrix(matrix, float3(0.0, 0.0, 0.1)) 220 | matrix = scalingMatrix(matrix, 0.25) 221 | matrix = translationMatrix(matrix, float3(0.0, 0.5, 0.0)) 222 | return matrix 223 | } 224 | } 225 | 226 | struct HueCircleMetalView: UIViewRepresentable { 227 | typealias UIViewType = MTKView 228 | var size: CGSize 229 | 230 | var delegate: MetalView 231 | init(_ size: CGSize) { 232 | self.size = size 233 | self.delegate = MetalView() 234 | } 235 | 236 | func makeUIView(context: Context) -> MTKView { 237 | let view = MTKView(frame: CGRect(x: 0, y: 0, width: size.width, height: size.height), device: delegate.device) 238 | view.delegate = delegate 239 | 240 | return view 241 | } 242 | 243 | func updateUIView(_ uiView: UIViewType, context: Context) { 244 | uiView.frame = CGRect(x: 0, y: 0, width: size.width, height: size.height) 245 | print("updated") 246 | 247 | } 248 | } 249 | 250 | 251 | struct HueCircleView: View { 252 | var body: some View { 253 | ZStack { 254 | GeometryReader { proxy in 255 | HueCircleMetalView(proxy.size) 256 | .mask(Circle()) 257 | } 258 | } 259 | } 260 | } 261 | 262 | struct HueCircleView_Previews: PreviewProvider { 263 | static var previews: some View { 264 | HueCircleView() 265 | } 266 | } 267 | -------------------------------------------------------------------------------- /SlidersExamples/RadialPadExamples/RadialPadExample.swift: -------------------------------------------------------------------------------- 1 | // 2 | // RadialPadExample.swift 3 | // SlidersExamples 4 | // 5 | // Created by Kieran Brown on 4/11/20. 6 | // Copyright © 2020 BrownandSons. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import Sliders 11 | import Shapes 12 | 13 | 14 | 15 | struct BrightnessSliderStyle: LSliderStyle { 16 | let hue: Double 17 | let saturation: Double 18 | let brightness: Double 19 | var color: Color { Color(hue: hue, saturation: saturation, brightness: brightness) } 20 | let strokeWidth: CGFloat 21 | var gradient: Gradient { 22 | Gradient(colors: [Color(hue: hue, saturation: saturation, brightness: 0), 23 | Color(hue: hue, saturation: saturation, brightness: 1)]) 24 | } 25 | 26 | func makeThumb(configuration: LSliderConfiguration) -> some View { 27 | ZStack { 28 | Pentagon() 29 | .fill(color) 30 | Pentagon() 31 | .stroke(Color.white, style: .init(lineWidth: 3, lineJoin: .round)) 32 | }.frame(width: strokeWidth/2, height: 0.66*strokeWidth) 33 | .offset(x: 0, y: 0.16*strokeWidth-1.5) 34 | } 35 | 36 | func makeTrack(configuration: LSliderConfiguration) -> some View { 37 | GeometryReader { proxy in 38 | ZStack { 39 | RoundedRectangle(cornerRadius: 5) 40 | .fill(LinearGradient(gradient: self.gradient, startPoint: .leading, endPoint: .trailing)) 41 | RoundedRectangle(cornerRadius: 5) 42 | .stroke(Color.white) 43 | }.frame(width: proxy.size.width) 44 | } 45 | } 46 | } 47 | 48 | struct SaturationHueRadialPad: RadialPadStyle { 49 | let brightness: Double 50 | var hueColors: [Color] { 51 | stride(from: 0, to: 1, by: 0.01).map { 52 | Color(hue: $0, saturation: 1, brightness: brightness) 53 | } 54 | } 55 | 56 | func makeThumb(configuration: RadialPadConfiguration) -> some View { 57 | let color = Color(hue: (configuration.angle.degrees/360), saturation: configuration.radialOffset, brightness: self.brightness) 58 | return ZStack { 59 | Circle() 60 | .fill(Color.white) 61 | Circle() 62 | .inset(by: 6) 63 | .fill(color) 64 | }.frame(width: 45, height: 45) 65 | } 66 | 67 | func makeTrack(configuration: RadialPadConfiguration) -> some View { 68 | ZStack { 69 | Circle() 70 | .fill(Color(hue: 0, saturation: 0, brightness: self.brightness)) 71 | HueCircleView() 72 | .blendMode(.plusDarker) 73 | Circle() 74 | .stroke(Color.white, lineWidth: 2) 75 | } 76 | } 77 | } 78 | 79 | struct CircularHSBColorPicker: View { 80 | @Binding var hue: Double 81 | @Binding var saturation: Double 82 | @Binding var brightness: Double 83 | var sliderHeight: CGFloat = 40 84 | 85 | var body: some View { 86 | VStack(spacing: 20) { 87 | RadialPad(offset: $saturation, 88 | angle: Binding(get: { Angle(degrees: self.hue*360) }, 89 | set: { self.hue = $0.degrees/360 })) 90 | .radialPadStyle(SaturationHueRadialPad(brightness: brightness)) 91 | LSlider($brightness, range: 0...1, angle: .zero) 92 | .linearSliderStyle(BrightnessSliderStyle(hue: hue, saturation: saturation, brightness: brightness, strokeWidth: sliderHeight)) 93 | .frame(height: sliderHeight) 94 | } 95 | } 96 | } 97 | 98 | struct CircularHSBPickerExample: View { 99 | @State var hue: Double = 0.5 100 | @State var saturation: Double = 0.5 101 | @State var brightness: Double = 0.5 102 | 103 | var body: some View { 104 | ZStack { 105 | Color(white: 0.2) 106 | CircularHSBColorPicker(hue: $hue, saturation: $saturation, brightness: $brightness) 107 | .frame(height: 400) 108 | .padding(50) 109 | }.navigationBarTitle("Circular HSB Picker") 110 | } 111 | } 112 | 113 | struct RadialPadExample_Previews: PreviewProvider { 114 | static var previews: some View { 115 | CircularHSBPickerExample() 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /SlidersExamples/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // SlidersExamples 4 | // 5 | // Created by Kieran Brown on 4/11/20. 6 | // Copyright © 2020 BrownandSons. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import SwiftUI 11 | 12 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 18 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 19 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 20 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 21 | 22 | // Create the SwiftUI view that provides the window contents. 23 | let contentView = ContentView() 24 | 25 | // Use a UIHostingController as window root view controller. 26 | if let windowScene = scene as? UIWindowScene { 27 | let window = UIWindow(windowScene: windowScene) 28 | window.rootViewController = UIHostingController(rootView: contentView) 29 | self.window = window 30 | window.makeKeyAndVisible() 31 | } 32 | } 33 | 34 | func sceneDidDisconnect(_ scene: UIScene) { 35 | // Called as the scene is being released by the system. 36 | // This occurs shortly after the scene enters the background, or when its session is discarded. 37 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 38 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). 39 | } 40 | 41 | func sceneDidBecomeActive(_ scene: UIScene) { 42 | // Called when the scene has moved from an inactive state to an active state. 43 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 44 | } 45 | 46 | func sceneWillResignActive(_ scene: UIScene) { 47 | // Called when the scene will move from an active state to an inactive state. 48 | // This may occur due to temporary interruptions (ex. an incoming phone call). 49 | } 50 | 51 | func sceneWillEnterForeground(_ scene: UIScene) { 52 | // Called as the scene transitions from the background to the foreground. 53 | // Use this method to undo the changes made on entering the background. 54 | } 55 | 56 | func sceneDidEnterBackground(_ scene: UIScene) { 57 | // Called as the scene transitions from the foreground to the background. 58 | // Use this method to save data, release shared resources, and store enough scene-specific state information 59 | // to restore the scene back to its current state. 60 | } 61 | 62 | 63 | } 64 | 65 | -------------------------------------------------------------------------------- /SlidersExamples/TrackpadExamples/DefaultTrackPadExample.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DefaultTrackPadExample.swift 3 | // SlidersExamples 4 | // 5 | // Created by Kieran Brown on 4/11/20. 6 | // Copyright © 2020 BrownandSons. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import Sliders 11 | 12 | 13 | struct DefaultTrackPadExample: View { 14 | @State var value: CGPoint = .zero 15 | var body: some View { 16 | TrackPad($value) 17 | .frame(width: 200, height: 300) 18 | .navigationBarTitle("Default TrackPad") 19 | } 20 | } 21 | 22 | struct DefaultTrackPadExample_Previews: PreviewProvider { 23 | static var previews: some View { 24 | DefaultTrackPadExample() 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /SlidersExamples/TrackpadExamples/GraphingGrid.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SwiftUIView.swift 3 | // SlidersExamples 4 | // 5 | // Created by Kieran Brown on 4/11/20. 6 | // Copyright © 2020 BrownandSons. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import Sliders 11 | import Shapes 12 | 13 | public struct CrossHair: View { 14 | var color: Color 15 | var length: CGFloat 16 | func line(angle: CGFloat, proxy: GeometryProxy) -> some View { 17 | let midX = proxy.frame(in: .local).width/2 18 | let midY = proxy.frame(in: .local).height/2 19 | 20 | return Path { p in 21 | p.move(to: CGPoint(x: midX, y: midY-9)) 22 | p.addLine(to: CGPoint(x: midX, y: midY+length)) 23 | }.rotation(Angle(degrees: Double(angle)), anchor: .top) 24 | .stroke(color, lineWidth: 5) 25 | } 26 | 27 | /// # Crosshair 28 | /// - parameters: 29 | /// - color The color of the crosshair 30 | /// - lineLength: The length of each of the for lines that converge to the center of the crosshair. 31 | public init(color: Color = .black, lineLength: CGFloat = 20) { 32 | self.color = color 33 | self.length = lineLength 34 | } 35 | 36 | public var body: some View { 37 | ZStack { 38 | Circle().stroke(self.color, lineWidth: 4).frame(width: 40, height: 40) 39 | .overlay(GeometryReader { (proxy: GeometryProxy) in 40 | ZStack { 41 | self.line(angle: 0, proxy: proxy) 42 | self.line(angle: 90, proxy: proxy) 43 | self.line(angle: 180, proxy: proxy) 44 | self.line(angle: 270, proxy: proxy) 45 | }.offset(CGSize(width: 0, height: proxy.frame(in: .local).height/2)) 46 | }) 47 | .contentShape(Circle()) 48 | 49 | 50 | } 51 | } 52 | } 53 | 54 | struct GraphStyle: TrackPadStyle { 55 | func makeThumb(configuration: TrackPadConfiguration) -> some View { 56 | CrossHair(color: Color.blue, lineLength: 20) 57 | } 58 | func makeTrack(configuration: TrackPadConfiguration) -> some View { 59 | CartesianGrid(xCount: 7, yCount: 7).stroke(Color.gray) 60 | .overlay(RoundedRectangle(cornerRadius: 5).stroke(Color.white)) 61 | } 62 | } 63 | 64 | struct GraphStyleExample: View { 65 | @State var value: CGPoint = .zero 66 | var body: some View { 67 | ZStack { 68 | Color(white: 0.2) 69 | TrackPad($value) 70 | .trackPadStyle(GraphStyle()) 71 | .frame(width: 300, height: 300) 72 | }.navigationBarTitle("Graph Style Trackpad") 73 | } 74 | } 75 | 76 | struct SwiftUIView_Previews: PreviewProvider { 77 | static var previews: some View { 78 | GraphStyleExample() 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /SlidersExamples/TrackpadExamples/HSBColorPicker.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TrackPadExample.swift 3 | // SlidersExamples 4 | // 5 | // Created by Kieran Brown on 4/11/20. 6 | // Copyright © 2020 BrownandSons. All rights reserved. 7 | // 8 | 9 | import SwiftUI 10 | import Sliders 11 | import Shapes 12 | 13 | struct HueSliderStyle: LSliderStyle { 14 | var strokeWidth: CGFloat 15 | private let hueColors = stride(from: 0, to: 1, by: 0.03).map { 16 | Color(hue: $0, saturation: 1, brightness: 1) 17 | } 18 | 19 | func makeThumb(configuration: LSliderConfiguration) -> some View { 20 | return ZStack { 21 | Circle() 22 | .fill(Color.white) 23 | .shadow(radius: 2) 24 | Circle() 25 | .fill(Color(hue: configuration.pctFill, saturation: 1, brightness: 1)) 26 | .scaleEffect(0.8) 27 | }.frame(width: strokeWidth, height: strokeWidth) 28 | } 29 | 30 | func makeTrack(configuration: LSliderConfiguration) -> some View { 31 | let style: StrokeStyle = .init(lineWidth: strokeWidth, lineCap: .round) 32 | let gradient = LinearGradient(gradient: Gradient(colors: hueColors), startPoint: .leading, endPoint: .trailing) 33 | return AdaptiveLine(angle: configuration.angle) 34 | .stroke(gradient, style: style) 35 | .overlay(GeometryReader { proxy in 36 | Capsule() 37 | .stroke(Color.white) 38 | .frame(width: proxy.size.width + self.strokeWidth) 39 | .rotationEffect(configuration.angle) 40 | }) 41 | } 42 | } 43 | 44 | 45 | public struct SaturationBrightnessStyle: TrackPadStyle { 46 | var hue: Double 47 | private var saturationColors: [Color] { 48 | return stride(from: 0, to: 1, by: 0.01).map { 49 | Color(hue: hue, saturation: $0, brightness: 1) 50 | } 51 | } 52 | 53 | public func makeThumb(configuration: TrackPadConfiguration) -> some View { 54 | ZStack { 55 | Circle() 56 | .foregroundColor(configuration.isActive ? .yellow : .white) 57 | Circle() 58 | .fill(Color(hue: self.hue, saturation: Double(configuration.pctX), brightness: Double(configuration.pctY))) 59 | .scaleEffect(0.8) 60 | }.frame(width: 40, height: 40) 61 | } 62 | public func makeTrack(configuration: TrackPadConfiguration) -> some View { 63 | let brightnessGradient = LinearGradient(gradient: Gradient(colors: [Color(red: 1, green: 1, blue: 1), Color(red: 0, green: 0, blue: 0)]), startPoint: .bottom, endPoint: .top) 64 | let saturationGradient = LinearGradient(gradient:Gradient(colors: saturationColors), startPoint: .leading, endPoint: .trailing) 65 | return ZStack { 66 | RoundedRectangle(cornerRadius: 5) 67 | .fill(brightnessGradient) 68 | RoundedRectangle(cornerRadius: 5) 69 | .fill(saturationGradient) 70 | .drawingGroup(opaque: false, colorMode: .extendedLinear) 71 | .blendMode(.plusDarker) 72 | }.overlay(RoundedRectangle(cornerRadius: 5).stroke(Color.white, lineWidth: 2)) 73 | } 74 | } 75 | 76 | 77 | struct HSBColorPicker: View { 78 | @Binding var hue: Double 79 | @Binding var saturation: Double 80 | @Binding var brightness: Double 81 | var sliderHeight: CGFloat = 40 82 | 83 | var body: some View { 84 | let brightnessSaturation = Binding(get: {CGPoint(x: self.saturation, y: self.brightness)}, 85 | set: { (new) in 86 | self.saturation = Double(new.x) 87 | self.brightness = Double(new.y) 88 | }) 89 | 90 | return VStack(spacing: 30) { 91 | TrackPad(value: brightnessSaturation, rangeX: 0.01...1, rangeY: 0.01...1) 92 | .trackPadStyle(SaturationBrightnessStyle(hue: self.hue)) 93 | 94 | LSlider($hue, range: 0...0.999, angle: .zero) 95 | .linearSliderStyle(HueSliderStyle(strokeWidth: sliderHeight)) 96 | .frame(height: sliderHeight) 97 | .padding(.horizontal, sliderHeight/2) 98 | } 99 | } 100 | } 101 | struct HSBColorPickerExample: View { 102 | @State var hue: Double = 0.5 103 | @State var saturation: Double = 0.5 104 | @State var brightness: Double = 0.5 105 | var overlay: some View { 106 | VStack { 107 | Text("h: \(String(format: "%.0f", hue*360))") 108 | Text("s: \(String(format: "%.0f", saturation*100))%") 109 | Text("b: \(String(format: "%.0f", brightness*100))%") 110 | Text(Color(hue: hue, saturation: saturation, brightness: brightness).description) 111 | } 112 | } 113 | var body: some View { 114 | ZStack { 115 | Color(white: 0.2) 116 | VStack(spacing: 0) { 117 | RoundedRectangle(cornerRadius: 5) 118 | .fill(Color(hue: hue, saturation: saturation, brightness: brightness)) 119 | .overlay(overlay) 120 | HSBColorPicker(hue: $hue, saturation: $saturation, brightness: $brightness) 121 | .frame(height: 400) 122 | } 123 | 124 | .padding(50) 125 | }.navigationBarTitle("HSB Color Picker") 126 | } 127 | } 128 | 129 | struct TrackPadExample_Previews: PreviewProvider { 130 | static var previews: some View { 131 | HSBColorPickerExample() 132 | } 133 | } 134 | --------------------------------------------------------------------------------