Skip to content

Commit

Permalink
Animation implementation using the Web Animations API (#427)
Browse files Browse the repository at this point in the history
  • Loading branch information
carson-katri committed Jul 13, 2021
1 parent a064956 commit ab5e564
Show file tree
Hide file tree
Showing 45 changed files with 1,920 additions and 262 deletions.
8 changes: 6 additions & 2 deletions NativeDemo/TokamakDemo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
207C05712610E16E00BBBE54 /* DatePickerDemo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 207C056F2610E16E00BBBE54 /* DatePickerDemo.swift */; };
262DA7B32695D99500CABEAE /* ShapeStyleDemo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 262DA7B22695D99500CABEAE /* ShapeStyleDemo.swift */; };
262DA7B42695D99500CABEAE /* ShapeStyleDemo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 262DA7B22695D99500CABEAE /* ShapeStyleDemo.swift */; };
26A3BFB0269BD18A0004DA16 /* AnimationDemo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26A3BFAF269BD18A0004DA16 /* AnimationDemo.swift */; };
26A3BFB1269BD18A0004DA16 /* AnimationDemo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 26A3BFAF269BD18A0004DA16 /* AnimationDemo.swift */; };
3DCDE44424CA6AD400910F17 /* SidebarDemo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DCDE44324CA6AD400910F17 /* SidebarDemo.swift */; };
3DCDE44524CA6AD400910F17 /* SidebarDemo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DCDE44324CA6AD400910F17 /* SidebarDemo.swift */; };
4550BD5225B642B80088F4EA /* ShadowDemo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4550BD5125B642B80088F4EA /* ShadowDemo.swift */; };
Expand Down Expand Up @@ -100,6 +102,7 @@
/* Begin PBXFileReference section */
207C056F2610E16E00BBBE54 /* DatePickerDemo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DatePickerDemo.swift; sourceTree = "<group>"; };
262DA7B22695D99500CABEAE /* ShapeStyleDemo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShapeStyleDemo.swift; sourceTree = "<group>"; };
26A3BFAF269BD18A0004DA16 /* AnimationDemo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnimationDemo.swift; sourceTree = "<group>"; };
3DCDE44324CA6AD400910F17 /* SidebarDemo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SidebarDemo.swift; sourceTree = "<group>"; };
4550BD5125B642B80088F4EA /* ShadowDemo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ShadowDemo.swift; sourceTree = "<group>"; };
8500293E24D2FF3E001A2E84 /* SliderDemo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SliderDemo.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -194,10 +197,9 @@
85ED189924AD425E0085DFA0 /* TokamakDemo */ = {
isa = PBXGroup;
children = (
26A3BFAF269BD18A0004DA16 /* AnimationDemo.swift */,
262DA7B22695D99500CABEAE /* ShapeStyleDemo.swift */,
D120FDDA257E7145008FFBAD /* TextEditorDemo.swift */,
D1D6B62224D817350041E1D9 /* GeometryReaderDemo.swift */,
D1C726F224CB63C6003B576D /* ButtonStyleDemo.swift */,
B5C76E4924C73ED4003EABB2 /* AppStorageDemo.swift */,
D1C726F224CB63C6003B576D /* ButtonStyleDemo.swift */,
B56F22DF24BC89FD001738DF /* ColorDemo.swift */,
Expand Down Expand Up @@ -372,6 +374,7 @@
D1D6B62324D817350041E1D9 /* GeometryReaderDemo.swift in Sources */,
B5DBA22B24D509B4003D3347 /* RedactDemo.swift in Sources */,
B56F22E024BC89FD001738DF /* ColorDemo.swift in Sources */,
26A3BFB0269BD18A0004DA16 /* AnimationDemo.swift in Sources */,
B51F215024B920B400CF2583 /* PathDemo.swift in Sources */,
85ED18AF24AD425E0085DFA0 /* EnvironmentDemo.swift in Sources */,
85ED18A324AD425E0085DFA0 /* SpacerDemo.swift in Sources */,
Expand Down Expand Up @@ -406,6 +409,7 @@
D1B4229324B3B9BB00682F74 /* OutlineGroupDemo.swift in Sources */,
D1D6B62424D817350041E1D9 /* GeometryReaderDemo.swift in Sources */,
B5DBA22C24D509B4003D3347 /* RedactDemo.swift in Sources */,
26A3BFB1269BD18A0004DA16 /* AnimationDemo.swift in Sources */,
B56F22E124BC89FD001738DF /* ColorDemo.swift in Sources */,
B51F215124B920B400CF2583 /* PathDemo.swift in Sources */,
85ED18A424AD425E0085DFA0 /* SpacerDemo.swift in Sources */,
Expand Down
153 changes: 153 additions & 0 deletions Sources/TokamakCore/Animation/Animatable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
// Copyright 2020 Tokamak contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Created by Carson Katri on 7/11/21.
//

import Foundation

public protocol Animatable {
associatedtype AnimatableData: VectorArithmetic
var animatableData: Self.AnimatableData { get set }
}

public protocol _PrimitiveAnimatable {}

public extension Animatable where Self: VectorArithmetic {
var animatableData: Self {
get { self }
// swiftlint:disable:next unused_setter_value
set {}
}
}

public extension Animatable where Self.AnimatableData == EmptyAnimatableData {
var animatableData: EmptyAnimatableData {
@inlinable get { EmptyAnimatableData() }
// swiftlint:disable:next unused_setter_value
@inlinable set {}
}
}

@frozen public struct EmptyAnimatableData: VectorArithmetic {
@inlinable
public init() {}
@inlinable public static var zero: Self { .init() }
@inlinable
public static func += (lhs: inout Self, rhs: Self) {}
@inlinable
public static func -= (lhs: inout Self, rhs: Self) {}
@inlinable
public static func + (lhs: Self, rhs: Self) -> Self {
.zero
}

@inlinable
public static func - (lhs: Self, rhs: Self) -> Self {
.zero
}

@inlinable
public mutating func scale(by rhs: Double) {}
@inlinable public var magnitudeSquared: Double { .zero }
public static func == (a: Self, b: Self) -> Bool { true }
}

@frozen public struct AnimatablePair<First, Second>: VectorArithmetic
where First: VectorArithmetic, Second: VectorArithmetic
{
public var first: First
public var second: Second
@inlinable
public init(_ first: First, _ second: Second) {
self.first = first
self.second = second
}

@inlinable
internal subscript() -> (First, Second) {
get { (first, second) }
set { (first, second) = newValue }
}

@_transparent public static var zero: Self {
@_transparent get {
.init(First.zero, Second.zero)
}
}

@_transparent
public static func += (lhs: inout Self, rhs: Self) {
lhs.first += rhs.first
lhs.second += rhs.second
}

@_transparent
public static func -= (lhs: inout Self, rhs: Self) {
lhs.first -= rhs.first
lhs.second -= rhs.second
}

@_transparent
public static func + (lhs: Self, rhs: Self) -> Self {
.init(lhs.first + rhs.first, lhs.second + rhs.second)
}

@_transparent
public static func - (lhs: Self, rhs: Self) -> Self {
.init(lhs.first - rhs.first, lhs.second - rhs.second)
}

@_transparent
public mutating func scale(by rhs: Double) {
first.scale(by: rhs)
second.scale(by: rhs)
}

@_transparent public var magnitudeSquared: Double {
@_transparent get {
first.magnitudeSquared + second.magnitudeSquared
}
}

public static func == (a: Self, b: Self) -> Bool {
a.first == b.first
&& a.second == b.second
}
}

extension CGPoint: Animatable {
public var animatableData: AnimatablePair<CGFloat, CGFloat> {
@inlinable get { .init(x, y) }
@inlinable set { (x, y) = newValue[] }
}
}

extension CGSize: Animatable {
public var animatableData: AnimatablePair<CGFloat, CGFloat> {
@inlinable get { .init(width, height) }
@inlinable set { (width, height) = newValue[] }
}
}

extension CGRect: Animatable {
public var animatableData: AnimatablePair<CGPoint.AnimatableData, CGSize.AnimatableData> {
@inlinable get {
.init(origin.animatableData, size.animatableData)
}
@inlinable set {
(origin.animatableData, size.animatableData) = newValue[]
}
}
}
18 changes: 18 additions & 0 deletions Sources/TokamakCore/Animation/AnimatableModifier.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright 2020 Tokamak contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Created by Carson Katri on 7/11/21.
//

public protocol AnimatableModifier: Animatable, ViewModifier {}
Loading

0 comments on commit ab5e564

Please sign in to comment.