Skip to content

Commit

Permalink
Merge pull request #17 from chenhaiteng/feature/text-on-archimedean-s…
Browse files Browse the repository at this point in the history
…piral

Feature/text on archimedean spiral
  • Loading branch information
chenhaiteng authored May 13, 2021
2 parents 51f7bde + c6045d2 commit b79d86e
Show file tree
Hide file tree
Showing 11 changed files with 572 additions and 79 deletions.
9 changes: 7 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ let package = Package(
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
.package(name: "CoreGraphicsExtension", url: "https://github.com/chenhaiteng/CoreGraphicsExtension.git", from: "0.2.0")
.package(name: "CoreGraphicsExtension", url: "https://github.com/chenhaiteng/CoreGraphicsExtension.git", from: "0.2.0"),
.package(name: "ArchimedeanSpiral", url: "https://github.com/chenhaiteng/ArchimedeanSpiral.git", from: "1.0.12")
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
Expand All @@ -27,7 +28,11 @@ let package = Package(
dependencies: []),
.target(
name: "Rings",
dependencies: ["CoreGraphicsExtension", "CommonExts"]),
dependencies: ["CoreGraphicsExtension", "CommonExts", "ArchimedeanSpiral"],
exclude: ["RingText.md",
"ClockIndex.md",
"ArchimedeanSpiralText.md",
"HandAiguille.md"]),
.testTarget(
name: "RingsTests",
dependencies: ["Rings",
Expand Down
128 changes: 62 additions & 66 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,86 +1,82 @@
# Rings
# Rings ![GitHub](https://img.shields.io/github/license/chenhaiteng/Rings?style=plastic) ![GitHub release (latest by date)](https://img.shields.io/github/v/release/chenhaiteng/rings)

**Rings** is a collection of controls which have similar shapes of ring, circle...

It includes following controls:
* RingText
* ClockIndex
* HandAiguille
* ArchimedeanSpiralText (In-progress)
* SphericText (In-progress)
* Knob (In-planning)
It includes following controls, click to see what it looks like:

## RingText
* **[RingText](#ringtext)**
* **[ClockIndex](#clockindex)**
* **[HandAiguille](#handaiguille)**
* **[ArchimedeanSpiralText](#archimedeanspiraltext)**

### Preview
![RingDemo](https://user-images.githubusercontent.com/1284944/115984682-fb26a700-a5da-11eb-8a59-a1554ec41bdf.gif)
and following functions are in progress:
* SphericText
* Knob

---
## Installation:
### Install with Swift Package Manager
#### - Add to Xcode:

1. File > Swift Packages > Add Package Dependency...
2. Choose Project you want to add Rings
3. Paste repository https://github.com/chenhaiteng/Rings.git
4. Rules > Version: Up to Next Major 0.1.0
It's can also apply Rules > Branch : main to access latest code.
If you want try some experimental features, you can also apply Rules > Branch : develop

### Usage:
**Note:** It might need to link Rings to your target maunally.

1. Open *Project Editor* by tap on root of project navigator
2. Choose the target you want to use Rings.
3. Choose **Build Phases**, and expand **Link Binary With Libraries**
4. Tap on **+** button, and choose Rings to add it.

#### - Add to SPM package:
```swift
// To layout the text "1234567890" along a circle with radius 40.
RingText(radius: 40.0, text: "1234567890")

// To layout a list to words along a circle with radius 40.
RingText(radius: 40.0, words: ["1","2","3","4","5","6"])

// To create and setup RingText with rich features:
RingText(radius: 40.0, text: "1234567890")
.font(Font.custom("Apple Chancery", size: 16.0)) // Setup font and size
.begin(degrees: -90.0) // Modify the begining degrees
.end(degress: 90.0) // Modify the end degrees.
.textColor(.red) // Change the color of text, default is white.

// Show blueprint of each text (For debug purpose)
RingText(radius: 40.0, text: "1234567890").showBlueprint(true)
dependencies: [
.package(name: "Rings", url: "https://github.com/chenhaiteng/Rings.git", from: "0.1.0")
// To specify branch, use following statement to instead of.
// .package(name: "Rings", url: "https://github.com/chenhaiteng/Rings.git", .branch("branch_name"))
],
targets: [
.target(
name: "MyPackage",
dependencies: ["Rings"]),
]
```
---

## RingText

### What it looks like
![RingDemo](https://user-images.githubusercontent.com/1284944/115984682-fb26a700-a5da-11eb-8a59-a1554ec41bdf.gif)

### ![How to use it](Sources/Rings/RingText.md)

## ClockIndex

### Preview
### What it looks like
![ClockIndex Demo Classic](https://user-images.githubusercontent.com/1284944/116664495-26d6d200-a9cb-11eb-906c-7ffe659dcfbc.gif)

<img width="598" alt="earchly_clock_demo" src="https://user-images.githubusercontent.com/1284944/116664737-73baa880-a9cb-11eb-97e1-afcb49dfcfcd.png">

### Usage:

```Swift
// Default clock index with radius 50.0
ClockIndex().radius(50.0)

// Modify hour index style with radius.
ClockIndex().hourIndexStyle(StrokeStyle(lineWidth: 5.0).hourStyle(with: indexRadius))

// Custom hour marker text
ClockIndex(textMarkers: ["I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII"])

// Show/Hide hour index and minutes track
ClockIndex().showIndex(shouldShowIndex)
```
### ![How to use it](Sources/Rings/ClockIndex.md)

## HandAiguille

### Preview
https://user-images.githubusercontent.com/1284944/117106480-83aeff80-adb2-11eb-8e82-d77d9569dcca.mov

### Usage:
```Swift
// Create empty hand aiguille with default size, and set the hand aiguille background red
HandAiguille() {
}.handBackground(Color.red)

// Create empty hand aiguille with time provider, and specify its time unit.
@State var hourProvider: Double = 0.0
HandAiguille(time: $hourProvider, unit: .hour) {
}.handBackgroudn(Color.red)

// Create hand aiguille with Image
@State var secsProvider: Double = 0.0
HandAiguille(time: $secsProvider) {
Image("SpadeHand")
}

// Create apple watch style hand
HandFactory.standard.makeAppleWatchStyleHand(time: $secsProvider)
```
### What it looks like:
![HandAguille](https://user-images.githubusercontent.com/1284944/118101511-47128200-b40a-11eb-870f-90ac2f2a302a.gif)

### ![How to use it](Sources/Rings/HandAiguille.md)

## ArchimedeanSpiralText

### What it looks like:
![ArchimedeanSpiralTextDemo](https://user-images.githubusercontent.com/1284944/117950922-3ef10e80-b346-11eb-9da1-50b0f87990a2.gif)

### ![How to use it](Sources/Rings/ArchimedeanSpiralText.md)

---
# License
Rings is released under the [MIT License](LICENSE).
120 changes: 120 additions & 0 deletions Sources/Rings/ArchimedeanSpiralPath.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
//
// ArchimedeanSpiralPath.swift
// Rings
//
// Created by Chen Hai Teng on 3/5/21.
//

import SwiftUI
import ArchimedeanSpiral
import CoreGraphicsExtension

public struct ArchimedeanSpiralPath: View {
var radiusSpacing: Double
var innerRadius: Double
var gap: Double
var ptCount: Int
var spiralDesc :ArchimedeanSpiral
var startAngle: CGAngle = CGAngle.zero

private lazy var points: [CGPoint] = spiralDesc.equidistantPoints(start: startAngle, num: ptCount).map { polar in
polar.cgpoint
}

init(_ innerRadius: Double = 12.0, spacing: Double = 10.0, gap: Double = 5.0, count: Int = 100) {
self.radiusSpacing = spacing
self.innerRadius = innerRadius
self.gap = gap
self.ptCount = count
spiralDesc = ArchimedeanSpiral(innerRadius: self.innerRadius, radiusSpacing: self.radiusSpacing, spacing: self.gap)

}

func getPoints()-> [CGPoint] {
var mutateSelf = self
return mutateSelf.points
}

public var body: some View {
GeometryReader { geo in
Path { path in
let midX = geo.size.width/2
let midY = geo.size.height/2
path.move(to: CGPoint(
x: midX,
y: midY
))
getPoints().forEach { pt in
let next = CGPoint(x: pt.x + midX, y: pt.y + midY)
path.addLine(to: next)
}
}.stroke(Color.red)
}
}
}

extension ArchimedeanSpiralPath : Adjustable {
func start(_ angle: CGAngle) -> Self {
setProperty { tmp in
tmp.startAngle = angle
}
}
}

struct ArchimedeanSpiralPathDemo : View {
@State var radiusSpacing: Double = 10.0
@State var innerR: Double = 5.0
@State var spacing: Double = 25.0
@State var count: Double = 100.0
@State var startAt: Double = 0.0
@State var showInner: Bool = false
@State var showRadius: Bool = false
var body: some View {
VStack {
ZStack {
GeometryReader { geo in
let midX = geo.size.width/2
let midY = geo.size.height/2
ArchimedeanSpiralPath(innerR, spacing: radiusSpacing, gap: spacing, count: Int(count)).start(CGAngle.degrees(startAt))
Group {
if (showInner) {
Path { p in
p.move(to: CGPoint(x: midX, y: midY))
p.addLine(to: CGPoint(x: midX + CGFloat(innerR), y: midY))
}.stroke(style: StrokeStyle(lineWidth: 2.0, lineCap: .butt, lineJoin: .miter, miterLimit: 0, dash: [3,1], dashPhase: 0))
}
if(showRadius) {
Path { p in
p.move(to: CGPoint(x: midX + CGFloat(innerR), y: midY))
p.addLine(to: CGPoint(x: midX + CGFloat(innerR) + CGFloat(radiusSpacing), y: midY))
}.stroke(Color.blue, style: StrokeStyle(lineWidth: 2.0, lineCap: .butt, lineJoin: .miter, miterLimit: 0, dash: [3,1], dashPhase: 0))
}
}
}
}
Slider(value: $startAt, in: 0.0...360.0) {
Text("start at (\(startAt))")
}.padding(EdgeInsets(top: 0, leading: 10, bottom: 0, trailing: 10))
Slider(value: $radiusSpacing, in: 10.0...50.0) {
Toggle("", isOn: $showRadius)
Text("radius spacing (\(radiusSpacing))")
}.padding(EdgeInsets(top: 0, leading: 10, bottom: 0, trailing: 10))
Slider(value: $innerR, in: 10.0...50.0) {
Toggle("", isOn: $showInner)
Text("inner radius(\(innerR))")
}.padding(EdgeInsets(top: 0, leading: 10, bottom: 0, trailing: 10))
Slider(value: $spacing, in: 10.0...50.0) {
Text("points spacing(\(spacing))")
}.padding(EdgeInsets(top: 0, leading: 10, bottom: 0, trailing: 10))
Slider(value: $count, in: 100.0...200.0, step: 10.0) {
Text("count(\(Int(count)))")
}.padding(EdgeInsets(top: 0, leading: 10, bottom: 0, trailing: 10))
}
}
}

struct SwiftUIView_Previews: PreviewProvider {
static var previews: some View {
ArchimedeanSpiralPathDemo()
}
}
24 changes: 24 additions & 0 deletions Sources/Rings/ArchimedeanSpiralText.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# ArchimedeanSpiralText

## Preview:

![ArchimedeanSpiralTextDemo](https://user-images.githubusercontent.com/1284944/117950922-3ef10e80-b346-11eb-9da1-50b0f87990a2.gif)

### Usage:
```swift
// Create text along archimedean spiral
ArchimedeanSpiralText("My Archimedean Spiral")

// Setup Archimedean Spiral parameters
ArchimedeanSpiralText("My Archimedean Spiral")
.gap(10.0) // To setup the distance between two calculated points.
.innerRadius(15.0) // To specify the start radius of an archimedean spiral
.spacing(radiusSpacing) // To adjust the constant separation distance between intersection points measured from the origin.

// Update the text appearance
ArchimedeanSpiralText()
.text("My Archimedean Spiral") // Modifing text content
.textDirection(direction) // Specifing the direction of text.
.textColor(color) // Change text color
.font(font) // Change font and text size
```
Loading

0 comments on commit b79d86e

Please sign in to comment.