mirror of
https://github.com/joncardasis/ChromaColorPicker.git
synced 2024-11-25 11:42:12 +03:00
Initial commit
This commit is contained in:
parent
5c04c2cb8f
commit
0830687e0f
@ -12,6 +12,11 @@
|
||||
35C376D61D5CF5300069D7A1 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 35C376D41D5CF5300069D7A1 /* Main.storyboard */; };
|
||||
35C376D81D5CF5300069D7A1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 35C376D71D5CF5300069D7A1 /* Assets.xcassets */; };
|
||||
35C376DB1D5CF5300069D7A1 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 35C376D91D5CF5300069D7A1 /* LaunchScreen.storyboard */; };
|
||||
35C376E71D5CF9400069D7A1 /* JCColorAddButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35C376E21D5CF9400069D7A1 /* JCColorAddButton.swift */; };
|
||||
35C376E81D5CF9400069D7A1 /* JCColorHandle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35C376E31D5CF9400069D7A1 /* JCColorHandle.swift */; };
|
||||
35C376E91D5CF9400069D7A1 /* JCColorPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35C376E41D5CF9400069D7A1 /* JCColorPicker.swift */; };
|
||||
35C376EA1D5CF9400069D7A1 /* JCShadeSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35C376E51D5CF9400069D7A1 /* JCShadeSlider.swift */; };
|
||||
35C376EB1D5CF9400069D7A1 /* UIColor+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 35C376E61D5CF9400069D7A1 /* UIColor+Utilities.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
@ -22,6 +27,11 @@
|
||||
35C376D71D5CF5300069D7A1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
35C376DA1D5CF5300069D7A1 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
35C376DC1D5CF5300069D7A1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
35C376E21D5CF9400069D7A1 /* JCColorAddButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JCColorAddButton.swift; path = JCColorPicker/JCColorAddButton.swift; sourceTree = SOURCE_ROOT; };
|
||||
35C376E31D5CF9400069D7A1 /* JCColorHandle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JCColorHandle.swift; path = JCColorPicker/JCColorHandle.swift; sourceTree = SOURCE_ROOT; };
|
||||
35C376E41D5CF9400069D7A1 /* JCColorPicker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JCColorPicker.swift; path = JCColorPicker/JCColorPicker.swift; sourceTree = SOURCE_ROOT; };
|
||||
35C376E51D5CF9400069D7A1 /* JCShadeSlider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = JCShadeSlider.swift; path = JCColorPicker/JCShadeSlider.swift; sourceTree = SOURCE_ROOT; };
|
||||
35C376E61D5CF9400069D7A1 /* UIColor+Utilities.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "UIColor+Utilities.swift"; path = "JCColorPicker/UIColor+Utilities.swift"; sourceTree = SOURCE_ROOT; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@ -54,6 +64,7 @@
|
||||
35C376CF1D5CF5300069D7A1 /* JCColorPicker-Demo */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
35C376EC1D5CF9450069D7A1 /* JCColorPicker */,
|
||||
35C376D01D5CF5300069D7A1 /* AppDelegate.swift */,
|
||||
35C376D21D5CF5300069D7A1 /* ViewController.swift */,
|
||||
35C376D41D5CF5300069D7A1 /* Main.storyboard */,
|
||||
@ -64,6 +75,18 @@
|
||||
path = "JCColorPicker-Demo";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
35C376EC1D5CF9450069D7A1 /* JCColorPicker */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
35C376E41D5CF9400069D7A1 /* JCColorPicker.swift */,
|
||||
35C376E31D5CF9400069D7A1 /* JCColorHandle.swift */,
|
||||
35C376E21D5CF9400069D7A1 /* JCColorAddButton.swift */,
|
||||
35C376E51D5CF9400069D7A1 /* JCShadeSlider.swift */,
|
||||
35C376E61D5CF9400069D7A1 /* UIColor+Utilities.swift */,
|
||||
);
|
||||
name = JCColorPicker;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
@ -96,6 +119,7 @@
|
||||
TargetAttributes = {
|
||||
35C376CC1D5CF5300069D7A1 = {
|
||||
CreatedOnToolsVersion = 7.3;
|
||||
DevelopmentTeam = 43DKZUY8C6;
|
||||
};
|
||||
};
|
||||
};
|
||||
@ -135,8 +159,13 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
35C376E91D5CF9400069D7A1 /* JCColorPicker.swift in Sources */,
|
||||
35C376D31D5CF5300069D7A1 /* ViewController.swift in Sources */,
|
||||
35C376D11D5CF5300069D7A1 /* AppDelegate.swift in Sources */,
|
||||
35C376E81D5CF9400069D7A1 /* JCColorHandle.swift in Sources */,
|
||||
35C376EB1D5CF9400069D7A1 /* UIColor+Utilities.swift in Sources */,
|
||||
35C376E71D5CF9400069D7A1 /* JCColorAddButton.swift in Sources */,
|
||||
35C376EA1D5CF9400069D7A1 /* JCShadeSlider.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -249,6 +278,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
INFOPLIST_FILE = "JCColorPicker-Demo/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.jonathancardasis.JCColorPicker-Demo";
|
||||
@ -260,6 +290,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
INFOPLIST_FILE = "JCColorPicker-Demo/Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.jonathancardasis.JCColorPicker-Demo";
|
||||
@ -286,6 +317,7 @@
|
||||
35C376E11D5CF5300069D7A1 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
|
@ -5,6 +5,22 @@
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "35C376CC1D5CF5300069D7A1"
|
||||
BuildableName = "JCColorPicker-Demo.app"
|
||||
BlueprintName = "JCColorPicker-Demo"
|
||||
ReferencedContainer = "container:JCColorPicker-Demo.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
@ -13,6 +29,15 @@
|
||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||
<Testables>
|
||||
</Testables>
|
||||
<MacroExpansion>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "35C376CC1D5CF5300069D7A1"
|
||||
BuildableName = "JCColorPicker-Demo.app"
|
||||
BlueprintName = "JCColorPicker-Demo"
|
||||
ReferencedContainer = "container:JCColorPicker-Demo.xcodeproj">
|
||||
</BuildableReference>
|
||||
</MacroExpansion>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</TestAction>
|
||||
@ -26,6 +51,16 @@
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "35C376CC1D5CF5300069D7A1"
|
||||
BuildableName = "JCColorPicker-Demo.app"
|
||||
BlueprintName = "JCColorPicker-Demo"
|
||||
ReferencedContainer = "container:JCColorPicker-Demo.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<AdditionalOptions>
|
||||
</AdditionalOptions>
|
||||
</LaunchAction>
|
||||
@ -35,6 +70,16 @@
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "35C376CC1D5CF5300069D7A1"
|
||||
BuildableName = "JCColorPicker-Demo.app"
|
||||
BlueprintName = "JCColorPicker-Demo"
|
||||
ReferencedContainer = "container:JCColorPicker-Demo.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
|
@ -1,25 +1,66 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6211" systemVersion="14A298i" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="10116" systemVersion="15D21" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6204"/>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="tne-QT-ifu">
|
||||
<objects>
|
||||
<viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<viewController id="BYZ-38-t0r" customClass="ViewController" customModule="JCColorPicker_Demo" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<layoutGuides>
|
||||
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
|
||||
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
|
||||
</layoutGuides>
|
||||
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="X0b-eI-A9U">
|
||||
<rect key="frame" x="182" y="656" width="50" height="50"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="50" id="VaL-Xe-gHc"/>
|
||||
<constraint firstAttribute="width" constant="50" id="oSC-v5-nta"/>
|
||||
</constraints>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="boolean" keyPath="layer.masksToBounds" value="YES"/>
|
||||
<userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
|
||||
<integer key="value" value="6"/>
|
||||
</userDefinedRuntimeAttribute>
|
||||
</userDefinedRuntimeAttributes>
|
||||
</view>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="JCColorPicker" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="guL-Cc-TeO">
|
||||
<rect key="frame" x="104" y="51" width="207" height="21"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="21" id="PkF-mH-S41"/>
|
||||
<constraint firstAttribute="width" constant="207" id="XOI-CR-PLS"/>
|
||||
</constraints>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="26"/>
|
||||
<color key="textColor" red="0.92549020051956177" green="0.93725490570068359" blue="0.94509804248809814" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="See ViewController for how JCColorPicker gets added here." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="4" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="bWG-XF-nzw">
|
||||
<rect key="frame" x="94" y="273" width="227" height="189"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" red="1" green="0.62745100259780884" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.37647058823529411" green="0.49019607843137253" blue="0.54509803921568623" alpha="1" colorSpace="calibratedRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="guL-Cc-TeO" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="NeS-Sh-S22"/>
|
||||
<constraint firstItem="X0b-eI-A9U" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="j8O-1F-Ipd"/>
|
||||
<constraint firstItem="guL-Cc-TeO" firstAttribute="top" secondItem="y3c-jy-aDJ" secondAttribute="bottom" constant="31" id="jcY-2d-hDz"/>
|
||||
<constraint firstItem="wfy-db-euE" firstAttribute="top" secondItem="X0b-eI-A9U" secondAttribute="bottom" constant="30" id="zjG-2C-dZg"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<simulatedScreenMetrics key="simulatedDestinationMetrics" type="retina55"/>
|
||||
</viewController>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
|
||||
</objects>
|
||||
<point key="canvasLocation" x="139" y="366"/>
|
||||
</scene>
|
||||
</scenes>
|
||||
</document>
|
||||
|
77
JCColorPicker/JCColorAddButton.swift
Normal file
77
JCColorPicker/JCColorAddButton.swift
Normal file
@ -0,0 +1,77 @@
|
||||
//
|
||||
// JCColorAddButton.swift
|
||||
//
|
||||
// Created by Jonathan Cardasis on 5/16/16.
|
||||
// Copyright © 2016 Jonathan Cardasis. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class JCColorAddButton: UIButton {
|
||||
var color = UIColor.grayColor(){
|
||||
didSet{
|
||||
if let layer = circleLayer{
|
||||
layer.fillColor = color.CGColor
|
||||
layer.strokeColor = color.darkerColor(0.075).CGColor
|
||||
}
|
||||
}
|
||||
}
|
||||
override var frame: CGRect{ //update on frame change
|
||||
didSet{
|
||||
self.layoutCircleLayer()
|
||||
self.layoutPlusIconLayer()
|
||||
}
|
||||
}
|
||||
var circleLayer: CAShapeLayer?
|
||||
var plusIconLayer: CAShapeLayer?
|
||||
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
self.createGraphics()
|
||||
}
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
self.createGraphics()
|
||||
}
|
||||
|
||||
func createGraphics(){
|
||||
circleLayer = CAShapeLayer()
|
||||
self.layoutCircleLayer()
|
||||
circleLayer!.fillColor = color.CGColor
|
||||
self.layer.addSublayer(circleLayer!)
|
||||
|
||||
/* Create Plus Icon */
|
||||
let plusPath = UIBezierPath()
|
||||
plusPath.moveToPoint(CGPointMake(self.bounds.width/2 - self.bounds.width/8, self.bounds.height/2))
|
||||
plusPath.addLineToPoint(CGPointMake(self.bounds.width/2 + self.bounds.width/8, self.bounds.height/2))
|
||||
plusPath.moveToPoint(CGPointMake(self.bounds.width/2, self.bounds.height/2 + self.bounds.height/8))
|
||||
plusPath.addLineToPoint(CGPointMake(self.bounds.width/2, self.bounds.height/2 - self.bounds.height/8))
|
||||
|
||||
plusIconLayer = CAShapeLayer()
|
||||
self.layoutPlusIconLayer()
|
||||
plusIconLayer!.strokeColor = UIColor.whiteColor().CGColor
|
||||
self.layer.addSublayer(plusIconLayer!)
|
||||
}
|
||||
|
||||
func layoutCircleLayer(){
|
||||
if let layer = circleLayer{
|
||||
layer.path = UIBezierPath(ovalInRect: self.bounds).CGPath
|
||||
layer.lineWidth = frame.width * 0.04 //4 for size (100,100)
|
||||
}
|
||||
}
|
||||
|
||||
func layoutPlusIconLayer(){
|
||||
if let layer = plusIconLayer{
|
||||
let plusPath = UIBezierPath()
|
||||
plusPath.moveToPoint(CGPointMake(self.bounds.width/2 - self.bounds.width/8, self.bounds.height/2))
|
||||
plusPath.addLineToPoint(CGPointMake(self.bounds.width/2 + self.bounds.width/8, self.bounds.height/2))
|
||||
plusPath.moveToPoint(CGPointMake(self.bounds.width/2, self.bounds.height/2 + self.bounds.height/8))
|
||||
plusPath.addLineToPoint(CGPointMake(self.bounds.width/2, self.bounds.height/2 - self.bounds.height/8))
|
||||
|
||||
layer.path = plusPath.CGPath
|
||||
layer.lineWidth = frame.width * 0.03
|
||||
}
|
||||
}
|
||||
|
||||
}
|
57
JCColorPicker/JCColorHandle.swift
Normal file
57
JCColorPicker/JCColorHandle.swift
Normal file
@ -0,0 +1,57 @@
|
||||
//
|
||||
// JCColorHandle.swift
|
||||
//
|
||||
// Created by Jonathan Cardasis on 5/16/16.
|
||||
// Copyright © 2016 Jonathan Cardasis. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class JCColorHandle: UIView {
|
||||
var color = UIColor.blackColor() {
|
||||
didSet{
|
||||
circleLayer.fillColor = color.CGColor
|
||||
}
|
||||
}
|
||||
override var frame: CGRect{
|
||||
didSet { self.layoutCircleLayer() }
|
||||
}
|
||||
var circleLayer = CAShapeLayer()
|
||||
|
||||
var shadowOffset: CGSize?{
|
||||
set{
|
||||
if let offset = newValue {
|
||||
circleLayer.shadowColor = UIColor.blackColor().CGColor
|
||||
circleLayer.shadowRadius = 3
|
||||
circleLayer.shadowOpacity = 0.3
|
||||
circleLayer.shadowOffset = offset
|
||||
}
|
||||
}
|
||||
get{
|
||||
return circleLayer.shadowOffset
|
||||
}
|
||||
}
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame:frame)
|
||||
self.backgroundColor = UIColor.clearColor()
|
||||
|
||||
/* Add Shape Layer */
|
||||
//circleLayer.shouldRasterize = true
|
||||
self.layoutCircleLayer()
|
||||
circleLayer.strokeColor = UIColor.whiteColor().CGColor
|
||||
circleLayer.fillColor = color.CGColor
|
||||
|
||||
self.layer.addSublayer(circleLayer)
|
||||
}
|
||||
|
||||
func layoutCircleLayer(){
|
||||
circleLayer.path = UIBezierPath(ovalInRect: self.bounds).CGPath
|
||||
circleLayer.strokeColor = UIColor.whiteColor().CGColor
|
||||
circleLayer.lineWidth = frame.width/8.75 //4
|
||||
}
|
||||
|
||||
required init(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
359
JCColorPicker/JCColorPicker.swift
Normal file
359
JCColorPicker/JCColorPicker.swift
Normal file
@ -0,0 +1,359 @@
|
||||
//
|
||||
// JCColorPicker.swift
|
||||
//
|
||||
// Created by Jonathan Cardasis on 5/9/16.
|
||||
// Copyright © 2016 Jonathan Cardasis. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
protocol JCColorPickerDelegate {
|
||||
/* Called when the user tapps the add button in the center */
|
||||
func colorPickerDidChooseColor(colorPicker: JCColorPicker, color: UIColor)
|
||||
}
|
||||
|
||||
class JCColorPicker: UIControl {
|
||||
var hexLabel: UILabel!
|
||||
var shadeSlider: JCShadeSlider!
|
||||
var handleView: JCColorHandle!
|
||||
var handleLine: CAShapeLayer!
|
||||
var addButton: JCColorAddButton!
|
||||
|
||||
var currentColor = UIColor()
|
||||
var delegate: JCColorPickerDelegate?
|
||||
var currentAngle: Float = 0
|
||||
var radius: CGFloat = 0
|
||||
var stroke: CGFloat = 1
|
||||
var padding: CGFloat = 15
|
||||
var handleSize: CGSize{
|
||||
get{ return CGSizeMake(self.bounds.width * 0.1, self.bounds.height * 0.1) }
|
||||
}
|
||||
|
||||
//MARK: - Initialization
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
self.commonInit()
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
self.commonInit()
|
||||
}
|
||||
|
||||
private func commonInit(){
|
||||
self.backgroundColor = UIColor.clearColor()
|
||||
|
||||
let minDimension = min(self.bounds.size.width, self.bounds.size.height)
|
||||
radius = minDimension/2 - handleSize.width/2
|
||||
|
||||
/* Setup Handle */
|
||||
handleView = JCColorHandle(frame: CGRectMake(0,0, handleSize.width, handleSize.height))
|
||||
handleView.shadowOffset = CGSizeMake(0,2)
|
||||
|
||||
/* Setup pan gesture for handle */
|
||||
let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(JCColorPicker.handleWasMoved(_:)))
|
||||
handleView.addGestureRecognizer(panRecognizer)
|
||||
|
||||
/* Setup Add Button */
|
||||
addButton = JCColorAddButton()
|
||||
self.layoutAddButton() //layout frame
|
||||
addButton.addTarget(self, action: #selector(JCColorPicker.addButtonPressed(_:)), forControlEvents: .TouchUpInside)
|
||||
|
||||
/* Setup Handle Line */
|
||||
handleLine = CAShapeLayer()
|
||||
handleLine.lineWidth = 2
|
||||
handleLine.strokeColor = UIColor.whiteColor().colorWithAlphaComponent(0.2).CGColor
|
||||
|
||||
/* Setup Color Hex Label */
|
||||
hexLabel = UILabel()
|
||||
self.layoutHexLabel() //layout frame
|
||||
hexLabel.layer.cornerRadius = 2
|
||||
hexLabel.adjustsFontSizeToFitWidth = true
|
||||
hexLabel.textAlignment = .Center
|
||||
hexLabel.textColor = UIColor(red: 51/255.0, green:51/255.0, blue: 51/255.0, alpha: 0.65)
|
||||
|
||||
/* Setup Shade Slider */
|
||||
shadeSlider = JCShadeSlider()
|
||||
shadeSlider.delegate = self
|
||||
self.layoutShadeSlider()
|
||||
|
||||
|
||||
/* Add components to view */
|
||||
self.layer.addSublayer(handleLine)
|
||||
self.addSubview(shadeSlider)
|
||||
self.addSubview(hexLabel)
|
||||
self.addSubview(handleView)
|
||||
self.addSubview(addButton)
|
||||
}
|
||||
|
||||
override func willMoveToSuperview(newSuperview: UIView?) {
|
||||
/* Get the starting color */
|
||||
currentColor = colorOnWheelFromAngle(currentAngle)
|
||||
handleView.center = positionOnWheelFromAngle(currentAngle) //update pos for angle
|
||||
self.layoutHandleLine() //layout the lines positioning
|
||||
|
||||
handleView.color = currentColor
|
||||
addButton.color = currentColor
|
||||
shadeSlider.primaryColor = currentColor
|
||||
self.updateHexLabel() //update for hex value
|
||||
}
|
||||
|
||||
|
||||
//MARK: - Handle Touches
|
||||
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?){
|
||||
//Overriden to prevent uicontrolevents being called from the super
|
||||
}
|
||||
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?){
|
||||
let touchPoint = touches.first!.locationInView(self)
|
||||
if CGRectContainsPoint(handleView.frame, touchPoint) {
|
||||
self.sendActionsForControlEvents(.TouchDown)
|
||||
|
||||
/* Enlarge Animation */
|
||||
UIView.animateWithDuration(0.15, delay: 0, options: .CurveEaseIn, animations: { () -> Void in
|
||||
self.handleView.transform = CGAffineTransformMakeScale(1.45, 1.45)
|
||||
}, completion: nil)
|
||||
}
|
||||
}
|
||||
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
|
||||
//Run this animation after a pan or here if touches are released
|
||||
if handleView.transform.d > 1 { //if scale is larger than 1 (already animated)
|
||||
self.executeHandleShrinkAnimation()
|
||||
}
|
||||
}
|
||||
|
||||
func handleWasMoved(recognizer: UIPanGestureRecognizer) {
|
||||
switch(recognizer.state){
|
||||
|
||||
case UIGestureRecognizerState.Changed:
|
||||
let touchPosition = recognizer.locationInView(self)
|
||||
self.moveHandleTowardPoint(touchPosition)
|
||||
self.sendActionsForControlEvents(.TouchDragInside)
|
||||
break
|
||||
|
||||
case UIGestureRecognizerState.Ended:
|
||||
/* Shrink Animation */
|
||||
self.executeHandleShrinkAnimation()
|
||||
break
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
private func executeHandleShrinkAnimation(){
|
||||
self.sendActionsForControlEvents(.TouchUpInside)
|
||||
UIView.animateWithDuration(0.15, delay: 0, options: .CurveEaseOut, animations: { () -> Void in
|
||||
self.handleView.transform = CGAffineTransformMakeScale(1, 1)
|
||||
}, completion: nil)
|
||||
}
|
||||
|
||||
private func moveHandleTowardPoint(point: CGPoint){
|
||||
currentAngle = angleToCenterFromPoint(point) //Find the angle of point to the frames center
|
||||
|
||||
//Layout Handle
|
||||
self.layoutHandle()
|
||||
|
||||
//Layout Line
|
||||
self.layoutHandleLine()
|
||||
|
||||
//Update color for shade slider
|
||||
shadeSlider.primaryColor = handleView.color//currentColor
|
||||
|
||||
//Update color for add button if a shade isnt selected
|
||||
if shadeSlider.currentValue == 0 {
|
||||
self.updateCurrentColor(shadeSlider.currentColor)
|
||||
}
|
||||
|
||||
//Update Text Field display value
|
||||
self.updateHexLabel()
|
||||
}
|
||||
|
||||
|
||||
func addButtonPressed(sender: JCColorAddButton){
|
||||
//Do a 'bob' animation
|
||||
UIView.animateWithDuration(0.2,
|
||||
delay: 0,
|
||||
options: .CurveEaseIn,
|
||||
animations: { () -> Void in
|
||||
sender.transform = CGAffineTransformMakeScale(1.1, 1.1)
|
||||
}, completion: { (done) -> Void in
|
||||
UIView.animateWithDuration(0.1, animations: { () -> Void in
|
||||
sender.transform = CGAffineTransformMakeScale(1, 1)
|
||||
})
|
||||
})
|
||||
|
||||
delegate?.colorPickerDidChooseColor(self, color: sender.color) //Delegate call
|
||||
}
|
||||
|
||||
|
||||
//MARK: - Drawing
|
||||
override func drawRect(rect: CGRect) {
|
||||
super.drawRect(rect)
|
||||
let ctx = UIGraphicsGetCurrentContext()
|
||||
drawRainbowCircle(in: ctx, outerRadius: radius - padding, innerRadius: radius - stroke - padding, resolution: 1)
|
||||
}
|
||||
|
||||
/*
|
||||
Resolution should be between 0.1 and 1
|
||||
*/
|
||||
func drawRainbowCircle(in context: CGContextRef?, outerRadius: CGFloat, innerRadius: CGFloat, resolution: Float){
|
||||
CGContextSaveGState(context)
|
||||
CGContextTranslateCTM(context, CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds)) //Move context to center
|
||||
|
||||
let subdivisions:CGFloat = CGFloat(resolution * 512) //Max subdivisions of 512
|
||||
|
||||
let innerHeight = (CGFloat(M_PI)*innerRadius)/subdivisions //height of the inner wall for each segment
|
||||
let outterHeight = (CGFloat(M_PI)*outerRadius)/subdivisions
|
||||
|
||||
let segment = UIBezierPath()
|
||||
segment.moveToPoint(CGPointMake(innerRadius, -innerHeight/2))
|
||||
segment.addLineToPoint(CGPointMake(innerRadius, innerHeight/2))
|
||||
segment.addLineToPoint(CGPointMake(outerRadius, outterHeight/2))
|
||||
segment.addLineToPoint(CGPointMake(outerRadius, -outterHeight/2))
|
||||
segment.closePath()
|
||||
|
||||
|
||||
//Draw each segment and rotate around the center
|
||||
for i in 0 ..< Int(ceil(subdivisions)) {
|
||||
UIColor(hue: CGFloat(i)/subdivisions, saturation: 1, brightness: 1, alpha: 1).set()
|
||||
segment.fill()
|
||||
let lineTailSpace = CGFloat(M_PI*2)*outerRadius/subdivisions //The amount of space between the tails of each segment
|
||||
segment.lineWidth = lineTailSpace //allows for seemless scaling
|
||||
segment.stroke()
|
||||
|
||||
//Rotate to correct location
|
||||
let rotate = CGAffineTransformMakeRotation(-(CGFloat(M_PI*2)/subdivisions)) //rotates each segment
|
||||
segment.applyTransform(rotate)
|
||||
}
|
||||
|
||||
CGContextTranslateCTM(context, -CGRectGetMidX(self.bounds), -CGRectGetMidY(self.bounds)) //Move context back to original position
|
||||
CGContextRestoreGState(context)
|
||||
}
|
||||
|
||||
|
||||
//MARK: - Layout Updates
|
||||
/* re-layout view and all its subview and drawings */
|
||||
func layout() {
|
||||
self.setNeedsDisplay() //mark view as dirty
|
||||
|
||||
let minDimension = min(self.bounds.size.width, self.bounds.size.height)
|
||||
radius = minDimension/2 - handleSize.width/2 //create radius for new size
|
||||
|
||||
self.layoutAddButton()
|
||||
|
||||
//Update handle's size
|
||||
handleView.frame = CGRect(origin: .zero, size: handleSize)
|
||||
self.layoutHandle()
|
||||
|
||||
//Ensure colors are updated
|
||||
self.updateCurrentColor(handleView.color)
|
||||
shadeSlider.primaryColor = handleView.color
|
||||
|
||||
self.layoutShadeSlider()
|
||||
self.layoutHandleLine()
|
||||
self.layoutHexLabel()
|
||||
}
|
||||
|
||||
func layoutAddButton(){
|
||||
let addButtonSize = CGSize(width: self.bounds.width/5, height: self.bounds.height/5)
|
||||
addButton.frame = CGRect(x: CGRectGetMidX(self.bounds) - addButtonSize.width/2, y: CGRectGetMidY(self.bounds) - addButtonSize.height/2, width: addButtonSize.width, height: addButtonSize.height)
|
||||
}
|
||||
|
||||
/*
|
||||
Update the handleView's position and color for the currentAngle
|
||||
*/
|
||||
func layoutHandle(){
|
||||
let angle = currentAngle //Preserve value in case it changes
|
||||
let newPosition = positionOnWheelFromAngle(angle) //find the correct position on the color wheel
|
||||
|
||||
//Update handle position
|
||||
handleView.center = newPosition
|
||||
|
||||
//Update color for the movement
|
||||
handleView.color = colorOnWheelFromAngle(angle)
|
||||
}
|
||||
|
||||
/*
|
||||
Updates the line view's position for the current angle
|
||||
Pre: dependant on addButtons position
|
||||
*/
|
||||
func layoutHandleLine(){
|
||||
let linePath = UIBezierPath()
|
||||
linePath.moveToPoint(addButton.center)
|
||||
linePath.addLineToPoint(positionOnWheelFromAngle(currentAngle))
|
||||
handleLine.path = linePath.CGPath
|
||||
}
|
||||
|
||||
/*
|
||||
Pre: dependant on addButtons position
|
||||
*/
|
||||
func layoutHexLabel(){
|
||||
hexLabel.frame = CGRect(x: 0, y: 0, width: addButton.bounds.width*1.5, height: addButton.bounds.height/3)
|
||||
hexLabel.center = CGPointMake(CGRectGetMidX(self.bounds), (addButton.frame.origin.y + (padding + handleView.frame.height/2 + stroke/2))/1.75) //Divided by 1.75 not 2 to make it a bit lower
|
||||
hexLabel.font = UIFont(name: "Menlo-Regular", size: hexLabel.bounds.height)
|
||||
}
|
||||
|
||||
/*
|
||||
Pre: dependant on radius
|
||||
*/
|
||||
func layoutShadeSlider(){
|
||||
/* Calculate proper length for slider */
|
||||
let centerPoint = CGPoint(x: CGRectGetMidX(bounds), y: CGRectGetMidY(bounds))
|
||||
let insideRadius = radius - padding
|
||||
|
||||
let pointLeft = CGPoint(x: centerPoint.x + insideRadius*CGFloat(cos(7*M_PI/6)), y: centerPoint.y - insideRadius*CGFloat(sin(7*M_PI/6)))
|
||||
let pointRight = CGPoint(x: centerPoint.x + insideRadius*CGFloat(cos(11*M_PI/6)), y: centerPoint.y - insideRadius*CGFloat(sin(11*M_PI/6)))
|
||||
let deltaX = pointRight.x - pointLeft.x //distance on circle between points at 7pi/6 and 11pi/6
|
||||
|
||||
|
||||
let sliderSize = CGSize(width: deltaX * 0.75, height: 0.08 * (bounds.height - padding*2))//bounds.height
|
||||
shadeSlider.frame = CGRect(x: bounds.midX - sliderSize.width/2, y: pointLeft.y - sliderSize.height/2, width: sliderSize.width, height: sliderSize.height)
|
||||
shadeSlider.handleCenterX = shadeSlider.bounds.width/2 //set handle starting position
|
||||
shadeSlider.layoutLayerFrames() //call sliders' layout function
|
||||
}
|
||||
|
||||
func updateHexLabel(){
|
||||
hexLabel.text = "#" + currentColor.hexCode
|
||||
}
|
||||
|
||||
func updateCurrentColor(color: UIColor){
|
||||
currentColor = color
|
||||
addButton.color = color
|
||||
self.sendActionsForControlEvents(.ValueChanged)
|
||||
}
|
||||
|
||||
|
||||
//MARK: - Helper Methods
|
||||
private func angleToCenterFromPoint(point: CGPoint) -> Float {
|
||||
let deltaX = Float(CGRectGetMidX(self.bounds) - point.x)
|
||||
let deltaY = Float(CGRectGetMidY(self.bounds) - point.y)
|
||||
let angle = atan2f(deltaX, deltaY)
|
||||
|
||||
// Convert the angle to be between 0 and 2PI
|
||||
var adjustedAngle = angle + Float(M_PI/2)
|
||||
if (adjustedAngle < 0){ //Left side (Q2 and Q3)
|
||||
adjustedAngle += Float(M_PI*2)
|
||||
}
|
||||
|
||||
return adjustedAngle
|
||||
}
|
||||
|
||||
/* Find the angle relative to the center of the frame and uses the angle to find what color lies there */
|
||||
private func colorOnWheelFromAngle(angle: Float) -> UIColor {
|
||||
return UIColor(hue: CGFloat(Double(angle)/(2*M_PI)), saturation: 1, brightness: 1, alpha: 1)
|
||||
}
|
||||
|
||||
/* Returns a position centered on the wheel for a given angle */
|
||||
private func positionOnWheelFromAngle(angle: Float) -> CGPoint{
|
||||
let buffer = padding + stroke/2
|
||||
return CGPoint(x: CGRectGetMidX(self.bounds) + ((radius - buffer) * CGFloat(cos(-angle))), y: CGRectGetMidY(self.bounds) + ((radius - buffer) * CGFloat(sin(-angle))))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension JCColorPicker: JCShadeSliderDelegate{
|
||||
func shadeSliderChoseColor(slider: JCShadeSlider, color: UIColor) {
|
||||
self.updateCurrentColor(color) //update main controller for selected color
|
||||
self.updateHexLabel()
|
||||
}
|
||||
}
|
184
JCColorPicker/JCShadeSlider.swift
Normal file
184
JCColorPicker/JCShadeSlider.swift
Normal file
@ -0,0 +1,184 @@
|
||||
//
|
||||
// JCShadeSlider.swift
|
||||
//
|
||||
// Created by Jonathan Cardasis on 7/7/16.
|
||||
// Copyright © 2016 Jonathan Cardasis. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class JCSliderTrackLayer: CALayer{
|
||||
let gradient = CAGradientLayer()
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
gradient.actions = ["position" : NSNull(), "bounds" : NSNull(), "path" : NSNull()]
|
||||
self.addSublayer(gradient)
|
||||
}
|
||||
override init(layer: AnyObject) {
|
||||
super.init(layer: layer)
|
||||
}
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
}
|
||||
|
||||
protocol JCShadeSliderDelegate {
|
||||
func shadeSliderChoseColor(slider: JCShadeSlider, color: UIColor)
|
||||
}
|
||||
|
||||
class JCShadeSlider: UIControl {
|
||||
var currentValue: CGFloat = 0.0 //range of {-1,1}
|
||||
|
||||
let trackLayer = JCSliderTrackLayer()
|
||||
let handleView = JCColorHandle()
|
||||
var handleWidth: CGFloat{ return self.bounds.height }
|
||||
var handleCenterX: CGFloat = 0.0
|
||||
var delegate: JCShadeSliderDelegate?
|
||||
|
||||
var primaryColor = UIColor.grayColor(){
|
||||
didSet{
|
||||
self.changeColorHue(to: currentColor)
|
||||
self.updateGradientTrack(for: primaryColor)
|
||||
}
|
||||
}
|
||||
/* The computed color of the primary color with shading based on the currentValue */
|
||||
var currentColor: UIColor{
|
||||
get{
|
||||
if currentValue < 0 {//darken
|
||||
return primaryColor.darkerColor(-currentValue)
|
||||
}
|
||||
else{ //lighten
|
||||
return primaryColor.lighterColor(currentValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
self.commonInit()
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
super.init(coder: aDecoder)
|
||||
self.commonInit()
|
||||
}
|
||||
|
||||
private func commonInit(){
|
||||
self.backgroundColor = nil
|
||||
handleCenterX = self.bounds.width/2
|
||||
|
||||
trackLayer.backgroundColor = UIColor.blueColor().CGColor
|
||||
trackLayer.masksToBounds = true
|
||||
trackLayer.actions = ["position" : NSNull(), "bounds" : NSNull(), "path" : NSNull()] //disable implicit animations
|
||||
self.layer.addSublayer(trackLayer)
|
||||
|
||||
handleView.color = UIColor.blueColor()
|
||||
handleView.circleLayer.borderWidth = 3
|
||||
handleView.userInteractionEnabled = false //disable interaction for touch events
|
||||
self.layer.addSublayer(handleView.layer)
|
||||
|
||||
let doubleTapGesture = UITapGestureRecognizer(target: self, action: #selector(resetHandleToCenter))
|
||||
doubleTapGesture.numberOfTapsRequired = 2
|
||||
self.addGestureRecognizer(doubleTapGesture)
|
||||
|
||||
self.layoutLayerFrames()
|
||||
self.changeColorHue(to: currentColor)
|
||||
self.updateGradientTrack(for: primaryColor)
|
||||
}
|
||||
|
||||
override func didMoveToSuperview() {
|
||||
self.updateGradientTrack(for: primaryColor)
|
||||
}
|
||||
|
||||
func layoutLayerFrames(){
|
||||
trackLayer.frame = self.bounds.insetBy(dx: handleWidth/2, dy: self.bounds.height/4) //Make half the height of the bounds
|
||||
trackLayer.cornerRadius = trackLayer.bounds.height/2
|
||||
|
||||
self.updateGradientTrack(for: primaryColor)
|
||||
handleCenterX = (currentValue+1)/2 * (bounds.width - handleView.bounds.width) + handleView.bounds.width/2 //Update where the handles center should be
|
||||
self.layoutHandleFrame()
|
||||
}
|
||||
|
||||
//Lays out handle according to the currentValue on slider
|
||||
func layoutHandleFrame(){
|
||||
handleView.frame = CGRect(x: handleCenterX - handleWidth/2, y: self.bounds.height/2 - handleWidth/2, width: handleWidth, height: handleWidth)
|
||||
}
|
||||
|
||||
func changeColorHue(to newColor: UIColor){
|
||||
handleView.color = newColor
|
||||
if currentValue != 0 { //Don't call delegate if the color hasnt changed
|
||||
self.delegate?.shadeSliderChoseColor(self, color: newColor)
|
||||
}
|
||||
}
|
||||
|
||||
func updateGradientTrack(for color: UIColor){
|
||||
trackLayer.gradient.frame = trackLayer.bounds
|
||||
trackLayer.gradient.startPoint = CGPoint(x: 0, y: 0.5)
|
||||
trackLayer.gradient.endPoint = CGPoint(x: 1, y: 0.5)
|
||||
|
||||
//Gradient is for astetics - the slider is actually between black and white
|
||||
trackLayer.gradient.colors = [color.darkerColor(0.65).CGColor, color.CGColor, color.lighterColor(0.65).CGColor]
|
||||
}
|
||||
|
||||
|
||||
override func beginTrackingWithTouch(touch: UITouch, withEvent event: UIEvent?) -> Bool {
|
||||
let location = touch.locationInView(self)
|
||||
|
||||
if handleView.frame.contains(location) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override func continueTrackingWithTouch(touch: UITouch, withEvent event: UIEvent?) -> Bool {
|
||||
let location = touch.locationInView(self)
|
||||
|
||||
//Update for center point
|
||||
handleCenterX = location.x
|
||||
handleCenterX = fittedValueInBounds(handleCenterX) //adjust value to fit in bounds if needed
|
||||
|
||||
|
||||
//Update current value
|
||||
currentValue = ((handleCenterX - handleWidth/2)/trackLayer.bounds.width - 0.5) * 2 //find current value between {-1,1} of the slider
|
||||
|
||||
//Update handle color
|
||||
self.changeColorHue(to: currentColor)
|
||||
|
||||
//Update layers frames
|
||||
CATransaction.begin()
|
||||
CATransaction.setDisableActions(true)
|
||||
self.layoutHandleFrame()
|
||||
CATransaction.commit()
|
||||
|
||||
self.sendActionsForControlEvents(.ValueChanged)
|
||||
return true
|
||||
}
|
||||
|
||||
func resetHandleToCenter(recognizer: UITapGestureRecognizer){
|
||||
let location = recognizer.locationInView(self)
|
||||
guard handleView.frame.contains(location) else {
|
||||
return
|
||||
}
|
||||
|
||||
//tap is on handle
|
||||
handleCenterX = self.bounds.width/2
|
||||
self.layoutHandleFrame()
|
||||
handleView.color = primaryColor
|
||||
currentValue = 0.0
|
||||
|
||||
self.sendActionsForControlEvents(.ValueChanged)
|
||||
self.delegate?.shadeSliderChoseColor(self, color: currentColor)
|
||||
}
|
||||
|
||||
/* Helper Methods */
|
||||
//Returns a CGFloat for the highest/lowest possble value such that it is inside the views bounds
|
||||
private func fittedValueInBounds(value: CGFloat) -> CGFloat {
|
||||
return min(max(value, trackLayer.frame.minX), trackLayer.frame.maxX)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
59
JCColorPicker/UIColor+Utilities.swift
Normal file
59
JCColorPicker/UIColor+Utilities.swift
Normal file
@ -0,0 +1,59 @@
|
||||
//
|
||||
// UIColor+Utilities.swift
|
||||
// JCUIElements
|
||||
//
|
||||
// Created by Jonathan Cardasis on 8/17/15.
|
||||
// Copyright (c) 2015 Jonathan Cardasis. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
extension UIColor{
|
||||
var hexCode: String {
|
||||
get{
|
||||
let colorComponents = CGColorGetComponents(self.CGColor)
|
||||
return String(format: "%02x%02x%02x", Int(colorComponents[0]*255.0), Int(colorComponents[1]*255.0),Int(colorComponents[2]*255.0)).uppercaseString
|
||||
}
|
||||
}
|
||||
|
||||
//Amount should be between 0 and 1
|
||||
func lighterColor(amount: CGFloat) -> UIColor{
|
||||
return UIColor.blendColors(color: self, destinationColor: UIColor.whiteColor(), amount: amount)
|
||||
}
|
||||
|
||||
func darkerColor(amount: CGFloat) -> UIColor{
|
||||
return UIColor.blendColors(color: self, destinationColor: UIColor.blackColor(), amount: amount)
|
||||
}
|
||||
|
||||
static func blendColors(color color: UIColor, destinationColor: UIColor, amount : CGFloat) -> UIColor{
|
||||
var amountToBlend = amount;
|
||||
if amountToBlend > 1{
|
||||
amountToBlend = 1.0
|
||||
}
|
||||
else if amountToBlend < 0{
|
||||
amountToBlend = 0
|
||||
}
|
||||
|
||||
var r,g,b, alpha : CGFloat
|
||||
r = 0
|
||||
g = 0
|
||||
b = 0
|
||||
alpha = 0
|
||||
color.getRed(&r, green: &g, blue: &b, alpha: &alpha) //gets the rgba values (0-1)
|
||||
|
||||
//Get the destination rgba values
|
||||
var dest_r, dest_g, dest_b, dest_alpha : CGFloat
|
||||
dest_r = 0
|
||||
dest_g = 0
|
||||
dest_b = 0
|
||||
dest_alpha = 0
|
||||
destinationColor.getRed(&dest_r, green: &dest_g, blue: &dest_b, alpha: &dest_alpha)
|
||||
|
||||
r = amountToBlend * (dest_r * 255) + (1 - amountToBlend) * (r * 255)
|
||||
g = amountToBlend * (dest_g * 255) + (1 - amountToBlend) * (g * 255)
|
||||
b = amountToBlend * (dest_b * 255) + (1 - amountToBlend) * (b * 255)
|
||||
alpha = fabs(alpha / dest_alpha)
|
||||
|
||||
return UIColor(red: r/255.0, green: g/255.0, blue: b/255.0, alpha: alpha)
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user