Update animation for onboarding carousel. (#16294)

* Update animation for onboarding carousel.

* Fixed issues with long press while swipe.

* Fixed issues after generating keys.
This commit is contained in:
Rahul Pratap 2023-06-27 20:45:13 +05:30 committed by GitHub
parent e0e693791f
commit 6b0a51720e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 94 additions and 53 deletions

View File

@ -1,6 +1,8 @@
import { useDerivedValue, withTiming, Easing } from 'react-native-reanimated';
const slideAnimationDuration = 300;
const totalPages = 4;
const pageSize = 100 / totalPages;
const easeOut = {
duration: slideAnimationDuration,
@ -15,29 +17,15 @@ export function dynamicProgressBarWidth(staticProgressBarWidth, progress) {
});
}
export function carouselLeftPosition(windowWidth, progress) {
export function carouselLeftPosition(windowWidth, progress, isDragging, dragAmount) {
return useDerivedValue(function () {
'worklet';
const progressValue = progress.value;
switch (true) {
case progressValue < 25:
return 0;
case progressValue === 25:
return withTiming(-windowWidth, easeOut);
case progressValue < 50:
return -windowWidth;
case progressValue === 50:
return withTiming(-2 * windowWidth, easeOut);
case progressValue < 75:
return -2 * windowWidth;
case progressValue === 75:
return withTiming(-3 * windowWidth, easeOut);
case progressValue < 100:
return -3 * windowWidth;
case progressValue === 100:
return withTiming(-4 * windowWidth, easeOut);
default:
return 0;
}
const dragAmountValue = dragAmount.value;
const baseOffset = (Math.floor(progressValue / pageSize) % totalPages) * windowWidth;
const adjustedOffset = baseOffset === 0 && dragAmountValue > 0 ? baseOffset : -baseOffset + dragAmountValue;
return isDragging.value ? withTiming(adjustedOffset, easeOut) : withTiming(-baseOffset, easeOut);
});
}

View File

@ -19,6 +19,8 @@
(defn gesture-pan [] (.Pan ^js Gesture))
(defn gesture-long-press [] (.LongPress ^js Gesture))
(defn gesture-pinch [] (.Pinch ^js Gesture))
(defn on-begin [gesture handler] (.onBegin ^js gesture handler))

View File

@ -32,6 +32,8 @@
(defonce progress (atom nil))
(defonce paused? (atom nil))
(defonce is-dragging? (atom nil))
(defonce drag-amount (atom nil))
(defn store-screen-height
[evt]
@ -60,7 +62,7 @@
animate? (not dark-overlay?)
window-width (rf/sub [:dimensions/window-width])]
(when animate?
(carousel.animation/use-initialize-animation progress paused? animate?))
(carousel.animation/use-initialize-animation progress paused? animate? is-dragging? drag-amount))
(rn/use-effect
(fn []
@ -78,6 +80,8 @@
:progress progress
:paused? paused?
:header-text header-text
:is-dragging? is-dragging?
:drag-amount drag-amount
:header-background true
:gesture :swipeable
:background [background-image (* 4 window-width)]}]

View File

@ -40,7 +40,7 @@
(if (zero? value) (slide-animation value 0) (slide-animation value)))
(defn animate-progress
[progress paused next-progress]
[progress paused? next-progress]
(let [q (quot next-progress 25)]
(reanimated/set-shared-value
progress
@ -53,7 +53,7 @@
(animate-progress-value (animation-value q 4))
(animate-progress-value (calculate-remainder next-progress drag-limit)))
-1)
paused))))
paused?))))
(defn get-next-progress
[progress]
@ -74,37 +74,74 @@
(* progress-threshold)))))
(defn use-initialize-animation
[progress paused animate?]
[progress paused? animate? is-dragging? drag-amount]
(reset! progress (reanimated/use-shared-value 0))
(reset! paused (reanimated/use-shared-value false))
(reset! paused? (reanimated/use-shared-value false))
(reset! is-dragging? (reanimated/use-shared-value false))
(reset! drag-amount (reanimated/use-shared-value 0))
(rn/use-effect
(fn []
(animate-progress @progress @paused 0))
(animate-progress @progress @paused? 0))
[animate?]))
(defn cleanup-animation
[progress paused]
[progress paused?]
(fn []
(reanimated/cancel-animation @progress)
(reanimated/cancel-animation @paused)))
(reanimated/cancel-animation @paused?)))
(defn update-progress
[progress paused new-progress]
[progress paused? new-progress]
(reanimated/set-shared-value @progress new-progress)
(animate-progress @progress @paused new-progress))
(animate-progress @progress @paused? new-progress))
(defn handle-drag
[event paused? is-dragging? drag-amount]
(let [translation-x (oops/oget event "translationX")]
(reanimated/set-shared-value @paused? true)
(reanimated/set-shared-value @is-dragging? true)
(reanimated/set-shared-value @drag-amount translation-x)))
(defn drag-gesture
[progress paused]
[progress paused? is-dragging? drag-amount]
(-> (gesture/gesture-pan)
(gesture/max-pointers 1)
(gesture/on-start
(fn [event]
(handle-drag event paused? is-dragging? drag-amount)))
(gesture/on-update
(fn [event]
(handle-drag event paused? is-dragging? drag-amount)))
(gesture/on-end
(fn []
(reanimated/set-shared-value @is-dragging? false)
(reanimated/set-shared-value @paused? false)))
(gesture/on-finalize
(fn [event]
(let [next? (< (oops/oget event "translationX") (- drag-limit))
previous? (> (oops/oget event "translationX") drag-limit)]
(when next?
(update-progress progress paused (get-next-progress progress)))
(update-progress progress paused? (get-next-progress progress)))
(when previous?
(update-progress progress paused (get-previous-progress progress))))))))
(update-progress progress paused? (get-previous-progress progress))))))))
(defn long-press-gesture
[paused?]
(->
(gesture/gesture-long-press)
(gesture/enabled true)
(gesture/on-start
(fn []
(reanimated/set-shared-value @paused? true)))
(gesture/on-finalize
(fn []
(reanimated/set-shared-value @paused? false)))))
(defn composed-gestures
[progress paused? is-dragging? drag-amount]
(let [long-press (long-press-gesture paused?)
drag (drag-gesture progress paused? is-dragging? drag-amount)]
(gesture/simultaneous long-press drag)))
(defn tap-gesture
[progress paused]
@ -112,9 +149,12 @@
(gesture/on-end #(update-progress progress paused (get-next-progress progress)))))
(defn carousel-left-position
[window-width animate? progress]
[window-width animate? progress is-dragging? drag-amount]
(if animate?
(worklets.onboarding-carousel/carousel-left-position window-width @progress)
(worklets.onboarding-carousel/carousel-left-position window-width
@progress
@is-dragging?
@drag-amount)
(-> (or (reanimated/get-shared-value @progress) 0)
(quot -25)
(* window-width))))

View File

@ -50,16 +50,19 @@
:progress-bar-width progress-bar-width}]]))
(defn f-view
[{:keys [animate? progress paused? header-text background header-background gesture]}]
(let [window-width (rf/sub [:dimensions/window-width])
status-bar-height (:status-bar-height @navigation/constants)
[{:keys [animate? progress paused? header-text background header-background gesture is-dragging?
drag-amount]}]
(let [window-width (rf/sub [:dimensions/window-width])
status-bar-height (:status-bar-height @navigation/constants)
progress-bar-width (- window-width 40)
carousel-left (animation/carousel-left-position window-width animate? progress)
container-view (if animate? reanimated/view rn/view)
identified-gesture (case gesture
:swipeable (animation/drag-gesture progress paused?)
:tappable (animation/tap-gesture progress paused?)
nil)]
carousel-left
(animation/carousel-left-position window-width animate? progress is-dragging? drag-amount)
container-view (if animate? reanimated/view rn/view)
identified-gesture
(case gesture
:swipeable (animation/composed-gestures progress paused? is-dragging? drag-amount)
:tappable (animation/tap-gesture progress paused?)
nil)]
[:<>
[gesture/gesture-detector {:gesture identified-gesture}
[container-view {:style (style/carousel-container carousel-left animate?)}

View File

@ -25,12 +25,14 @@
[]
(let [progress (atom nil)
paused? (atom nil)
is-dragging? (atom nil)
drag-amount (atom nil)
{:keys [emoji-hash display-name compressed-key
public-key]} (rf/sub [:multiaccount])
{:keys [color]} (rf/sub [:onboarding-2/profile])
photo-path (rf/sub [:chats/photo-path public-key])
emoji-string (string/join emoji-hash)]
(carousel.animation/use-initialize-animation progress paused? true)
(carousel.animation/use-initialize-animation progress paused? true is-dragging? drag-amount)
(rn/use-effect
(fn []
(carousel.animation/cleanup-animation progress paused?))
@ -39,11 +41,13 @@
[background/view true]
[rn/view {:style style/page-container}
[carousel/view
{:animate? true
:progress progress
:paused? paused?
:gesture :tappable
:header-text header-text}]
{:animate? true
:progress progress
:paused? paused?
:gesture :tappable
:is-dragging? is-dragging?
:drag-amount drag-amount
:header-text header-text}]
[rn/view {:style style/content-container}
[profile-card/profile-card
{:profile-picture photo-path

View File

@ -7,5 +7,5 @@
(.dynamicProgressBarWidth ^js worklets static-progress-bar-width progress))
(defn carousel-left-position
[window-width progress]
(.carouselLeftPosition ^js worklets window-width progress))
[window-width progress is-dragging? drag-amount]
(.carouselLeftPosition ^js worklets window-width progress is-dragging? drag-amount))