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'; import { useDerivedValue, withTiming, Easing } from 'react-native-reanimated';
const slideAnimationDuration = 300; const slideAnimationDuration = 300;
const totalPages = 4;
const pageSize = 100 / totalPages;
const easeOut = { const easeOut = {
duration: slideAnimationDuration, 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 () { return useDerivedValue(function () {
'worklet'; 'worklet';
const progressValue = progress.value; const progressValue = progress.value;
switch (true) { const dragAmountValue = dragAmount.value;
case progressValue < 25:
return 0; const baseOffset = (Math.floor(progressValue / pageSize) % totalPages) * windowWidth;
case progressValue === 25: const adjustedOffset = baseOffset === 0 && dragAmountValue > 0 ? baseOffset : -baseOffset + dragAmountValue;
return withTiming(-windowWidth, easeOut);
case progressValue < 50: return isDragging.value ? withTiming(adjustedOffset, easeOut) : withTiming(-baseOffset, easeOut);
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;
}
}); });
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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