Skip to content

Commit

Permalink
Render Icon to image and use them
Browse files Browse the repository at this point in the history
  • Loading branch information
lkeude96 committed Oct 19, 2019
1 parent 5ef0179 commit 3cd633c
Show file tree
Hide file tree
Showing 5 changed files with 186 additions and 35 deletions.
179 changes: 179 additions & 0 deletions CardParts/Assets/AssetManager.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
//
// AssetManager.swift
// CardParts
//
// Created by Eude K Lesperance on 10/18/19.
//

import UIKit

class AssetManager {
static var shared = AssetManager()

private var assets: [Icon: UIImage] = [:]

init() {
Icon.allCases.forEach { icon in
assets[icon] = render(icon)
}
}

func image(for icon: Icon) -> UIImage? {
return assets[icon]
}

private func render(_ icon: Icon, in rect: CGRect = CGRect(x: 0, y: 0, width: 24.0, height: 24.0)) -> UIImage {
let format = UIGraphicsImageRendererFormat.default()
let renderer = UIGraphicsImageRenderer(size: rect.size, format: format)

let image = renderer.image { ctx in
ctx.cgContext.scaleBy(x: rect.width / 24.0, y: rect.height / 24.0)
let path = icon.bezierPath()
if icon == .confetti {
UIColor.white.setStroke()
path.stroke()
} else {
UIColor.white.setFill()
path.fill()
}
}

return image.withRenderingMode(.alwaysTemplate)
}
}

extension AssetManager {
enum Icon: CaseIterable {
case arrowDown, star, diamond, triangle, pencil, confetti

func bezierPath() -> UIBezierPath {
switch self {
case .arrowDown: return arrowDown()
case .star: return star()
case .diamond: return diamond()
case .triangle: return triangle()
case .pencil: return pencil()
case .confetti: return confetti()
}
}

private func arrowDown() -> UIBezierPath {
let path = UIBezierPath()
path.move(to: CGPoint(x: 7.41, y: 8.59))
path.addLine(to: CGPoint(x: 12, y: 13.17))
path.addLine(to: CGPoint(x: 16.59, y: 8.59))
path.addLine(to: CGPoint(x: 18, y: 10))
path.addLine(to: CGPoint(x: 12, y: 16))
path.addLine(to: CGPoint(x: 6, y: 10))
path.addLine(to: CGPoint(x: 7.41, y: 8.59))
path.close()
return path
}

private func star() -> UIBezierPath {
let size = CGSize(width: 24.0, height: 24.0)
let sides = 5
let radius: CGFloat = min(size.width, size.height) / 2.0
let origin = CGPoint(x: size.width / 2.0 , y: size.height / 2.0)
let pointiness: CGFloat = 2.0
let startAngle = CGFloat(-1 * (360 / sides / 4))
let adjustment = startAngle + CGFloat(360 / sides / 2)

let points = polygonPoints(sides: sides, radius: radius / pointiness, origin: origin, adjustment: startAngle)
let points2 = polygonPoints(sides: sides, radius: radius, origin: origin, adjustment: adjustment)

let path = UIBezierPath()
path.move(to: points[0])
points.enumerated().forEach { i, point in
path.addLine(to: points2[i])
path.addLine(to: point)
}
path.close()
return path
}

private func confetti() -> UIBezierPath {
let linewidth: CGFloat = 4.0
let size = CGSize(width: 24.0, height: 24.0)
let radius: CGFloat = (min(size.width, size.height) - linewidth) / 2.0
let origin = CGPoint(x: size.width / 2.0 , y: size.height / 2.0)
let path = UIBezierPath(arcCenter: origin, radius: radius, startAngle: radian(from: 270), endAngle: radian(from: 180), clockwise: false)
path.lineWidth = linewidth
return path
}

private func triangle() -> UIBezierPath {
let size = CGSize(width: 24.0, height: 24.0)
let sides = 3
let radius: CGFloat = min(size.width, size.height) / 2.0
let origin = CGPoint(x: size.width / 2.0 , y: size.height / 2.0)
let startAngle = CGFloat(-1 * (360 / sides / 4))
let adjustment = startAngle + CGFloat(360 / sides / 2)

let points = polygonPoints(sides: sides, radius: radius, origin: origin, adjustment: adjustment)

let path = UIBezierPath()
path.move(to: points[0])
points.enumerated().forEach { _, point in
print(point)
path.addLine(to: point)
}
return path
}

private func diamond() -> UIBezierPath {
let path = UIBezierPath()
path.move(to: CGPoint(x: 11.96, y: 3.15))
path.addLine(to: CGPoint(x: 11.85, y: 3))
path.addLine(to: CGPoint(x: 5.24, y: 12.19))
path.addLine(to: CGPoint(x: 5.17, y: 12.29))
path.addLine(to: CGPoint(x: 12.24, y: 21.07))
path.addLine(to: CGPoint(x: 12.27, y: 21.11))
path.addLine(to: CGPoint(x: 18.88, y: 11.81))
path.addLine(to: CGPoint(x: 18.95, y: 11.71))
path.addLine(to: CGPoint(x: 11.96, y: 3.15))
path.close()
return path
}

private func pencil() -> UIBezierPath {
let path = UIBezierPath()
path.move(to: CGPoint(x: 3, y: 17.25))
path.addLine(to: CGPoint(x: 3, y: 21))
path.addLine(to: CGPoint(x: 6.75, y: 21))
path.addLine(to: CGPoint(x: 17.81, y: 9.94))
path.addLine(to: CGPoint(x: 14.06, y: 6.19))
path.addLine(to: CGPoint(x: 3, y: 17.25))
path.close()
path.move(to: CGPoint(x: 20.71, y: 7.04))
path.addCurve(to: CGPoint(x: 20.71, y: 5.63),
controlPoint1: CGPoint(x: 21.1, y: 6.65),
controlPoint2: CGPoint(x: 21.1, y: 6.02))
path.addLine(to: CGPoint(x: 18.37, y: 3.29))
path.addCurve(to: CGPoint(x: 16.96, y: 3.29),
controlPoint1: CGPoint(x: 17.98, y: 2.9),
controlPoint2: CGPoint(x: 17.35, y: 2.9))
path.addLine(to: CGPoint(x: 15.13, y: 5.12))
path.addLine(to: CGPoint(x: 18.88, y: 8.87))
path.addLine(to: CGPoint(x: 20.71, y: 7.04))
path.close()
return path
}

private func radian(from degree: CGFloat) -> CGFloat {
return CGFloat(Double.pi) * degree / 180.0
}

private func polygonPoints(sides: Int, radius: CGFloat, origin: CGPoint, adjustment: CGFloat = 0.0) -> [CGPoint] {
let angle = radian(from: 360 / CGFloat(sides))
let points: [CGPoint] = (0...sides).reversed()
.map { side in
return CGPoint (
x: origin.x - radius * cos(angle * CGFloat(side) + radian(from: adjustment)),
y: origin.y - radius * sin(angle * CGFloat(side) + radian(from: adjustment))
)
}
return points
}
}
}
8 changes: 4 additions & 4 deletions CardParts/src/Classes/Card Parts/CardPartConfettiView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public class CardPartConfettiView: UIView, CardPartView {
}
}

public var confettiImages = [UIImage(named: "confetti", in: Bundle(for: CardPartConfettiView.self),compatibleWith: nil)] as? [UIImage]
public var confettiImages = [AssetManager.shared.image(for: .confetti)] as? [UIImage]

//A layer that emits, animates, and renders a particle system.
var emitter: CAEmitterLayer = CAEmitterLayer()
Expand Down Expand Up @@ -127,15 +127,15 @@ public class CardPartConfettiView: UIView, CardPartView {
private func image(for type: ConfettiType, index: Int = 0) -> UIImage? {
switch type {
case .diamond:
return UIImage(named: "diamond", in: Bundle(for: CardPartConfettiView.self), compatibleWith: nil)
return AssetManager.shared.image(for: .diamond)
case .star:
return UIImage(named: "star", in: Bundle(for: CardPartConfettiView.self), compatibleWith: nil)
return AssetManager.shared.image(for: .star)
case let .image(customImage):
return customImage
case .mixed:
return confettiImages?[index]
case .confetti:
return UIImage(named: "confetti", in: Bundle(for: CardPartConfettiView.self), compatibleWith: nil)
return AssetManager.shared.image(for: .confetti)
}
}
}
17 changes: 2 additions & 15 deletions CardParts/src/Classes/Card Parts/CardPartTitleView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,6 @@ public class CardPartTitleView : UIView, CardPartView {
}
}
}
public var menuButtonImageName: String = "arrowdown" {
didSet {
if type == .titleWithMenu || type == .titleWithActionableButton {
menuButtonImage = UIImage(named: menuButtonImageName, in: Bundle(for: CardPartTitleView.self), compatibleWith: nil)
}
}
}
public var menuOptionObserver: ((String, Int) -> Void)?
public var menuActionableCallback: (()->())?

Expand Down Expand Up @@ -80,7 +73,7 @@ public class CardPartTitleView : UIView, CardPartView {
if let image = menuButtonImage {
button.setImage(image, for: .normal)
} else {
button.setImage(UIImage(named: menuButtonImageName, in: Bundle(for: CardPartTitleView.self), compatibleWith: nil), for: .normal)
button.setImage(AssetManager.shared.image(for: .arrowDown), for: .normal)
}
button.addTarget(self, action: #selector(menuButtonTapped), for: UIControl.Event.touchUpInside)
addSubview(button)
Expand All @@ -92,7 +85,7 @@ public class CardPartTitleView : UIView, CardPartView {
if let image = menuButtonImage {
button.setImage(image, for: .normal)
} else {
button.setImage(UIImage(named: menuButtonImageName, in: Bundle(for: CardPartTitleView.self), compatibleWith: nil), for: .normal)
button.setImage(AssetManager.shared.image(for: .arrowDown), for: .normal)
}
button.addTarget(self, action: #selector(actionableMenuTapped), for: UIControl.Event.touchUpInside)
addSubview(button)
Expand Down Expand Up @@ -190,12 +183,6 @@ extension Reactive where Base: CardPartTitleView {
titleView.menuOptions = menuOptions
}
}

public var menuButtonImageName: Binder<String>{
return Binder(self.base) { (titleView, menuButtonImageName) -> () in
titleView.menuButtonImageName = menuButtonImageName
}
}

public var menuButtonImage: Binder<UIImage?>{
return Binder(self.base) { (titleView, menuButtonImage) -> () in
Expand Down
3 changes: 1 addition & 2 deletions CardParts/src/Classes/CardsViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ open class CardsViewController : UIViewController, UICollectionViewDataSource, U
let editButtonOffset : CGFloat = 24
let editButtonHeight : CGFloat = 50
let editButtonWidth : CGFloat = 50
let editButtonImage = "budgets_disclosure_icon"

var cardControllers = [CardInfo]()
var bag = DisposeBag()
Expand Down Expand Up @@ -230,7 +229,7 @@ open class CardsViewController : UIViewController, UICollectionViewDataSource, U
}.disposed(by: bag)
if getEditModeForIndexPath(indexPath: indexPath) {
let editButton = UIButton(frame: CGRect(x: view.bounds.size.width - editButtonOffset - editButtonWidth, y: 0, width: editButtonWidth, height: editButtonHeight))
editButton.setImage(UIImage(named: editButtonImage, in: Bundle(for: CardsViewController.self), compatibleWith: nil), for: .normal)
editButton.setImage(AssetManager.shared.image(for: .pencil), for: .normal)
editButton.addTargetClosure { _ in
if let editibalCardTrait = cardController as? EditableCardTrait {
editibalCardTrait.onEditButtonTap()
Expand Down
14 changes: 0 additions & 14 deletions Example/Tests/CardPartTitleViewTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -112,18 +112,4 @@ class CardPartTitleViewTests: XCTestCase {
XCTAssertEqual(titlePart.menuOptions!, ["111", "222"])
}

func testMenuButtonImageNameProperty() {

let bag = DisposeBag()

let titlePart = CardPartTitleView(type: .titleOnly)

let buttonImageProperty = BehaviorRelay(value: "hello")
buttonImageProperty.asObservable().bind(to: titlePart.rx.menuButtonImageName).disposed(by: bag)
XCTAssertEqual(titlePart.menuButtonImageName, "hello")

buttonImageProperty.accept("New Value")
XCTAssertEqual(titlePart.menuButtonImageName, "New Value")
}

}

0 comments on commit 3cd633c

Please sign in to comment.