- Cards were swinging left and right instead of rotating in place
- Using
rotationEffectwhich rotates in 2D plane - No proper 3D perspective or center anchor
// Before: 2D rotation (swinging motion)
.rotationEffect(.degrees(rotationAngle))
// After: 3D rotation around center axis
.rotation3DEffect(
.degrees(rotationY),
axis: (x: 0, y: 1, z: 0), // Rotate around Y-axis (vertical)
anchor: .center, // Rotate around center point
perspective: 0.5 // Add perspective for 3D effect
)- Axis:
(x: 0, y: 1, z: 0)- Rotates around vertical Y-axis - Anchor:
.center- Rotation happens around card's center point - Perspective:
0.5- Adds 3D depth perception - Angle:
8.0degrees - Increased for more visible 3D effect - Duration:
6.0seconds - Slower for smoother motion
- Header wasn't hiding/showing on scroll
- Poor scroll offset detection
- Threshold-based approach wasn't working reliably
// Improved scroll detection with delta-based approach
private func handleScrollOffset(_ offset: CGFloat) {
let scrollDelta = offset - lastScrollOffset
let threshold: CGFloat = 5
if abs(scrollDelta) > threshold {
if scrollDelta < -threshold {
// Scrolling down - hide header
isHeaderVisible = false
} else if scrollDelta > threshold {
// Scrolling up - show header
isHeaderVisible = true
}
lastScrollOffset = offset
}
// Always show header when at top
if offset >= -10 {
isHeaderVisible = true
}
}- Delta-based Detection: Compares current vs previous scroll position
- Directional Logic: Detects scroll direction (up/down) instead of absolute position
- Top Override: Always shows header when near the top
- Debug Logging: Console output to track scroll behavior
- Reduced Threshold: More responsive to scroll movements
// Before: Generic coordinate space
.coordinateSpace(name: "scroll")
// After: Specific scroll view coordinate space
.coordinateSpace(name: "scrollView")GeometryReader { geometry in
let offset = geometry.frame(in: .named("scrollView")).minY
Color.clear
.preference(key: ScrollOffsetPreferenceKey.self, value: offset)
.onAppear {
print("🎯 Initial scroll position: \(offset)")
}
}
.frame(height: 1) // Minimal height for detection
.id("scrollDetector") // Unique identifier- Before: Cards swing left-right like pendulums
- After: Cards rotate in place around their center axis with 3D perspective
- Scroll Down: Filter buttons slide up and disappear
- Scroll Up: Filter buttons slide down and reappear
- At Top: Header always visible regardless of previous state
Console logs now show:
📊 Scroll offset: -45.2, delta: -12.3, headerVisible: true
🔽 Hiding header (scrolling down)
🔼 Showing header (scrolling up)
🔝 Showing header (at top)
- Uses hardware-accelerated
rotation3DEffect - Proper anchor point prevents layout recalculations
- Perspective value optimized for performance
- Delta-based approach reduces unnecessary animations
- Threshold prevents micro-scroll triggers
- State tracking minimizes redundant updates
- Observe: Cards should rotate in place around their center
- 3D Effect: Should see depth/perspective as cards turn
- Smooth Motion: 6-second cycles with easeInOut animation
- Scroll Down: Header should disappear after scrolling down
- Scroll Up: Header should reappear when scrolling up
- Top Position: Header should always show when at top
- Console: Check logs for scroll detection feedback
The animations now provide proper 3D card rotation and reliable collapsible header behavior!