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:
parent
e0e693791f
commit
6b0a51720e
|
@ -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;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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)]}]
|
||||||
|
|
|
@ -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))))
|
||||||
|
|
|
@ -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?)}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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))
|
||||||
|
|
Loading…
Reference in New Issue