From 747d18205bb0f17bc6f6ed75d92cb1fed41b85a8 Mon Sep 17 00:00:00 2001 From: Nathan Walker Date: Mon, 13 Mar 2023 13:38:28 -0700 Subject: [PATCH] chore: api cleanup --- apps/toolbox/src/pages/transitions.ts | 12 +- packages/core/ui/frame/index.ios.ts | 5 - .../ui/transition/modal-transition.android.ts | 21 +-- .../ui/transition/modal-transition.ios.ts | 52 +++--- .../ui/transition/page-transition.android.ts | 167 ++++++------------ .../core/ui/transition/page-transition.ios.ts | 62 +++---- .../core/ui/transition/shared-transition.ts | 45 ++++- 7 files changed, 154 insertions(+), 210 deletions(-) diff --git a/apps/toolbox/src/pages/transitions.ts b/apps/toolbox/src/pages/transitions.ts index db9b59a9e..448d068c6 100644 --- a/apps/toolbox/src/pages/transitions.ts +++ b/apps/toolbox/src/pages/transitions.ts @@ -17,11 +17,11 @@ export class TransitionsModel extends Observable { instance: SharedTransition.configure({ page, instance: new PageTransition(), - incomingViewStart: { - duration: 5000, + toPageStart: { + duration: 1000, }, - dismissViewEnd: { - duration: 5000, + fromPageEnd: { + duration: 500, }, }), }, @@ -35,11 +35,11 @@ export class TransitionsModel extends Observable { instance: SharedTransition.configure({ page, instance: new ModalTransition(), - incomingViewStart: { + toPageStart: { y: 200, duration: 1000, }, - dismissViewEnd: { + fromPageEnd: { y: 100, duration: 500, }, diff --git a/packages/core/ui/frame/index.ios.ts b/packages/core/ui/frame/index.ios.ts index b457c37d4..271ea9043 100644 --- a/packages/core/ui/frame/index.ios.ts +++ b/packages/core/ui/frame/index.ios.ts @@ -98,12 +98,7 @@ export class Frame extends FrameBase { const nativeTransition = _getNativeTransition(navigationTransition, true); if (!nativeTransition && navigationTransition) { - // if (navigationTransition.instance?.iosPresentedController) { - // this._ios.controller.transitioningDelegate = this._animatedDelegate; - // } else { this._ios.controller.delegate = this._animatedDelegate; - - // } viewController[DELEGATE] = this._animatedDelegate; } else { viewController[DELEGATE] = null; diff --git a/packages/core/ui/transition/modal-transition.android.ts b/packages/core/ui/transition/modal-transition.android.ts index 2744ae235..1c8336db4 100644 --- a/packages/core/ui/transition/modal-transition.android.ts +++ b/packages/core/ui/transition/modal-transition.android.ts @@ -1,7 +1,6 @@ import { BackstackEntry } from '../frame'; -import { View } from '../core/view'; import { Transition } from '.'; -import { querySelectorAll } from '../core/view-base'; +import { SharedTransition } from './shared-transition'; export class ModalTransition extends Transition { createAndroidAnimator(transitionType: string) { @@ -17,21 +16,11 @@ export class ModalTransition extends Transition { const currentFragment: androidx.fragment.app.Fragment = currentEntry ? currentEntry.fragment : null; const newFragment: androidx.fragment.app.Fragment = newEntry.fragment; - // 1. Presented view: gather all sharedTransitionTag views - const presentedSharedElements = >querySelectorAll(toPage, 'sharedTransitionTag'); - // console.log('presented sharedTransitionTag total:', presentedSharedElements.length); - - // 2. Presenting view: gather all sharedTransitionTag views - const presentingSharedElements = >querySelectorAll(fromPage, 'sharedTransitionTag'); - // console.log('presenting sharedTransitionTag total:', presentingSharedElements.length); - - // 3. only handle sharedTransitionTag on presenting which match presented - const presentedTags = presentedSharedElements.map((v) => v.sharedTransitionTag); - const presentingViewsToHandle = presentingSharedElements.filter((v) => presentedTags.includes(v.sharedTransitionTag)); + const { sharedElements, presented, presenting } = SharedTransition.getSharedElements(fromPage, toPage); // fragmentTransaction.addSharedElement(); toPage.on('loaded', () => { - presentedSharedElements.forEach((v) => { + presented.forEach((v) => { console.log({ presentedSharedElements: true, nativeView: !!v.nativeView, @@ -45,7 +34,7 @@ export class ModalTransition extends Transition { // }, 2000) }); - presentingSharedElements.forEach((v) => { + presenting.forEach((v) => { console.log({ presentingSharedElements: true, nativeView: !!v.nativeView, @@ -53,7 +42,7 @@ export class ModalTransition extends Transition { }); androidx.core.view.ViewCompat.setTransitionName(v.nativeView, v.sharedTransitionTag); }); - presentingSharedElements.forEach((v) => { + presenting.forEach((v) => { fragmentTransaction.addSharedElement(v.nativeView, v.sharedTransitionTag); }); diff --git a/packages/core/ui/transition/modal-transition.ios.ts b/packages/core/ui/transition/modal-transition.ios.ts index 6f76bec17..f7677866d 100644 --- a/packages/core/ui/transition/modal-transition.ios.ts +++ b/packages/core/ui/transition/modal-transition.ios.ts @@ -74,27 +74,17 @@ class ModalTransitionController extends NSObject implements UIViewControllerAnim transitionContext.containerView.addSubview(owner.presented.view); owner.presented.view.layoutIfNeeded(); - // 1. Presented view: gather all sharedTransitionTag views - const presentedSharedElements = >querySelectorAll(state.toPage, 'sharedTransitionTag'); - // console.log('presented sharedTransitionTag total:', presentedSharedElements.length); - - // 2. Presenting view: gather all sharedTransitionTag views - const presentingSharedElements = >querySelectorAll(state.page, 'sharedTransitionTag'); - // console.log('presenting sharedTransitionTag total:', presentingSharedElements.length); - - // 3. only handle sharedTransitionTag on presenting which match presented - const presentedTags = presentedSharedElements.map((v) => v.sharedTransitionTag); - const presentingViewsToHandle = presentingSharedElements.filter((v) => presentedTags.includes(v.sharedTransitionTag)); + const { sharedElements, presented } = SharedTransition.getSharedElements(state.page, state.toPage); console.log(' '); console.log( `1. Found sharedTransitionTags to animate:`, - presentingViewsToHandle.map((v) => v.sharedTransitionTag) + sharedElements.map((v) => v.sharedTransitionTag) ); console.log(`2. Take snapshots of shared elements and position them based on presenting view:`); - for (const presentingView of presentingViewsToHandle) { + for (const presentingView of sharedElements) { if (!owner.sharedElements) { owner.sharedElements = { presented: [], @@ -108,7 +98,7 @@ class ModalTransitionController extends NSObject implements UIViewControllerAnim // Note: snapshot may be most efficient/simple // console.log('---> ', presentingView.sharedTransitionTag, ': ', presentingSharedElement) - const presentedView = presentedSharedElements.find((v) => v.sharedTransitionTag === presentingView.sharedTransitionTag); + const presentedView = presented.find((v) => v.sharedTransitionTag === presentingView.sharedTransitionTag); const presentedSharedElement = presentedView.ios; const sharedElementSnapshot = UIImageView.alloc().init(); // WithImage(snapshotView(presentedSharedElement)); @@ -214,28 +204,28 @@ class ModalTransitionController extends NSObject implements UIViewControllerAnim }; // starting page properties - owner.presented.view.alpha = typeof state.incomingViewStart?.opacity === 'number' ? state.incomingViewStart?.opacity : 0; + owner.presented.view.alpha = typeof state.toPageStart?.opacity === 'number' ? state.toPageStart?.opacity : 0; - const startX = typeof state.incomingViewStart?.x === 'number' ? state.incomingViewStart?.x : 0; - const startY = typeof state.incomingViewStart?.y === 'number' ? state.incomingViewStart?.y : Screen.mainScreen.heightDIPs; - const startWidth = typeof state.incomingViewStart?.width === 'number' ? state.incomingViewStart?.width : Screen.mainScreen.widthDIPs; - const startHeight = typeof state.incomingViewStart?.height === 'number' ? state.incomingViewStart?.height : Screen.mainScreen.heightDIPs; + const startX = typeof state.toPageStart?.x === 'number' ? state.toPageStart?.x : 0; + const startY = typeof state.toPageStart?.y === 'number' ? state.toPageStart?.y : Screen.mainScreen.heightDIPs; + const startWidth = typeof state.toPageStart?.width === 'number' ? state.toPageStart?.width : Screen.mainScreen.widthDIPs; + const startHeight = typeof state.toPageStart?.height === 'number' ? state.toPageStart?.height : Screen.mainScreen.heightDIPs; owner.presented.view.frame = CGRectMake(startX, startY, startWidth, startHeight); UIView.animateWithDurationDelayUsingSpringWithDampingInitialSpringVelocityOptionsAnimationsCompletion( - typeof state.incomingViewStart?.duration === 'number' ? state.incomingViewStart?.duration / 1000 : DEFAULT_DURATION, + typeof state.toPageStart?.duration === 'number' ? state.toPageStart?.duration / 1000 : DEFAULT_DURATION, 0, 0.5, 3, UIViewAnimationOptions.CurveEaseInOut, () => { // animate page properties to the following: - owner.presented.view.alpha = typeof state.incomingViewEnd?.opacity === 'number' ? state.incomingViewEnd?.opacity : 1; + owner.presented.view.alpha = typeof state.toPageEnd?.opacity === 'number' ? state.toPageEnd?.opacity : 1; - const endX = typeof state.incomingViewEnd?.x === 'number' ? state.incomingViewEnd?.x : 0; - const endY = typeof state.incomingViewEnd?.y === 'number' ? state.incomingViewEnd?.y : 0; - const endWidth = typeof state.incomingViewEnd?.width === 'number' ? state.incomingViewEnd?.width : Screen.mainScreen.widthDIPs; - const endHeight = typeof state.incomingViewEnd?.height === 'number' ? state.incomingViewEnd?.height : Screen.mainScreen.heightDIPs; + const endX = typeof state.toPageEnd?.x === 'number' ? state.toPageEnd?.x : 0; + const endY = typeof state.toPageEnd?.y === 'number' ? state.toPageEnd?.y : 0; + const endWidth = typeof state.toPageEnd?.width === 'number' ? state.toPageEnd?.width : Screen.mainScreen.widthDIPs; + const endHeight = typeof state.toPageEnd?.height === 'number' ? state.toPageEnd?.height : Screen.mainScreen.heightDIPs; owner.presented.view.frame = CGRectMake(endX, endY, endWidth, endHeight); updateFramePresent(); @@ -287,18 +277,18 @@ class ModalTransitionController extends NSObject implements UIViewControllerAnim }; UIView.animateWithDurationDelayUsingSpringWithDampingInitialSpringVelocityOptionsAnimationsCompletion( - typeof state.dismissViewEnd?.duration === 'number' ? state.dismissViewEnd?.duration / 1000 : DEFAULT_DURATION, + typeof state.fromPageEnd?.duration === 'number' ? state.fromPageEnd?.duration / 1000 : DEFAULT_DURATION, 0, 0.5, 3, UIViewAnimationOptions.CurveEaseInOut, () => { - owner.presented.view.alpha = typeof state.dismissViewEnd?.opacity === 'number' ? state.dismissViewEnd?.opacity : 0; + owner.presented.view.alpha = typeof state.fromPageEnd?.opacity === 'number' ? state.fromPageEnd?.opacity : 0; - const endX = typeof state.dismissViewEnd?.x === 'number' ? state.dismissViewEnd?.x : 0; - const endY = typeof state.dismissViewEnd?.y === 'number' ? state.dismissViewEnd?.y : Screen.mainScreen.heightDIPs; - const endWidth = typeof state.dismissViewEnd?.width === 'number' ? state.dismissViewEnd?.width : Screen.mainScreen.widthDIPs; - const endHeight = typeof state.dismissViewEnd?.height === 'number' ? state.dismissViewEnd?.height : Screen.mainScreen.heightDIPs; + const endX = typeof state.fromPageEnd?.x === 'number' ? state.fromPageEnd?.x : 0; + const endY = typeof state.fromPageEnd?.y === 'number' ? state.fromPageEnd?.y : Screen.mainScreen.heightDIPs; + const endWidth = typeof state.fromPageEnd?.width === 'number' ? state.fromPageEnd?.width : Screen.mainScreen.widthDIPs; + const endHeight = typeof state.fromPageEnd?.height === 'number' ? state.fromPageEnd?.height : Screen.mainScreen.heightDIPs; owner.presented.view.frame = CGRectMake(endX, endY, endWidth, endHeight); updateFrameDismiss(); diff --git a/packages/core/ui/transition/page-transition.android.ts b/packages/core/ui/transition/page-transition.android.ts index 3ee67d7c4..5cda7aa6d 100644 --- a/packages/core/ui/transition/page-transition.android.ts +++ b/packages/core/ui/transition/page-transition.android.ts @@ -1,124 +1,67 @@ +import { BackstackEntry } from '../frame'; import { Transition } from '.'; -import { Screen } from '../../platform'; -import lazy from '../../utils/lazy'; - -const screenWidth = lazy(() => Screen.mainScreen.widthPixels); -const screenHeight = lazy(() => Screen.mainScreen.heightPixels); +import { SharedTransition } from './shared-transition'; export class PageTransition extends Transition { - private _direction: string; - - constructor(direction: string, duration: number, curve: any) { - super(duration, curve); - this._direction = direction; + createAndroidAnimator(transitionType: string) { + console.log('HELLO', transitionType); } - public createAndroidAnimator(transitionType: string): android.animation.Animator { - const translationValues = Array.create('float', 2); - switch (this._direction) { - case 'left': - switch (transitionType) { - case Transition.AndroidTransitionType.enter: - translationValues[0] = screenWidth(); - translationValues[1] = 0; - break; - case Transition.AndroidTransitionType.exit: - translationValues[0] = 0; - translationValues[1] = -screenWidth(); - break; - case Transition.AndroidTransitionType.popEnter: - translationValues[0] = -screenWidth(); - translationValues[1] = 0; - break; - case Transition.AndroidTransitionType.popExit: - translationValues[0] = 0; - translationValues[1] = screenWidth(); - break; - } - break; - case 'right': - switch (transitionType) { - case Transition.AndroidTransitionType.enter: - translationValues[0] = -screenWidth(); - translationValues[1] = 0; - break; - case Transition.AndroidTransitionType.exit: - translationValues[0] = 0; - translationValues[1] = screenWidth(); - break; - case Transition.AndroidTransitionType.popEnter: - translationValues[0] = screenWidth(); - translationValues[1] = 0; - break; - case Transition.AndroidTransitionType.popExit: - translationValues[0] = 0; - translationValues[1] = -screenWidth(); - break; - } - break; - case 'top': - switch (transitionType) { - case Transition.AndroidTransitionType.enter: - translationValues[0] = screenHeight(); - translationValues[1] = 0; - break; - case Transition.AndroidTransitionType.exit: - translationValues[0] = 0; - translationValues[1] = -screenHeight(); - break; - case Transition.AndroidTransitionType.popEnter: - translationValues[0] = -screenHeight(); - translationValues[1] = 0; - break; - case Transition.AndroidTransitionType.popExit: - translationValues[0] = 0; - translationValues[1] = screenHeight(); - break; - } - break; - case 'bottom': - switch (transitionType) { - case Transition.AndroidTransitionType.enter: - translationValues[0] = -screenHeight(); - translationValues[1] = 0; - break; - case Transition.AndroidTransitionType.exit: - translationValues[0] = 0; - translationValues[1] = screenHeight(); - break; - case Transition.AndroidTransitionType.popEnter: - translationValues[0] = screenHeight(); - translationValues[1] = 0; - break; - case Transition.AndroidTransitionType.popExit: - translationValues[0] = 0; - translationValues[1] = -screenHeight(); - break; - } - break; - } + test(fragmentTransaction: androidx.fragment.app.FragmentTransaction, currentEntry: BackstackEntry, newEntry: BackstackEntry) { + console.log('HELLO', fragmentTransaction); - let prop; + const fromPage = currentEntry.resolvedPage; + const toPage = newEntry.resolvedPage; - if (this._direction === 'left' || this._direction === 'right') { - prop = 'translationX'; - } else { - prop = 'translationY'; - } + const currentFragment: androidx.fragment.app.Fragment = currentEntry ? currentEntry.fragment : null; + const newFragment: androidx.fragment.app.Fragment = newEntry.fragment; - const animator = android.animation.ObjectAnimator.ofFloat(null, prop, translationValues); - const duration = this.getDuration(); - if (duration !== undefined) { - animator.setDuration(duration); - } - animator.setInterpolator(this.getCurve()); + const { sharedElements, presented, presenting } = SharedTransition.getSharedElements(fromPage, toPage); + // fragmentTransaction.addSharedElement(); - const animatorSet = new android.animation.AnimatorSet(); - animatorSet.play(animator); - return animatorSet; - } + toPage.on('loaded', () => { + presented.forEach((v) => { + console.log({ + presentedSharedElements: true, + nativeView: !!v.nativeView, + sharedTransitionTag: v.sharedTransitionTag, + }); + androidx.core.view.ViewCompat.setTransitionName(v.nativeView, v.sharedTransitionTag); + }); - public toString(): string { - return `${super.toString()} ${this._direction}`; + // setTimeout(() => { + newFragment.startPostponedEnterTransition(); + // }, 2000) + }); + + presenting.forEach((v) => { + console.log({ + presentingSharedElements: true, + nativeView: !!v.nativeView, + sharedTransitionTag: v.sharedTransitionTag, + }); + androidx.core.view.ViewCompat.setTransitionName(v.nativeView, v.sharedTransitionTag); + }); + presenting.forEach((v) => { + fragmentTransaction.addSharedElement(v.nativeView, v.sharedTransitionTag); + }); + + fragmentTransaction.setReorderingAllowed(true); + + const transitionSet = new androidx.transition.TransitionSet(); + transitionSet.setDuration(2000); + transitionSet.addTransition(new androidx.transition.ChangeBounds()); + transitionSet.addTransition(new androidx.transition.ChangeTransform()); + // transitionSet.addTransition(new androidx.transition.ChangeClipBounds()); + + // postpone enter until we call "loaded" on the new page + newFragment.postponeEnterTransition(); + + newFragment.setSharedElementEnterTransition(transitionSet); + newFragment.setSharedElementReturnTransition(transitionSet); + + // newFragment.setSharedElementReturnTransition(new androidx.transition.ChangeBounds()); + // currentFragment.setSharedElementEnterTransition(new androidx.transition.ChangeBounds()); + // currentFragment.setSharedElementReturnTransition(new androidx.transition.ChangeBounds()); } } diff --git a/packages/core/ui/transition/page-transition.ios.ts b/packages/core/ui/transition/page-transition.ios.ts index 5e0c501a7..8e76decf0 100644 --- a/packages/core/ui/transition/page-transition.ios.ts +++ b/packages/core/ui/transition/page-transition.ios.ts @@ -30,30 +30,21 @@ export class PageTransition extends Transition { this.presented = toViewCtrl; console.log('-- Transition present --', this.presented); - transitionContext.containerView.addSubview(this.presented.view); + // transitionContext.containerView.addSubview(this.presented.view); + transitionContext.containerView.insertSubviewAboveSubview(this.presented.view, fromViewCtrl.view); this.presented.view.layoutIfNeeded(); - // 1. Presented view: gather all sharedTransitionTag views - const presentedSharedElements = >querySelectorAll(state.toPage, 'sharedTransitionTag'); - // console.log('presented sharedTransitionTag total:', presentedSharedElements.length); - - // 2. Presenting view: gather all sharedTransitionTag views - const presentingSharedElements = >querySelectorAll(state.page, 'sharedTransitionTag'); - // console.log('presenting sharedTransitionTag total:', presentingSharedElements.length); - - // 3. only handle sharedTransitionTag on presenting which match presented - const presentedTags = presentedSharedElements.map((v) => v.sharedTransitionTag); - const presentingViewsToHandle = presentingSharedElements.filter((v) => presentedTags.includes(v.sharedTransitionTag)); + const { sharedElements, presented } = SharedTransition.getSharedElements(state.page, state.toPage); console.log(' '); console.log( `1. Found sharedTransitionTags to animate:`, - presentingViewsToHandle.map((v) => v.sharedTransitionTag) + sharedElements.map((v) => v.sharedTransitionTag) ); console.log(`2. Take snapshots of shared elements and position them based on presenting view:`); - for (const presentingView of presentingViewsToHandle) { + for (const presentingView of sharedElements) { if (!this.sharedElements) { this.sharedElements = { presented: [], @@ -67,7 +58,7 @@ export class PageTransition extends Transition { // Note: snapshot may be most efficient/simple // console.log('---> ', presentingView.sharedTransitionTag, ': ', presentingSharedElement) - const presentedView = presentedSharedElements.find((v) => v.sharedTransitionTag === presentingView.sharedTransitionTag); + const presentedView = presented.find((v) => v.sharedTransitionTag === presentingView.sharedTransitionTag); const presentedSharedElement = presentedView.ios; const sharedElementSnapshot = UIImageView.alloc().init(); // WithImage(snapshotView(presentedSharedElement)); @@ -116,7 +107,8 @@ export class PageTransition extends Transition { presentingView.opacity = 0; presentedView.opacity = 0; // add snapshot to animate - transitionContext.containerView.addSubview(sharedElementSnapshot); + // transitionContext.containerView.addSubview(sharedElementSnapshot); + transitionContext.containerView.insertSubviewAboveSubview(sharedElementSnapshot, this.presented.view); } const cleanupPresent = () => { @@ -173,28 +165,28 @@ export class PageTransition extends Transition { }; // starting page properties - this.presented.view.alpha = typeof state.incomingViewStart?.opacity === 'number' ? state.incomingViewStart?.opacity : 0; + this.presented.view.alpha = typeof state.toPageStart?.opacity === 'number' ? state.toPageStart?.opacity : 0; - const startX = typeof state.incomingViewStart?.x === 'number' ? state.incomingViewStart?.x : Screen.mainScreen.widthDIPs; - const startY = typeof state.incomingViewStart?.y === 'number' ? state.incomingViewStart?.y : 0; - const startWidth = typeof state.incomingViewStart?.width === 'number' ? state.incomingViewStart?.width : Screen.mainScreen.widthDIPs; - const startHeight = typeof state.incomingViewStart?.height === 'number' ? state.incomingViewStart?.height : Screen.mainScreen.heightDIPs; + const startX = typeof state.toPageStart?.x === 'number' ? state.toPageStart?.x : Screen.mainScreen.widthDIPs; + const startY = typeof state.toPageStart?.y === 'number' ? state.toPageStart?.y : 0; + const startWidth = typeof state.toPageStart?.width === 'number' ? state.toPageStart?.width : Screen.mainScreen.widthDIPs; + const startHeight = typeof state.toPageStart?.height === 'number' ? state.toPageStart?.height : Screen.mainScreen.heightDIPs; this.presented.view.frame = CGRectMake(startX, startY, startWidth, startHeight); UIView.animateWithDurationDelayUsingSpringWithDampingInitialSpringVelocityOptionsAnimationsCompletion( - typeof state.incomingViewStart?.duration === 'number' ? state.incomingViewStart?.duration / 1000 : DEFAULT_DURATION, + typeof state.toPageStart?.duration === 'number' ? state.toPageStart?.duration / 1000 : DEFAULT_DURATION, 0, 0.5, 3, UIViewAnimationOptions.CurveEaseInOut, () => { // animate page properties to the following: - this.presented.view.alpha = typeof state.incomingViewEnd?.opacity === 'number' ? state.incomingViewEnd?.opacity : 1; + this.presented.view.alpha = typeof state.toPageEnd?.opacity === 'number' ? state.toPageEnd?.opacity : 1; - const endX = typeof state.incomingViewEnd?.x === 'number' ? state.incomingViewEnd?.x : 0; - const endY = typeof state.incomingViewEnd?.y === 'number' ? state.incomingViewEnd?.y : 0; - const endWidth = typeof state.incomingViewEnd?.width === 'number' ? state.incomingViewEnd?.width : Screen.mainScreen.widthDIPs; - const endHeight = typeof state.incomingViewEnd?.height === 'number' ? state.incomingViewEnd?.height : Screen.mainScreen.heightDIPs; + const endX = typeof state.toPageEnd?.x === 'number' ? state.toPageEnd?.x : 0; + const endY = typeof state.toPageEnd?.y === 'number' ? state.toPageEnd?.y : 0; + const endWidth = typeof state.toPageEnd?.width === 'number' ? state.toPageEnd?.width : Screen.mainScreen.widthDIPs; + const endHeight = typeof state.toPageEnd?.height === 'number' ? state.toPageEnd?.height : Screen.mainScreen.heightDIPs; this.presented.view.frame = CGRectMake(endX, endY, endWidth, endHeight); updateFramePresent(); @@ -209,6 +201,8 @@ export class PageTransition extends Transition { // this.presented = fromViewCtrl; console.log('-- Transition dismiss --', this.presented); + transitionContext.containerView.insertSubviewBelowSubview(toViewCtrl.view, fromViewCtrl.view); + // console.log('transitionContext.containerView.subviews.count:', transitionContext.containerView.subviews.count); console.log(' '); @@ -225,11 +219,13 @@ export class PageTransition extends Transition { for (const p of this.sharedElements.presenting) { p.snapshot.alpha = p.endOpacity; transitionContext.containerView.addSubview(p.snapshot); + // transitionContext.containerView.insertSubviewBelowSubview(p.snapshot, fromViewCtrl.view); } const cleanupDismiss = () => { for (const presenting of this.sharedElements.presenting) { presenting.view.opacity = presenting.startOpacity; + presenting.snapshot.removeFromSuperview(); } SharedTransition.finishState(this.id); transitionContext.completeTransition(true); @@ -247,18 +243,18 @@ export class PageTransition extends Transition { }; UIView.animateWithDurationDelayUsingSpringWithDampingInitialSpringVelocityOptionsAnimationsCompletion( - typeof state.dismissViewEnd?.duration === 'number' ? state.dismissViewEnd?.duration / 1000 : DEFAULT_DURATION, + typeof state.fromPageEnd?.duration === 'number' ? state.fromPageEnd?.duration / 1000 : DEFAULT_DURATION, 0, 0.5, 3, UIViewAnimationOptions.CurveEaseInOut, () => { - this.presented.view.alpha = typeof state.dismissViewEnd?.opacity === 'number' ? state.dismissViewEnd?.opacity : 0; + this.presented.view.alpha = typeof state.fromPageEnd?.opacity === 'number' ? state.fromPageEnd?.opacity : 0; - const endX = typeof state.dismissViewEnd?.x === 'number' ? state.dismissViewEnd?.x : Screen.mainScreen.widthDIPs; - const endY = typeof state.dismissViewEnd?.y === 'number' ? state.dismissViewEnd?.y : 0; - const endWidth = typeof state.dismissViewEnd?.width === 'number' ? state.dismissViewEnd?.width : Screen.mainScreen.widthDIPs; - const endHeight = typeof state.dismissViewEnd?.height === 'number' ? state.dismissViewEnd?.height : Screen.mainScreen.heightDIPs; + const endX = typeof state.fromPageEnd?.x === 'number' ? state.fromPageEnd?.x : Screen.mainScreen.widthDIPs; + const endY = typeof state.fromPageEnd?.y === 'number' ? state.fromPageEnd?.y : 0; + const endWidth = typeof state.fromPageEnd?.width === 'number' ? state.fromPageEnd?.width : Screen.mainScreen.widthDIPs; + const endHeight = typeof state.fromPageEnd?.height === 'number' ? state.fromPageEnd?.height : Screen.mainScreen.heightDIPs; this.presented.view.frame = CGRectMake(endX, endY, endWidth, endHeight); updateFrameDismiss(); diff --git a/packages/core/ui/transition/shared-transition.ts b/packages/core/ui/transition/shared-transition.ts index 75429296e..829b99810 100644 --- a/packages/core/ui/transition/shared-transition.ts +++ b/packages/core/ui/transition/shared-transition.ts @@ -1,5 +1,6 @@ import type { Transition } from '.'; -// import type { View } from '../../core/view'; +import { querySelectorAll } from '../core/view-base'; +import type { View } from '../core/view'; import type { Page } from '../page'; export const DEFAULT_DURATION = 0.35; @@ -18,17 +19,17 @@ export interface SharedTransitionConfig { */ instance?: Transition; /** - * View settings to start your transition from. + * View settings to start your transition. */ - incomingViewStart?: SharedTransitionPageProperties; + toPageStart?: SharedTransitionPageProperties; /** - * View settings to animate your page to. + * View settings to end your transition. */ - incomingViewEnd?: SharedTransitionPageProperties; + toPageEnd?: SharedTransitionPageProperties; /** - * View settings to animate your page to when dismissed. + * View settings to end your transition for the 'from' (aka outgoing or dismissed) page. */ - dismissViewEnd?: SharedTransitionPageProperties; + fromPageEnd?: SharedTransitionPageProperties; } export interface SharedTransitionState extends SharedTransitionConfig { id?: number; @@ -46,6 +47,12 @@ type SharedTransitionPageProperties = { */ duration?: number; }; +/** + * Shared Element Transition (experimental) + * + * no + * Note: some APIs may change in subsequent releases + */ export class SharedTransition { static configure(options: SharedTransitionConfig): Transition { SharedTransition.updateState({ @@ -92,4 +99,28 @@ export class SharedTransition { SharedTransition.currentStack.splice(index, 1); } } + static getSharedElements( + fromPage: Page, + toPage: Page + ): { + sharedElements: Array; + presented: Array; + presenting: Array; + } { + // 1. Presented view: gather all sharedTransitionTag views + const presentedSharedElements = >querySelectorAll(toPage, 'sharedTransitionTag'); + // console.log('presented sharedTransitionTag total:', presentedSharedElements.length); + + // 2. Presenting view: gather all sharedTransitionTag views + const presentingSharedElements = >querySelectorAll(fromPage, 'sharedTransitionTag'); + // console.log('presenting sharedTransitionTag total:', presentingSharedElements.length); + + // 3. only handle sharedTransitionTag on presenting which match presented + const presentedTags = presentedSharedElements.map((v) => v.sharedTransitionTag); + return { + sharedElements: presentingSharedElements.filter((v) => presentedTags.includes(v.sharedTransitionTag)), + presented: presentedSharedElements, + presenting: presentingSharedElements, + }; + } }