Skip to content

Instantly share code, notes, and snippets.

@rr-codes
Created July 9, 2020 20:38
Show Gist options
  • Select an option

  • Save rr-codes/439d4dbf265448b970596c7c0d983414 to your computer and use it in GitHub Desktop.

Select an option

Save rr-codes/439d4dbf265448b970596c7c0d983414 to your computer and use it in GitHub Desktop.
//
// Playground.swift
// Hourglass
//
// Created by Richard Robinson on 2020-07-06.
//
import Foundation
import SwiftUI
import PlaygroundSupport
extension AnyTransition {
static var rotate: AnyTransition { get {
AnyTransition.modifier(active: RotateTransition(percent: 0), identity: RotateTransition(percent: 1))
}
}
}
struct RotateTransition: GeometryEffect {
var percent: Double
var animatableData: Double {
get { percent }
set { percent = newValue }
}
func effectValue(size: CGSize) -> ProjectionTransform {
let rotationPercent = percent
let a = CGFloat(Angle(degrees: 170 * (1-rotationPercent)).radians)
var transform3d = CATransform3DIdentity;
transform3d.m34 = -1/max(size.width, size.height)
transform3d = CATransform3DRotate(transform3d, a, 0, 1, 0)
transform3d = CATransform3DTranslate(transform3d, -size.width/2.0, -size.height/2.0, 0)
let affineTransform1 = ProjectionTransform(CGAffineTransform(translationX: size.width/2.0, y: size.height / 2.0))
let affineTransform2 = ProjectionTransform(CGAffineTransform(scaleX: CGFloat(percent * 2), y: CGFloat(percent * 2)))
if percent <= 0.5 {
return ProjectionTransform(transform3d).concatenating(affineTransform2).concatenating(affineTransform1)
} else {
return ProjectionTransform(transform3d).concatenating(affineTransform1)
}
}
}
struct ContentView : View {
@State var show = false
@State var selectedColor: Color? = nil
@Namespace var namespace
let columns: [GridItem] = Array(repeating: GridItem(.flexible(), spacing: 0), count: 2)
let colors: [Color] = [.red, .blue, .green, .purple, .pink, .yellow]
var body: some View {
ZStack {
LazyVGrid(columns: columns) {
ForEach(colors, id: \.self) { color in
color
.frame(width: 200, height: 200)
.onTapGesture {
self.selectedColor = color
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
self.show = true
}
}
.zIndex(self.selectedColor == color ? 5 : 0)
.animation(.spring())
.transition(.rotate)
.matchedGeometryEffect(id: "\(color.hashValue)", in: namespace, isSource: false)
}
}
if show {
Color.black
.frame(width: 300, height: 300, alignment: .center)
.zIndex(2)
.animation(.spring())
.transition(.rotate)
.matchedGeometryEffect(id: "\(selectedColor?.hashValue ?? -1)", in: namespace, isSource: true)
}
}
}
}
PlaygroundPage.current.setLiveView(
ContentView().frame(width: 450, height: 650)
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment