Swiftpack.co - Package - fummicc1/SimpleRoulette

Images

Pod Platform Pod License Pod Version Carthage Compatible Swift Package Manager compatible


SimpleRoulette

SimpleRoulette helps you to create customizable Roulette, both UIView and View.


Demo

Dark Mode Light Mode SwiftUI

Install

Swift Package Manager

Create Package.swift and add dependency like the following.

dependencies: [
    .package(url: "https://github.com/fummicc1/SimpleRoulette.git", from: "0.2.0")
]

Cocoapods

Create Podfile and add dependency like the following.

pod 'SimpleRoulette', '~> 0.2'

Carthage

Create Cartfile and add dependency like the following.

github "fummicc1/SimpleRoulette"

Usage

UIKit

Initialize RouletteView

Without Storyboard/Xib

You can use RouletteView without UIStoryboard.

let rouletteView: RouletteView = .init(frame: .zero)
With Storyboard/Xib

You can also use RouletteView with UIStoryboard or Xib, though it can not visualize until run the code on the device.

@IBOutlet weak var rouletteView: RouletteView!

Insert parts with RouletteView#configure

You can choose parts from Roulette.AnglePart or Roulette.HugePart.

// Using AnglePart
rouletteView.configure(parts: [
    Roulette.AnglePart(name: "Title A", startAngle: .init(degree: 0), endAngle: .init(degree: 90), index: 0),
    Roulette.AnglePart(name: "Title B", startAngle: .init(degree: 90), endAngle: .init(degree: 200), index: 1),
    Roulette.AnglePart(name: "Title C", startAngle: .init(degree: 200), endAngle: .init(degree: 360), index: 2)
])

// Using HugePart
rouletteView.configure(parts: [
    Roulette.HugePart(name: "Title A", huge: .small, delegate: rouletteView, index: 0),
    Roulette.HugePart(name: "Title B", huge: .large, delegate: rouletteView, index: 1),
    Roulette.HugePart(name: "Title C", huge: .normal, delegate: rouletteView, index: 2),
])

Start Roulette by RouletteView#start

You can start Roulette by start(duration: clockwise: animated:) method.

Implementation is here.

rouletteView.start(duration: 2)
Parameters
Arguments Description Default Value
duration Duration 2
clockwise Boolen value that is used when UIBezierPath#addArc true
animated Boolen value that should be animated true

Stop Roulette by RouletteView#stop

You can stop Roulette by stop method.

Implementation is here.

As RouletteView does not automatically stop, you have to call RouletteView#stop if you want !

rouletteView.start()
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
    // RouletteView is animating for 3 seconds.
    self.rouletteView.stop()
}

Implement RouletteViewDelegate

RouletteViewDelegate informs you when Roulette has been stopped.

So you should set self, or something, as RouletteViewDelegate and add func rouletteView(_: didStopAt:) implementation.

rouletteView.delegate = self

extension HogeViewController: RouletteViewDelegate {
    func rouletteView(_ rouletteView: RouletteView, didStopAt part: RoulettePartType) {
        let alert = UIAlertController(title: "結果", message: part.name, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "閉じる", style: .default, handler: nil))
        present(alert, animated: true, completion: nil)
    }
}

SwiftUI

Documentation is not ready. I am looking forward to getting PullRequest :)

Mainly, you use and.

RouletteViewSwiftUI

RouletteViewSwiftUI confirms to View, so you can use it like the follwing.

struct ContentView: View {
    var body: some View {
        VStack {
            RouletteViewSwiftUI(viewModel: RouletteViewModel(duration: 5))
        }
    }
}

As for RouletteViewModel, please check RouletteViewModel

RouletteViewModel

RouletteViewModel is ObservableObject to store the state of Roulette. In addition to it, RouletteViewModel has onDecide: PassthroughSubject<RoulettePartType, Never> to oberve when Roulette has stopped. About RoulettePartType, please check About RoulettePatyType

RouletteViewModel#init

To initialize ROuletteViewMdel, you can no more than two params, duration and onDecide. onDecide can be saved.

let viewModel = RouletteViewModel(duration: 5)

Actually, though initializing is easy, you should configure content of Roulette by RouletteViewModel#configureParts(_:).

viewModel.configureParts([
    Roulette.HugePart(name: "Title A", huge: .large, delegate: viewModel, index: 0, fillColor: UIColor.systemTeal),
    Roulette.HugePart(name: "Title B", huge: .small, delegate: viewModel, index: 1, fillColor: UIColor.systemBlue),
    Roulette.HugePart(name: "Title C", huge: .normal, delegate: viewModel, index: 2, fillColor: UIColor.systemRed),
]

Example [WIP]


About RoulettePartType

RoulettePartType is either Roulette.HugePart or Roulette.AnglePart.

Both PartType's initializer has name and index parameters in common.

About Roulette.AnglePart

This struct's initializer has start and end degrees in addition to common args.

rouletteView.configure(parts: [
    Roulette.AnglePart(name: "Title A", startAngle: .init(degree: 0), endAngle: .init(degree: 90), index: 0),
    Roulette.AnglePart(name: "Title B", startAngle: .init(degree: 90), endAngle: .init(degree: 200), index: 1),
    Roulette.AnglePart(name: "Title C", startAngle: .init(degree: 200), endAngle: .init(degree: 360), index: 2)
])

If you think configuring each degree is troublesome, it's time to use Roulette.HugePart.

About Roulette.HugePart

This struct's initializer has neither start nor end. Instead of them, it has huge and delegate parameters which makes you to configure percentage of each RoulettePart intuitively。

you set RouletteView as delegate while using UIKit.

rouletteView.configure(parts: [
    Roulette.HugePart(name: "Title A", huge: .small, delegate: rouletteView, index: 0),
    Roulette.HugePart(name: "Title B", huge: .large, delegate: rouletteView, index: 1),
    Roulette.HugePart(name: "Title C", huge: .normal, delegate: rouletteView, index: 2),
])

IMPORTANT: can not combine Huge with Angle in RouletteView().configure.


Contributing

Pull requests, bug reports and feature requests are welcome 🚀


License

MIT LICENSE

Github

link
Stars: 7

Dependencies

Used By

Total: 0

Releases

Support SwiftUI -

RouletteViewSwiftUI and RouletteViewModel is ready. You can use RouletteView without UIKit :)

support UserInterfaceStyle change -

This version(v0.1.2) fixes a problem that cgColor does not change according to UIUserInterfaceStyle though its appearance is compatible with both light and dark mode style.

Prevent Crash -

add "break" to RouletteView#stop to prevent app from being crash when configure parts as soon as RouletteView stops.

update minor version -

Use UIView instead of CALayer. Fix some layout bugs. -

fix RouletteView Layout. -

  • Use UIStackView to layout RouletteView.
  • Setup layout inside UIView::layoutSubviews.
  • Delete unnecessary code.
  • Fix animation bug.

-

Test Package.swift