diff --git a/Assets/Prism.mp4 b/Assets/Prism.mp4 new file mode 100644 index 0000000..1206c7d Binary files /dev/null and b/Assets/Prism.mp4 differ diff --git a/Example/PrismExample/PrismExample.xcodeproj/project.pbxproj b/Example/PrismExample/PrismExample.xcodeproj/project.pbxproj index 1f7d7e2..47985a3 100644 --- a/Example/PrismExample/PrismExample.xcodeproj/project.pbxproj +++ b/Example/PrismExample/PrismExample.xcodeproj/project.pbxproj @@ -26,6 +26,7 @@ 3C35DD4028E28804006B7A47 /* Basic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C35DD3F28E28804006B7A47 /* Basic.swift */; }; 3C35DD4228E28818006B7A47 /* Logo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C35DD4128E28818006B7A47 /* Logo.swift */; }; 3C35DD4428E28827006B7A47 /* Models.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C35DD4328E28827006B7A47 /* Models.swift */; }; + 3C44857628E34E9C005F7B46 /* Interaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C44857528E34E9C005F7B46 /* Interaction.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -49,6 +50,7 @@ 3C35DD3F28E28804006B7A47 /* Basic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Basic.swift; sourceTree = ""; }; 3C35DD4128E28818006B7A47 /* Logo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Logo.swift; sourceTree = ""; }; 3C35DD4328E28827006B7A47 /* Models.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Models.swift; sourceTree = ""; }; + 3C44857528E34E9C005F7B46 /* Interaction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Interaction.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -133,6 +135,7 @@ 3C35DD3928E2846D006B7A47 /* Slime.swift */, 3C35DD3D28E28800006B7A47 /* Transform.swift */, 3C35DD4128E28818006B7A47 /* Logo.swift */, + 3C44857528E34E9C005F7B46 /* Interaction.swift */, ); path = Showcase; sourceTree = ""; @@ -214,6 +217,7 @@ buildActionMask = 2147483647; files = ( 3C35DD2928E25D53006B7A47 /* Color.swift in Sources */, + 3C44857628E34E9C005F7B46 /* Interaction.swift in Sources */, 3C35DD3A28E2846D006B7A47 /* Slime.swift in Sources */, 3C35DD4028E28804006B7A47 /* Basic.swift in Sources */, 3C35DD3528E27FD5006B7A47 /* Image.swift in Sources */, diff --git a/Example/PrismExample/PrismExample/Gallery/GalleryView.swift b/Example/PrismExample/PrismExample/Gallery/GalleryView.swift index d812e49..14aa340 100644 --- a/Example/PrismExample/PrismExample/Gallery/GalleryView.swift +++ b/Example/PrismExample/PrismExample/Gallery/GalleryView.swift @@ -14,6 +14,7 @@ enum ExampleKind: String { case slime = "Slime" case transform = "Transform" case logo = "Logo" + case interaction = "Interaction" case color = "Color" case gradient = "Gradient" @@ -38,6 +39,8 @@ struct GalleryView: View { TransformGalleryView(model: model) LogoGalleryView(model: model) + + InteractionGalleryView(model: model) } header: { Text("Showcase") .foregroundColor(UIColor.secondaryLabel.color) @@ -72,6 +75,8 @@ struct GalleryView: View { TransformDetailView() case .logo: LogoDetailView() + case .interaction: + InteractionDetailView() case .color: ColorDetailView() case .gradient: diff --git a/Example/PrismExample/PrismExample/Showcase/Interaction.swift b/Example/PrismExample/PrismExample/Showcase/Interaction.swift new file mode 100644 index 0000000..c206b2d --- /dev/null +++ b/Example/PrismExample/PrismExample/Showcase/Interaction.swift @@ -0,0 +1,98 @@ +// +// Interaction.swift +// PrismExample +// +// Created by A. Zheng (github.com/aheze) on 9/27/22. +// Copyright © 2022 A. Zheng. All rights reserved. +// + +import Prism +import SwiftUI + +struct InteractionGalleryView: View { + @ObservedObject var model: ViewModel + @State var configuration = PrismConfiguration( + tilt: 1, + size: .init(width: 60, height: 60), + extrusion: 60 + ) + + var body: some View { + GalleryCardView(model: model, kind: .interaction) { + PrismCanvas(tilt: configuration.tilt) { + InteractionPrismView(configuration: configuration) + } + .scaleEffect(y: 0.76) + .allowsHitTesting(false) + .frame(minHeight: 240) + .offset(y: 20) + } + } +} + +struct InteractionDetailView: View { + @State var configuration = PrismConfiguration( + tilt: 1, + size: .init(width: 60, height: 60), + extrusion: 60 + ) + + var body: some View { + PrismCanvas(tilt: configuration.tilt) { + InteractionPrismView(configuration: configuration) + } + .scaleEffect(y: 0.76) + .navigationTitle("Interaction") + } +} + +class InteractionPrismViewModel: ObservableObject { + @Published var rotateBlue = false + @Published var rotateRed = false + @Published var rotateGreen = false + + func rotate(keyPath: ReferenceWritableKeyPath) { + withAnimation(.spring()) { + self[keyPath: keyPath] = true + } + + DispatchQueue.main.asyncAfter(deadline: .now() + 0.9) { + withAnimation(.spring()) { + self[keyPath: keyPath] = false + } + } + } +} + +struct InteractionPrismView: View { + var configuration: PrismConfiguration + @StateObject var model = InteractionPrismViewModel() + + var body: some View { + PrismView(configuration: configuration) { + Button { + model.rotate(keyPath: \.rotateBlue) + } label: { + Color.blue + .rotationEffect(.degrees(model.rotateBlue ? 180 : 0)) + } + .buttonStyle(.scaling) + } left: { + Button { + model.rotate(keyPath: \.rotateRed) + } label: { + Color.red + .rotationEffect(.degrees(model.rotateRed ? 180 : 0)) + } + .buttonStyle(.scaling) + } right: { + Button { + model.rotate(keyPath: \.rotateGreen) + } label: { + Color.green + .rotationEffect(.degrees(model.rotateGreen ? 180 : 0)) + } + .buttonStyle(.scaling) + } + } +}