-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
40 changed files
with
1,559 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
// | ||
// UIPitView.swift | ||
// LimberTabbar | ||
// | ||
// Created by Afshin Hoseini on 4/7/19. | ||
// Copyright © 2019 Afshin Hoseini. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
import UIKit | ||
|
||
@IBDesignable | ||
public class AHPitView : UIView { | ||
|
||
//MARK:- Properties | ||
var borderLayer = CAShapeLayer() | ||
var guideRectsLayer = CAShapeLayer() | ||
let pitDepth = CGFloat(40) | ||
let maxDepth = CGFloat(40) | ||
|
||
@IBInspectable | ||
public var pitPositionScale = CGFloat(0) { | ||
|
||
didSet { | ||
|
||
renderBorder() | ||
} | ||
} | ||
|
||
@IBInspectable | ||
public var pitDepthScale = CGFloat(0) { | ||
|
||
didSet { | ||
|
||
renderBorder() | ||
} | ||
} | ||
|
||
@IBInspectable | ||
public var showRects = true { | ||
|
||
didSet { | ||
renderBorder() | ||
} | ||
} | ||
|
||
//MARK:- Initializers | ||
public override init(frame: CGRect) { | ||
super.init(frame: frame) | ||
commonInit() | ||
} | ||
|
||
public required init?(coder aDecoder: NSCoder) { | ||
super.init(coder: aDecoder) | ||
commonInit() | ||
} | ||
|
||
func commonInit() { | ||
|
||
//Initializes border and guide rects layers | ||
|
||
borderLayer.bounds = bounds | ||
borderLayer.fillColor = UIColor.red.cgColor | ||
borderLayer.strokeColor = UIColor.red.cgColor | ||
borderLayer.position = CGPoint(x: 0, y: 0) | ||
borderLayer.anchorPoint = CGPoint(x: 0, y: 0) | ||
borderLayer.lineJoin = .round | ||
|
||
borderLayer.shadowColor = UIColor.black.cgColor | ||
borderLayer.shadowOffset = CGSize(width: 0, height: -2) | ||
borderLayer.shadowRadius = 1 | ||
borderLayer.shadowOpacity = 0.3 | ||
|
||
|
||
guideRectsLayer.fillColor = nil | ||
guideRectsLayer.strokeColor = UIColor.cyan.cgColor | ||
guideRectsLayer.position = CGPoint(x: 0, y: 0) | ||
guideRectsLayer.bounds = bounds | ||
guideRectsLayer.anchorPoint = CGPoint(x: 0, y: 0) | ||
|
||
layer.addSublayer(borderLayer) | ||
layer.addSublayer(guideRectsLayer) | ||
|
||
renderBorder() | ||
self.backgroundColor = nil | ||
} | ||
|
||
//MARK:- Functions | ||
public override func prepareForInterfaceBuilder() { | ||
|
||
pitPositionScale = CGFloat(0.5) | ||
pitDepthScale = CGFloat(1) | ||
} | ||
|
||
/** | ||
* Renders the border of view including the hole | ||
*/ | ||
func renderBorder() { | ||
|
||
//Initial calculations | ||
let pitWidth = CGMutablePath.calculatePitWith(maxPitDepth: pitDepth) | ||
let y = CGFloat(0) | ||
let possibleDiggingWidth = bounds.width - pitWidth | ||
let holeStartingPointX = CGFloat(possibleDiggingWidth * pitPositionScale) | ||
|
||
//Creates the hole | ||
let borderPath = CGMutablePath() | ||
borderPath.move(to: CGPoint.zero) | ||
borderPath.addLine(to: CGPoint(x: holeStartingPointX, y: y)) | ||
|
||
let guideRects = borderPath.addPit(toPath: borderPath, startingPointX: holeStartingPointX, y: y, depth: pitDepth, scale: pitDepthScale).guideRects | ||
|
||
borderPath.addLine(to: CGPoint(x: bounds.width, y: 0)) | ||
borderPath.addLine(to: CGPoint(x: bounds.width, y: bounds.height)) | ||
borderPath.addLine(to: CGPoint(x: 0, y: bounds.height)) | ||
borderPath.addLine(to: CGPoint(x: 0, y: 0)) | ||
|
||
borderLayer.path = borderPath | ||
|
||
//Rects layer | ||
|
||
if (showRects) { | ||
|
||
let rectPath = CGMutablePath() | ||
rectPath.addRects(guideRects) | ||
guideRectsLayer.path = rectPath | ||
} | ||
else { | ||
guideRectsLayer.path = nil | ||
} | ||
|
||
} | ||
} |
This file was deleted.
Oops, something went wrong.
63 changes: 63 additions & 0 deletions
63
LimberTabbar/LimberTabbar/Extensions/CGMutablePath+pit.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// | ||
// CGMutablePath+pit.swift | ||
// LimberTabbar | ||
// | ||
// Created by Afshin Hoseini on 4/7/19. | ||
// Copyright © 2019 Afshin Hoseini. All rights reserved. | ||
// | ||
|
||
import Foundation | ||
import UIKit | ||
|
||
extension CGMutablePath { | ||
|
||
class func calculatePitWith(maxPitDepth: CGFloat) -> CGFloat { | ||
|
||
return maxPitDepth * 2.25 | ||
} | ||
|
||
/** | ||
Draws the pit's path from given starting point. | ||
In order to simplify the code, the scale parameter has been used once for the middle rect's height calculation. The other discussed parameters have bound to middle rect's height. | ||
**Returns** a tuple including guide rects and the end point. | ||
*/ | ||
@discardableResult | ||
public func addPit(toPath path: CGMutablePath, startingPointX : CGFloat, y: CGFloat, depth: CGFloat = 40, scale: CGFloat = 1) -> (guideRects: [CGRect], endPoint : CGPoint) { | ||
|
||
let pitWidth = CGMutablePath.calculatePitWith(maxPitDepth: depth) // Including the pit's domains | ||
let endPoint = CGPoint(x: startingPointX + pitWidth, y: y) | ||
|
||
let centerRectWidth = depth | ||
let centerRectHeight = depth * scale | ||
let smallRectsWidth = centerRectWidth / 2 | ||
let smallRectsHeight = centerRectHeight / 2 | ||
let pitCenterBottomPoint = CGPoint(x: startingPointX + (pitWidth / 2), y: centerRectHeight) | ||
|
||
|
||
let leftRect = CGRect(x: startingPointX, y: y, width: smallRectsWidth, height: smallRectsHeight) | ||
let centerRect = CGRect(x: leftRect.origin.x + leftRect.width, y: y, width: centerRectWidth, height: centerRectHeight) | ||
let rightRect = CGRect(x: centerRect.origin.x + centerRect.width, y: y, width: smallRectsWidth, height: smallRectsHeight) | ||
|
||
|
||
//Curves' control points calculations. | ||
//Right Curve's Top Control Point | ||
let RCTCP = CGPoint(x: endPoint.x - (abs(rightRect.height) * 1.25), y: y) | ||
//Right Curve's Bottom Control Point | ||
let RCBCP = CGPoint(x: pitCenterBottomPoint.x + abs(centerRectHeight), y: centerRectHeight) | ||
//Left Curve's Top Control Point | ||
let LCTCP = CGPoint(x: startingPointX + (abs(leftRect.height) * 1.25), y: y) | ||
//Left Curve's Bottom Control Point | ||
let LCBCP = CGPoint(x: pitCenterBottomPoint.x - abs(centerRectHeight), y: centerRectHeight) | ||
|
||
|
||
|
||
//Addes curves to the given path. | ||
|
||
path.addCurve(to: pitCenterBottomPoint, control1: LCTCP, control2: LCBCP) | ||
path.addCurve(to: endPoint, control1: RCBCP, control2: RCTCP) | ||
|
||
return([leftRect, centerRect, rightRect], endPoint) | ||
} | ||
} |
Oops, something went wrong.