Skip to content

Commit

Permalink
Return ShimmerModifier
Browse files Browse the repository at this point in the history
  • Loading branch information
bigMOTOR committed May 26, 2023
1 parent a849d21 commit 0589e7a
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 1 deletion.
2 changes: 1 addition & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ let package = Package(
platforms: [
.iOS(.v13),
.watchOS(.v7),
.macOS(.v11)
.macOS(.v12)
],
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ func cornerRadius(_ radius: CGFloat, corners: UIRectCorner)
func onRotate(perform action: @escaping (UIDeviceOrientation) -> Void)
func rotateHandling(anchor: UnitPoint = .center)
func rotated(_ angle: Angle)
func shimmer(isActive: Bool = true, speed: Double = 0.15, angle: Angle = .init(degrees: 70), opacity: Double = 1.0)
```

Shapes:
Expand Down
76 changes: 76 additions & 0 deletions Sources/HelpersSwiftUI/View/Modifiers/ShimmerModifier.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
//
// ShimmerModifier.swift
//
//
// Created by Mykola Fiantsev on 27.05.2023.
//

import SwiftUI

public extension View {
func shimmer(isActive: Bool = true, speed: Double = 0.15, angle: Angle = .init(degrees: 70), opacity: Double = 1.0) -> some View {
return self.modifier(ShimmerModifier(isActive: isActive, speed: speed, angle: angle, opacity: opacity))
}
}

private struct ShimmerModifier: ViewModifier {
let isActive: Bool
let speed: Double
let angle: Angle
let opacity: Double

@ViewBuilder
func body(content: Content) -> some View {
if !isActive { content }

content
.opacity(opacity)
.overlay(ShimmerView(speed: speed, angle: angle).mask(content))
}
}

private struct ShimmerView: View {
let speed: Double
let angle: Angle
@State private var _show = false

var body: some View {
GeometryReader { geo in
Color.white
.mask(Rectangle().fill(_gradient))
.padding(-_calcSize(geo))
.rotationEffect(angle)
.offset(x: _calcOffset(geo), y: 0)
.animation(_animation)
}
.onAppear { _show.toggle() }
}

private var _gradient: LinearGradient {
let leading = Gradient.Stop(color: .clear, location: 0.35)
let center = Gradient.Stop(color: Color.white.opacity(0.7), location: 0.45)
let trailing = Gradient.Stop(color: .clear, location: 0.55)

return LinearGradient(
gradient: .init(stops: [leading, center, trailing]),
startPoint: .top,
endPoint: .bottom
)
}

private var _animation: Animation {
Animation.default
.speed(0.15)
.delay(0)
.repeatForever(autoreverses: false)
}

private func _calcOffset(_ geo: GeometryProxy) -> CGFloat {
let size = _calcSize(geo)
return (_show ? size : -size) * 2
}

private func _calcSize(_ geo: GeometryProxy) -> CGFloat {
return max(geo.size.width, geo.size.height)
}
}

0 comments on commit 0589e7a

Please sign in to comment.