commit
bedae06152
|
@ -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.
|
||||||
|
|
|
@ -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 |
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue