Skip to content

Commit

Permalink
Add animation and AnimatedMeshGradientView
Browse files Browse the repository at this point in the history
  • Loading branch information
rudrankriyam committed Oct 19, 2024
1 parent d751371 commit bbcac98
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 0 deletions.
73 changes: 73 additions & 0 deletions Sources/MeshingKit/AnimatedMeshGradientView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//
// AnimatedMeshGradientView.swift
// MeshingKit
//
// Created by Rudrank Riyam on 10/19/24.
//

import SwiftUI

/// A view that displays an animated mesh gradient.
struct AnimatedMeshGradientView: View {
var gridSize: Int
@Binding var showAnimation: Bool
var positions: [SIMD2<Float>]
var colors: [Color]
var background: Color

var body: some View {
TimelineView(.animation(minimumInterval: 1/120, paused: !showAnimation)) { phase in
MeshGradient(
width: gridSize,
height: gridSize,
locations: .points(animatedPositions(for: phase.date)),
colors: .colors(colors),
background: background,
smoothsColors: true
)
.ignoresSafeArea()
}
}

private func animatedPositions(for date: Date) -> [SIMD2<Float>] {
if gridSize == 3 {
let phase = date.timeIntervalSinceReferenceDate
var animatedPositions = positions.map { CGPoint(x: CGFloat($0.x), y: CGFloat($0.y)) }

animatedPositions[1].x = 0.5 + 0.4 * CGFloat(cos(phase))
animatedPositions[3].y = 0.5 + 0.3 * CGFloat(cos(phase * 1.1))
animatedPositions[4].y = 0.5 - 0.4 * CGFloat(cos(phase * 0.9))
animatedPositions[4].x = 0.5 + 0.2 * CGFloat(cos(phase * 0.7))
animatedPositions[5].y = 0.5 - 0.2 * CGFloat(cos(phase * 0.9))
animatedPositions[7].x = 0.5 - 0.4 * CGFloat(cos(phase * 1.2))

return animatedPositions.map { SIMD2<Float>(Float($0.x), Float($0.y)) }
} else if gridSize == 4 {
let phase = date.timeIntervalSinceReferenceDate / 2
var animatedPositions = positions.map { CGPoint(x: CGFloat($0.x), y: CGFloat($0.y)) }

// Animate middle points of edges
animatedPositions[1].x = 0.33 + 0.1 * CGFloat(cos(phase * 0.7)) // Top edge
animatedPositions[2].x = 0.67 - 0.1 * CGFloat(cos(phase * 0.8)) // Top edge
animatedPositions[4].y = 0.33 + 0.1 * CGFloat(cos(phase * 0.9)) // Left edge
animatedPositions[7].y = 0.37 - 0.1 * CGFloat(cos(phase * 0.6)) // Left edge
animatedPositions[11].y = 0.67 - 0.1 * CGFloat(cos(phase * 1.2)) // Bottom edge
animatedPositions[13].x = 0.33 + 0.1 * CGFloat(cos(phase * 1.3)) // Right edge
animatedPositions[14].x = 0.67 - 0.1 * CGFloat(cos(phase * 1.4)) // Right edge

// Animate inner points
animatedPositions[5].x = 0.33 + 0.15 * CGFloat(cos(phase * 0.8))
animatedPositions[5].y = 0.33 + 0.15 * CGFloat(cos(phase * 0.9))
animatedPositions[6].x = 0.67 - 0.15 * CGFloat(cos(phase * 1.0))
animatedPositions[6].y = 0.33 + 0.15 * CGFloat(cos(phase * 1.1))
animatedPositions[9].x = 0.33 + 0.15 * CGFloat(cos(phase * 1.2))
animatedPositions[9].y = 0.67 - 0.15 * CGFloat(cos(phase * 1.3))
animatedPositions[10].x = 0.67 - 0.15 * CGFloat(cos(phase * 1.4))
animatedPositions[10].y = 0.67 - 0.15 * CGFloat(cos(phase * 1.5))

return animatedPositions.map { SIMD2<Float>(Float($0.x), Float($0.y)) }
} else {
return positions
}
}
}
39 changes: 39 additions & 0 deletions Sources/MeshingKit/MeshingKit.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//

import SwiftUI

/// A structure that provides utility functions for creating mesh gradients.
public struct MeshingKit: Sendable {

Expand Down Expand Up @@ -41,4 +42,42 @@ public struct MeshingKit: Sendable {
@MainActor public static func gradientSize4(template: GradientTemplateSize4) -> MeshGradient {
MeshGradient(width: template.size, height: template.size, points: template.points, colors: template.colors)
}

/// Creates an animated `MeshGradient` view from a given `GradientTemplateSize3`.
///
/// This function takes a `GradientTemplateSize3` and creates an animated `MeshGradient` view,
/// using the template's size, points, colors, and background.
///
/// - Parameters:
/// - template: A `GradientTemplateSize3` containing the gradient's specifications.
/// - showAnimation: A binding to control the animation's play/pause state.
/// - Returns: A view containing the animated `MeshGradient`.
@MainActor public static func animatedGradientSize3(template: GradientTemplateSize3, showAnimation: Binding<Bool>) -> some View {
AnimatedMeshGradientView(
gridSize: template.size,
showAnimation: showAnimation,
positions: template.points,
colors: template.colors,
background: template.background
)
}

/// Creates an animated `MeshGradient` view from a given `GradientTemplateSize4`.
///
/// This function takes a `GradientTemplateSize4` and creates an animated `MeshGradient` view,
/// using the template's size, points, colors, and background.
///
/// - Parameters:
/// - template: A `GradientTemplateSize4` containing the gradient's specifications.
/// - showAnimation: A binding to control the animation's play/pause state.
/// - Returns: A view containing the animated `MeshGradient`.
@MainActor public static func animatedGradientSize4(template: GradientTemplateSize4, showAnimation: Binding<Bool>) -> some View {
AnimatedMeshGradientView(
gridSize: template.size,
showAnimation: showAnimation,
positions: template.points,
colors: template.colors,
background: template.background
)
}
}

0 comments on commit bbcac98

Please sign in to comment.