diff --git a/README.md b/README.md index 5418ed6..1eb7a14 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ SwiftUI-Version ![Badge](https://img.shields.io/badge/swift-white.svg?style=flat-square&logo=Swift) ![Badge](https://img.shields.io/badge/SwiftUI-001b87.svg?style=flat-square&logo=Swift&logoColor=black) -![Badge - Version](https://img.shields.io/badge/Version-0.7.0-1177AA?style=flat-square) +![Badge - Version](https://img.shields.io/badge/Version-0.7.1-1177AA?style=flat-square) ![Badge - Swift Package Manager](https://img.shields.io/badge/SPM-compatible-orange?style=flat-square) ![Badge - Platform](https://img.shields.io/badge/platform-mac_12|ios_15|watchos_8|tvos_15-yellow?style=flat-square) ![Badge - License](https://img.shields.io/badge/license-MIT-black?style=flat-square) @@ -171,6 +171,6 @@ Once you have your Swift package set up, adding AnimateNumberText as a dependenc ```swift dependencies: [ - .package(url: "https://github.com/swift-man/AnimateNumberText.git", from: "0.7.0") + .package(url: "https://github.com/swift-man/AnimateNumberText.git", from: "0.7.1") ] ``` diff --git a/Sources/AnimateNumberText/AnimateNumberText.docc/AnimateNumberText.md b/Sources/AnimateNumberText/AnimateNumberText.docc/AnimateNumberText.md index 1fb1fdb..74991f6 100644 --- a/Sources/AnimateNumberText/AnimateNumberText.docc/AnimateNumberText.md +++ b/Sources/AnimateNumberText/AnimateNumberText.docc/AnimateNumberText.md @@ -14,7 +14,7 @@ Add AnimateNumberText to your Swift package dependencies. ```swift dependencies: [ - .package(url: "https://github.com/swift-man/AnimateNumberText.git", from: "0.7.0") + .package(url: "https://github.com/swift-man/AnimateNumberText.git", from: "0.7.1") ] ``` diff --git a/Sources/AnimateNumberText/Private/TextType.swift b/Sources/AnimateNumberText/Private/TextType.swift index f9de879..0f82f9c 100644 --- a/Sources/AnimateNumberText/Private/TextType.swift +++ b/Sources/AnimateNumberText/Private/TextType.swift @@ -93,6 +93,18 @@ extension Array where Element == TextColumn { filter(\.value.isNumber).count } + func digitOrdinalsByIndex() -> [Int: Int] { + var ordinalsByIndex: [Int: Int] = [:] + var digitOrdinal = 0 + + for index in indices where self[index].value.isNumber { + ordinalsByIndex[index] = digitOrdinal + digitOrdinal += 1 + } + + return ordinalsByIndex + } + func preservingReelPositions(_ positions: [UUID: Double]) -> [UUID: Double] { var nextPositions: [UUID: Double] = [:] @@ -115,22 +127,50 @@ extension Array where Element == TextColumn { return nextPositions } + @available(iOS 15.0, macOS 12.0, tvOS 15.0, watchOS 8.0, *) + func reelPositions(updatingTo characters: [Character], + animation: AnimateNumberTextAnimation, + currentPositions: [UUID: Double]) -> [UUID: Double] { + let digitOrdinals = digitOrdinalsByIndex() + var nextPositions = preservingReelPositions(currentPositions) + + for (index, character) in characters.enumerated() { + let targetValue = TextType(character) + guard canAnimateDigitChange(to: targetValue, index: index), + let digit = targetValue.digitValue, + let digitOrdinal = digitOrdinals[index] else { + continue + } + + let column = self[index] + let currentPosition = nextPositions[column.id] + ?? Double(column.value.digitValue ?? digit) + nextPositions[column.id] = animation.reelTargetPosition(from: currentPosition, + to: digit, + ordinal: digitOrdinal) + } + + return nextPositions + } + func canAnimateDigitChange(to value: Character, index: Int) -> Bool { + canAnimateDigitChange(to: TextType(value), index: index) + } + + func canAnimateDigitChange(to value: TextType, index: Int) -> Bool { guard indices.contains(index) else { return false } - return self[index].value.isNumber && TextType(value).isNumber + return self[index].value.isNumber && value.isNumber } func needsUpdate(to value: Character, index: Int) -> Bool { - guard indices.contains(index) else { return false } - - return self[index].value != TextType(value) + needsUpdate(to: TextType(value), index: index) } - func digitOrdinal(at index: Int) -> Int? { - guard indices.contains(index), self[index].value.isNumber else { return nil } + func needsUpdate(to value: TextType, index: Int) -> Bool { + guard indices.contains(index) else { return false } - return self[..