Merge pull request #2 from simibac/develop

multi platform support
This commit is contained in:
Simon Bachmann 2020-12-04 20:56:14 +01:00 committed by GitHub
commit bedae06152
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 148 additions and 37 deletions

View File

@ -6,7 +6,10 @@ import PackageDescription
let package = Package( let package = Package(
name: "ConfettiSwiftUI", name: "ConfettiSwiftUI",
platforms: [ platforms: [
.iOS(.v14) .iOS(.v14),
.macOS(.v11),
.tvOS(.v14),
.watchOS(.v7)
], ],
products: [ products: [
// Products define the executables and libraries a package produces, and make them visible to other packages. // Products define the executables and libraries a package produces, and make them visible to other packages.

View File

@ -102,7 +102,7 @@ ConfettiCannon(counter: $counter4, num: 50, openingAngle: Angle(degrees: 0), clo
Code: Code:
```swift ```swift
ConfettiCannon(counter: $counter5, emojis: ["❤️", "💙", "💚", "🧡"]) ConfettiCannon(counter: $counter5, confettis: [.text("❤️"), .text("💙"), .text("💚"), .text("🧡")])
``` ```
#### Endless Configuration #### Endless Configuration
@ -114,7 +114,7 @@ ConfettiCannon(counter: $counter5, emojis: ["❤️", "💙", "💚", "🧡"])
Code: Code:
```swift ```swift
ConfettiCannon(counter: $counter6, num:1, emojis: ["💩"], confettiSize: 20, repetitions: 100, repetitionInterval: 0.1) ConfettiCannon(counter: $counter6, num:1, confettis: [.text("💩")], confettiSize: 20, repetitions: 100, repetitionInterval: 0.1)
``` ```
#### Make-it-Rain Configuration #### Make-it-Rain Configuration
@ -126,7 +126,7 @@ ConfettiCannon(counter: $counter6, num:1, emojis: ["💩"], confettiSize: 20, re
Code: Code:
```swift ```swift
ConfettiCannon(counter: $counter7, num:1, emojis: ["💵", "💶", "💷", "💴"], confettiSize: 30, repetitions: 50, repetitionInterval: 0.1) ConfettiCannon(counter: $counter7, num:1, confettis: [.text("💵"), .text("💶"), .text("💷"), .text("💴")], confettiSize: 30, repetitions: 50, repetitionInterval: 0.1)
``` ```
### Parameters ### Parameters
@ -135,8 +135,7 @@ ConfettiCannon(counter: $counter7, num:1, emojis: ["💵", "💶", "💷", "💴
| -------------------- | ------------ | ----------------------------------------------------- | ------------------------------------------------------- | | -------------------- | ------------ | ----------------------------------------------------- | ------------------------------------------------------- |
| counter | Binding<Int> | on any change of this variable triggers the animation | 0 | | counter | Binding<Int> | on any change of this variable triggers the animation | 0 |
| num | Int | amount of confettis | 20 | | num | Int | amount of confettis | 20 |
| emojis | [String] | list of emojis as strings | [String]() | | confettis | [ConfettiType] | list of shapes and text | [.shape(.circle), .shape(.triangle), .shape(.square), .shape(.slimRectangle), .shape(.roundedCross)] |
| includeDefaultShapes | Bool | include default confetti shapes such as circle | true |
| colors | [Color] | list of colors applied to the default shapes | [.blue, .red, .green, .yellow, .pink, .purple, .orange] | | colors | [Color] | list of colors applied to the default shapes | [.blue, .red, .green, .yellow, .pink, .purple, .orange] |
| confettiSize | CGFloat | size that confettis and emojis are scaled to | 10.0 | | confettiSize | CGFloat | size that confettis and emojis are scaled to | 10.0 |
| rainHeight | CGFloat | vertical distance that confettis pass | 600.0 | | rainHeight | CGFloat | vertical distance that confettis pass | 600.0 |

View File

@ -7,7 +7,42 @@
import SwiftUI import SwiftUI
@available(iOS 14.0, *) public enum ConfettiType:CaseIterable, Hashable {
public enum Shape {
case circle
case triangle
case square
case slimRectangle
case roundedCross
}
case shape(Shape)
case text(String)
public var view:AnyView{
switch self {
case .shape(.square):
return AnyView(Rectangle())
case .shape(.triangle):
return AnyView(Triangle())
case .shape(.slimRectangle):
return AnyView(SlimRectangle())
case .shape(.roundedCross):
return AnyView(RoundedCross())
case let .text(text):
return AnyView(Text(text))
default:
return AnyView(Circle())
}
}
public static var allCases: [ConfettiType] {
return [.shape(.circle), .shape(.triangle), .shape(.square), .shape(.slimRectangle), .shape(.roundedCross)]
}
}
@available(iOS 14.0, macOS 11.0, watchOS 7, tvOS 14.0, *)
public struct ConfettiCannon: View { public struct ConfettiCannon: View {
@Binding var counter:Int @Binding var counter:Int
@StateObject private var confettiConfig:ConfettiConfig @StateObject private var confettiConfig:ConfettiConfig
@ -21,8 +56,6 @@ public struct ConfettiCannon: View {
/// - Parameters: /// - Parameters:
/// - counter: on any change of this variable the animation is run /// - counter: on any change of this variable the animation is run
/// - num: amount of confettis /// - num: amount of confettis
/// - emojis: list of emojis
/// - includeDefaultShapes: include default confetti shapes such as circle and square
/// - colors: list of colors that is applied to the default shapes /// - colors: list of colors that is applied to the default shapes
/// - confettiSize: size that confettis and emojis are scaled to /// - confettiSize: size that confettis and emojis are scaled to
/// - rainHeight: vertical distance that confettis pass /// - rainHeight: vertical distance that confettis pass
@ -35,8 +68,7 @@ public struct ConfettiCannon: View {
/// - repetitionInterval: duration between the repetitions /// - repetitionInterval: duration between the repetitions
public init(counter:Binding<Int>, public init(counter:Binding<Int>,
num:Int = 20, num:Int = 20,
emojis:[String] = [String](), confettis:[ConfettiType] = ConfettiType.allCases,
includeDefaultShapes:Bool = false,
colors:[Color] = [.blue, .red, .green, .yellow, .pink, .purple, .orange], colors:[Color] = [.blue, .red, .green, .yellow, .pink, .purple, .orange],
confettiSize:CGFloat = 10.0, confettiSize:CGFloat = 10.0,
rainHeight: CGFloat = 600.0, rainHeight: CGFloat = 600.0,
@ -50,17 +82,17 @@ public struct ConfettiCannon: View {
) { ) {
self._counter = counter self._counter = counter
var shapes = [AnyView]() var shapes = [AnyView]()
if(emojis.count > 0){
for emoji in emojis{
shapes.append(AnyView(Text("\(emoji)").font(.system(size: confettiSize))))
}
}
if includeDefaultShapes || emojis.count == 0{ for confetti in confettis{
shapes.append(AnyView(Rectangle().frame(width: confettiSize, height: confettiSize, alignment: .center))) for color in colors{
shapes.append(AnyView(Circle().frame(width: confettiSize, height: confettiSize, alignment: .center))) switch confetti {
case .shape(_):
shapes.append(AnyView(confetti.view.foregroundColor(color).frame(width: confettiSize, height: confettiSize, alignment: .center)))
default:
shapes.append(AnyView(confetti.view.foregroundColor(color).font(.system(size: confettiSize))))
}
}
} }
_confettiConfig = StateObject(wrappedValue: ConfettiConfig( _confettiConfig = StateObject(wrappedValue: ConfettiConfig(
@ -106,7 +138,7 @@ public struct ConfettiCannon: View {
} }
} }
@available(iOS 14.0, *) @available(iOS 14.0, macOS 11.0, watchOS 7, tvOS 14.0, *)
struct ConfettiContainer: View { struct ConfettiContainer: View {
@Binding var finishedAnimationCouter:Int @Binding var finishedAnimationCouter:Int
@StateObject var confettiConfig:ConfettiConfig @StateObject var confettiConfig:ConfettiConfig
@ -115,7 +147,7 @@ struct ConfettiContainer: View {
var body: some View{ var body: some View{
ZStack{ ZStack{
ForEach(0...confettiConfig.num-1, id:\.self){_ in ForEach(0...confettiConfig.num-1, id:\.self){_ in
Confetti(confettiConfig: confettiConfig) ConfettiView(confettiConfig: confettiConfig)
} }
} }
.onAppear(){ .onAppear(){
@ -129,13 +161,12 @@ struct ConfettiContainer: View {
} }
} }
@available(iOS 14.0, *) @available(iOS 14.0, macOS 11.0, watchOS 7, tvOS 14.0, *)
struct Confetti: View{ struct ConfettiView: View{
@State var location:CGPoint = CGPoint(x: 0, y: 0) @State var location:CGPoint = CGPoint(x: 0, y: 0)
@State var opacity:Double = 0.0 @State var opacity:Double = 0.0
@StateObject var confettiConfig:ConfettiConfig @StateObject var confettiConfig:ConfettiConfig
func getShape() -> AnyView { func getShape() -> AnyView {
return confettiConfig.shapes.randomElement()! return confettiConfig.shapes.randomElement()!
} }
@ -150,7 +181,7 @@ struct Confetti: View{
} }
var body: some View{ var body: some View{
ConfettiView(shape:getShape(), color:getColor(), spinDirX: getSpinDirection(), spinDirZ: getSpinDirection()) ConfettiAnimationView(shape:getShape(), color:getColor(), spinDirX: getSpinDirection(), spinDirZ: getSpinDirection())
.offset(x: location.x, y: location.y) .offset(x: location.x, y: location.y)
.opacity(opacity) .opacity(opacity)
.onAppear(){ .onAppear(){
@ -185,7 +216,7 @@ struct Confetti: View{
} }
struct ConfettiView: View { struct ConfettiAnimationView: View {
@State var shape: AnyView @State var shape: AnyView
@State var color: Color @State var color: Color
@State var spinDirX: CGFloat @State var spinDirX: CGFloat
@ -194,7 +225,6 @@ struct ConfettiView: View {
@State var move = false @State var move = false
// @State var xSpeed = Double.random(in: 0.7...3)
@State var xSpeed:Double = Double.random(in: 1...2) @State var xSpeed:Double = Double.random(in: 1...2)
@State var zSpeed = Double.random(in: 1...2) @State var zSpeed = Double.random(in: 1...2)
@ -216,15 +246,6 @@ struct ConfettiView: View {
} }
} }
struct Movement{
var x: CGFloat
var y: CGFloat
var z: CGFloat
var opacity: Double
}
class ConfettiConfig: ObservableObject { class ConfettiConfig: ObservableObject {
internal init(num: Int, shapes: [AnyView], colors: [Color], confettiSize: CGFloat, rainHeight: CGFloat, fadesOut: Bool, opacity: Double, openingAngle:Angle, closingAngle:Angle, radius:CGFloat, repetitions:Int, repetitionInterval:Double) { internal init(num: Int, shapes: [AnyView], colors: [Color], confettiSize: CGFloat, rainHeight: CGFloat, fadesOut: Bool, opacity: Double, openingAngle:Angle, closingAngle:Angle, radius:CGFloat, repetitions:Int, repetitionInterval:Double) {
self.num = num self.num = num

View File

@ -0,0 +1,34 @@
//
// RoundedCross.swift
// Confetti
//
// Created by Simon Bachmann on 04.12.20.
//
import SwiftUI
public struct RoundedCross: Shape {
public func path(in rect: CGRect) -> Path {
var path = Path()
path.move(to: CGPoint(x: rect.minX, y: rect.maxY/3))
path.addQuadCurve(to: CGPoint(x: rect.maxX/3, y: rect.minY), control: CGPoint(x: rect.maxX/3, y: rect.maxY/3))
path.addLine(to: CGPoint(x: 2*rect.maxX/3, y: rect.minY))
path.addQuadCurve(to: CGPoint(x: rect.maxX, y: rect.maxY/3), control: CGPoint(x: 2*rect.maxX/3, y: rect.maxY/3))
path.addLine(to: CGPoint(x: rect.maxX, y: 2*rect.maxY/3))
path.addQuadCurve(to: CGPoint(x: 2*rect.maxX/3, y: rect.maxY), control: CGPoint(x: 2*rect.maxX/3, y: 2*rect.maxY/3))
path.addLine(to: CGPoint(x: rect.maxX/3, y: rect.maxY))
path.addQuadCurve(to: CGPoint(x: 2*rect.minX/3, y: 2*rect.maxY/3), control: CGPoint(x: rect.maxX/3, y: 2*rect.maxY/3))
return path
}
}
struct RoundedCross_Previews: PreviewProvider {
static var previews: some View {
RoundedCross()
}
}

View File

@ -0,0 +1,27 @@
//
// SlimRectangle.swift
// Confetti
//
// Created by Simon Bachmann on 04.12.20.
//
import SwiftUI
public struct SlimRectangle: Shape {
public func path(in rect: CGRect) -> Path {
var path = Path()
path.move(to: CGPoint(x: rect.minX, y: 4*rect.maxY/5))
path.addLine(to: CGPoint(x: rect.maxX, y: 4*rect.maxY/5))
path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
return path
}
}
struct SlimRectangle_Previews: PreviewProvider {
static var previews: some View {
SlimRectangle()
}
}

View File

@ -0,0 +1,27 @@
//
// Triangle.swift
// Confetti
//
// Created by Simon Bachmann on 04.12.20.
//
import SwiftUI
public struct Triangle: Shape {
public func path(in rect: CGRect) -> Path {
var path = Path()
path.move(to: CGPoint(x: rect.midX, y: rect.minY))
path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
path.addLine(to: CGPoint(x: rect.midX, y: rect.minY))
return path
}
}
struct Triangle_Previews: PreviewProvider {
static var previews: some View {
Triangle()
}
}