Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save MojtabaHs/91e34fd0e987fe7ce801936dc6ece0e8 to your computer and use it in GitHub Desktop.
Save MojtabaHs/91e34fd0e987fe7ce801936dc6ece0e8 to your computer and use it in GitHub Desktop.
var body: some View {
GeometryReader { geometry in
ForEach(0..<Int(count)) { index in
item(forIndex: index, in: geometry.size)
}
}
.aspectRatio(contentMode: .fit)
}
struct UsageDemoView: View {
@State var start: Bool = true
var body: some View {
VStack(spacing: 24) {
HStack(spacing: 24) {
Bars(animate: $start, opacityRange: 1...1)
Bars(animate: $start, scaleRange: 1...1)
Bars(animate: $start, count: 3)
}
Button("toggle") { start.toggle() }
}
.padding()
.foregroundColor(.red)
}
}
private func size(count: UInt, geometry: CGSize) -> CGFloat {
(geometry.width/CGFloat(count)) - (spacing-2)
}
private var scale: CGFloat {
CGFloat(isAnimating ? scaleRange.lowerBound : scaleRange.upperBound)
}
private var opacity: Double {
isAnimating ? opacityRange.lowerBound : opacityRange.upperBound
}
public init(animate: Binding<Bool>,
count: UInt = 8,
spacing: CGFloat = 8,
cornerRadius: CGFloat = 8,
scaleRange: ClosedRange<Double> = (0.5...1),
opacityRange: ClosedRange<Double> = (0.25...1)) {
self._isAnimating = animate
self.count = count
self.spacing = spacing
self.cornerRadius = cornerRadius
self.scaleRange = scaleRange
self.opacityRange = opacityRange
}
struct Bars: View {
@Binding var isAnimating: Bool
let count: UInt
let spacing: CGFloat
let cornerRadius: CGFloat
let scaleRange: ClosedRange<Double>
let opacityRange: ClosedRange<Double>
}
private func item(forIndex index: Int, in geometrySize: CGSize) -> some View {
RoundedRectangle(cornerRadius: cornerRadius, style: .continuous)
.frame(width: size(count: count, geometry: geometrySize), height: geometrySize.height)
.scaleEffect(x: 1, y: scale, anchor: .center)
.opacity(opacity)
.animation(
Animation
.default
.repeatCount(isAnimating ? .max : 1, autoreverses: true)
.delay(Double(index) / Double(count) / 2)
)
.offset(x: CGFloat(index) * (size(count: count, geometry: geometrySize) + spacing))
}
extension Bars {
func style(count: UInt = 8,
spacing: CGFloat = 8,
cornerRadius: CGFloat = 8,
scaleRange: ClosedRange<Double> = (0.5...1),
opacityRange: ClosedRange<Double> = (0.25...1)) -> Self {
Self.init(animate: self.$isAnimating,
count: count,
spacing: spacing,
cornerRadius: cornerRadius,
scaleRange: scaleRange,
opacityRange: opacityRange)
}
}
Bars(animate: $start)
.style(count: 3)
struct DirectUsageView_Previews: PreviewProvider {
static var previews: some View {
UsageDemoView()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment