diff options
Diffstat (limited to 'src/client/views')
| -rw-r--r-- | src/client/views/PinFuncs.ts | 2 | ||||
| -rw-r--r-- | src/client/views/PropertiesView.tsx | 2 | ||||
| -rw-r--r-- | src/client/views/animationtimeline/Timeline.tsx | 2 | ||||
| -rw-r--r-- | src/client/views/nodes/DocumentView.tsx | 18 | ||||
| -rw-r--r-- | src/client/views/nodes/trails/PresBox.tsx | 50 | ||||
| -rw-r--r-- | src/client/views/nodes/trails/PresEnums.ts | 2 | ||||
| -rw-r--r-- | src/client/views/nodes/trails/SlideEffect.scss | 2 | ||||
| -rw-r--r-- | src/client/views/nodes/trails/SlideEffect.tsx | 402 | ||||
| -rw-r--r-- | src/client/views/nodes/trails/SpringUtils.ts | 2 |
9 files changed, 120 insertions, 362 deletions
diff --git a/src/client/views/PinFuncs.ts b/src/client/views/PinFuncs.ts index 3d998ecaf..430455644 100644 --- a/src/client/views/PinFuncs.ts +++ b/src/client/views/PinFuncs.ts @@ -54,7 +54,7 @@ export function PinDocView(pinDocIn: Doc, pinProps: PinProps, targetDoc: Doc) { pinDoc.config_width = NumCast(targetDoc.width); pinDoc.config_height = NumCast(targetDoc.height); } - if (pinProps.pinAudioPlay) pinDoc.presPlayAudio = true; + if (pinProps.pinAudioPlay) pinDoc.presentation_playAudio = true; if (pinProps.pinData) { pinDoc.config_pinData = pinProps.pinData.scrollable || diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index df4ed98ac..024db82a4 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -1487,7 +1487,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps onChange={e => this.changeAnimationBehavior(e.currentTarget.value)} value={StrCast(this.sourceAnchor?.followLinkAnimEffect, 'default')}> <option value="default">Default</option> - {[PresEffect.None, PresEffect.Zoom, PresEffect.Lightspeed, PresEffect.Fade, PresEffect.Flip, PresEffect.Rotate, PresEffect.Bounce, PresEffect.Roll].map(effect => ( + {[PresEffect.None, PresEffect.Expand, PresEffect.Lightspeed, PresEffect.Fade, PresEffect.Flip, PresEffect.Rotate, PresEffect.Bounce, PresEffect.Roll].map(effect => ( <option key={effect.toString()} value={effect.toString()}> {effect.toString()} </option> diff --git a/src/client/views/animationtimeline/Timeline.tsx b/src/client/views/animationtimeline/Timeline.tsx index c4d35330b..d9ff21035 100644 --- a/src/client/views/animationtimeline/Timeline.tsx +++ b/src/client/views/animationtimeline/Timeline.tsx @@ -547,7 +547,7 @@ export class Timeline extends ObservableReactComponent<FieldViewProps> { <div key="timeline_info" className="info-container" onPointerDown={this.onPanDown} ref={this._infoContainer} onWheel={this.onWheelZoom}> {this.drawTicks()} <div key="timeline_scrubber" className="scrubber" style={{ transform: `translate(${this._currentBarX}px)` }}> - <div key="timeline_scrubberhead" className="scrubberhead" onPointerDown={this.onScrubberDown}></div> + <div key="timeline_scrubberhead" className="scrubberhead" onPointerDown={this.onScrubberDown} /> </div> <div key="timeline_trackbox" className="trackbox" ref={this._trackbox} style={{ width: `${this._totalLength}px` }}> {[...this.children, this._props.Document].map(doc => ( diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 6f9e14c1b..c59cd0ee4 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -934,7 +934,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document borderRadius: this.borderRounding, pointerEvents: this._pointerEvents === 'visiblePainted' ? 'none' : this._pointerEvents, // visible painted means that the underlying doc contents are irregular and will process their own pointer events (otherwise, the contents are expected to fill the entire doc view box so we can handle pointer events here) }}> - {this._componentView?.isUnstyledView?.() ? renderDoc : DocumentViewInternal.AnimationEffect(renderDoc, this.Document[Animation], this.Document)} + {this._componentView?.isUnstyledView?.() || this.Document.type === DocumentType.CONFIG ? renderDoc : DocumentViewInternal.AnimationEffect(renderDoc, this.Document[Animation], this.Document)} {borderPath?.jsx} </div> ); @@ -958,7 +958,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document duration: Cast(presEffectDoc?.presentation_transition, 'number', Cast(presEffectDoc?.followLinkTransitionTime, 'number', null)), }; - const timing = StrCast(presEffectDoc?.presEffectTiming); + const timing = StrCast(presEffectDoc?.presentation_effectTiming); let timingConfig: SpringSettings | undefined; if (timing) { timingConfig = JSON.parse(timing); @@ -976,13 +976,13 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document } switch (StrCast(presEffectDoc?.presentation_effect, StrCast(presEffectDoc?.followLinkAnimEffect))) { - case PresEffect.Zoom: return <SpringAnimation doc={root} dir={dir} presEffect={PresEffect.Zoom} tension={timingConfig.stiffness} friction={timingConfig.damping} mass={timingConfig.mass}>{renderDoc}</SpringAnimation> - // case PresEffect.Fade: return <SlideEffect doc={root} dir={dir} presEffect={PresEffect.Fade} tension={timingConfig.stiffness} friction={timingConfig.damping} mass={timingConfig.mass}>{renderDoc}</SlideEffect> + case PresEffect.Expand: return <SpringAnimation doc={root} startOpacity={0} dir={dir} presEffect={PresEffect.Expand} springSettings={timingConfig}>{renderDoc}</SpringAnimation> + case PresEffect.Flip: return <SpringAnimation doc={root} startOpacity={0} dir={dir} presEffect={PresEffect.Flip} springSettings={timingConfig}>{renderDoc}</SpringAnimation> + case PresEffect.Rotate: return <SpringAnimation doc={root} startOpacity={0} dir={dir} presEffect={PresEffect.Rotate} springSettings={timingConfig}>{renderDoc}</SpringAnimation> + case PresEffect.Bounce: return <SpringAnimation doc={root} startOpacity={0} dir={dir} presEffect={PresEffect.Bounce} springSettings={timingConfig}>{renderDoc}</SpringAnimation> + case PresEffect.Roll: return <SpringAnimation doc={root} startOpacity={0} dir={dir} presEffect={PresEffect.Roll} springSettings={timingConfig}>{renderDoc}</SpringAnimation> + // case PresEffect.Fade: return <SlideEffect doc={root} dir={dir} presEffect={PresEffect.Fade} tension={timingConfig.stiffness} friction={timingConfig.damping} mass={timingConfig.mass}>{renderDoc}</SlideEffect> case PresEffect.Fade: return <Fade {...effectProps}>{renderDoc}</Fade> - case PresEffect.Flip: return <SpringAnimation doc={root} dir={dir} presEffect={PresEffect.Flip} tension={timingConfig.stiffness} friction={timingConfig.damping} mass={timingConfig.mass}>{renderDoc}</SpringAnimation> - case PresEffect.Rotate: return <SpringAnimation doc={root} dir={dir} presEffect={PresEffect.Rotate} tension={timingConfig.stiffness} friction={timingConfig.damping} mass={timingConfig.mass}>{renderDoc}</SpringAnimation> - case PresEffect.Bounce: return <SpringAnimation doc={root} dir={dir} presEffect={PresEffect.Bounce} tension={timingConfig.stiffness} friction={timingConfig.damping} mass={timingConfig.mass}>{renderDoc}</SpringAnimation> - case PresEffect.Roll: return <SpringAnimation doc={root} dir={dir} presEffect={PresEffect.Roll} tension={timingConfig.stiffness} friction={timingConfig.damping} mass={timingConfig.mass}>{renderDoc}</SpringAnimation> // keep as preset, doesn't really make sense with spring config case PresEffect.Lightspeed: return <JackInTheBox {...effectProps}>{renderDoc}</JackInTheBox>; case PresEffect.None: @@ -1416,7 +1416,7 @@ export class DocumentView extends DocComponent<DocumentViewProps>() { <div className="webBox-textHighlight"> <ObserverJsxParser autoCloseVoidElements key={42} onError={(e: any) => console.log('PARSE error', e)} renderInWrapper={false} jsx={StrCast(this._htmlOverlayText)} /> </div>, - { ...(this._htmlOverlayEffect ?? {}), presentation_effect: effect ?? PresEffect.Zoom } as any as Doc, + { ...(this._htmlOverlayEffect ?? {}), presentation_effect: effect ?? PresEffect.Expand } as any as Doc, this.Document )} </div> diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index 69d03ac2e..101f28ae7 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -185,7 +185,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { @computed get currCPoints() { - const strPoints = this.activeItem.presEaseFunc ? StrCast(this.activeItem.presEaseFunc) : 'ease'; + const strPoints = this.activeItem.presentation_easeFunc ? StrCast(this.activeItem.presentation_easeFunc) : 'ease'; return EaseFuncToPoints(strPoints); } @@ -858,9 +858,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { effect: activeItem, noSelect: true, openLocation: targetDoc.type === DocumentType.PRES ? ((OpenWhere.replace + ':' + PresBox.PanelName) as OpenWhere) : OpenWhere.addLeft, - easeFunc: StrCast(activeItem.presEaseFunc, 'ease') as any, + easeFunc: StrCast(activeItem.presentation_easeFunc, 'ease') as any, zoomTextSelections: BoolCast(activeItem.presentation_zoomText), - playAudio: BoolCast(activeItem.presPlayAudio), + playAudio: BoolCast(activeItem.presentation_playAudio), playMedia: activeItem.presentation_mediaStart === 'auto', }; if (activeItem.presentation_openInLightbox) { @@ -1575,16 +1575,16 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { @undoBatch updateEaseFunc = (activeItem: Doc) => { - activeItem.presEaseFunc = activeItem.presEaseFunc === 'linear' ? 'ease' : 'linear'; + activeItem.presentation_easeFunc = activeItem.presentation_easeFunc === 'linear' ? 'ease' : 'linear'; this.selectedArray.forEach(doc => { - doc.presEaseFunc = activeItem.presEaseFunc; + doc.presentation_easeFunc = activeItem.presentation_easeFunc; }); }; setEaseFunc = (activeItem: Doc, easeFunc: string) => { - activeItem.presEaseFunc = easeFunc; + activeItem.presentation_easeFunc = easeFunc; this.selectedArray.forEach(doc => { - doc.presEaseFunc = activeItem.presEaseFunc; + doc.presentation_easeFunc = activeItem.presentation_easeFunc; }); }; @@ -1602,9 +1602,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { @undoBatch updateEffectTiming = (activeItem: Doc, timing: SpringSettings) => { - activeItem.presEffectTiming = JSON.stringify(timing); + activeItem.presentation_effectTiming = JSON.stringify(timing); this.selectedArray.forEach(doc => { - doc.presEffectTiming = activeItem.presEffectTiming; + doc.presentation_effectTiming = activeItem.presentation_effectTiming; }); }; @@ -1829,7 +1829,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { @computed get transitionDropdown() { const { activeItem } = this; // Retrieving spring timing properties - const timing = StrCast(activeItem.presEffectTiming); + const timing = StrCast(activeItem.presentation_effectTiming); let timingConfig: SpringSettings | undefined; if (timing) { timingConfig = JSON.parse(timing); @@ -1847,8 +1847,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { if (activeItem && this.targetDoc) { const transitionSpeed = activeItem.presentation_transition ? NumCast(activeItem.presentation_transition) / 1000 : 0.5; const zoom = NumCast(activeItem.config_zoom, 1) * 100; - const effect = StrCast(activeItem.presentation_effect) ? StrCast(activeItem.presentation_effect) : PresEffect.None; - const direction = StrCast(activeItem.presentation_effectDirection); + const effect = StrCast(activeItem.presentation_effect) ? (StrCast(activeItem.presentation_effect) as any as PresEffect) : PresEffect.None; + const direction = StrCast(activeItem.presentation_effectDirection) as PresEffectDirection; return ( <> @@ -1876,7 +1876,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { /> <IconButton type={Type.TERT} - color={this.isRecording ? '#2bcaff' : StrCast(Doc.UserDoc().userVariantColor)} + color={this.isRecording ? '#2bcaff' : SnappingManager.userVariantColor} tooltip="Record" icon={<BiMicrophone size="16px" />} onClick={() => { @@ -1894,7 +1894,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { type={Type.TERT} icon={this.isLoading ? <ReactLoading type="spin" color="#ffffff" width={20} height={20} /> : <AiOutlineSend />} iconPlacement="right" - color={StrCast(Doc.UserDoc().userVariantColor)} + color={SnappingManager.userVariantColor} onClick={() => { this.stopDictation(); this.customizeWithGPT(this.chatInput); @@ -1919,7 +1919,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { > Movement <Dropdown - color={StrCast(Doc.UserDoc().userColor)} + color={SnappingManager.userColor} formLabel="Movement" closeOnSelect items={movementItems} @@ -1951,11 +1951,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { </div> {/* Easing function */} <Dropdown - color={StrCast(Doc.UserDoc().userColor)} + color={SnappingManager.userColor} formLabel="Easing Function" closeOnSelect items={easeItems} - selectedVal={this.activeItem.presEaseFunc ? (StrCast(this.activeItem.presEaseFunc).startsWith('cubic') ? 'custom' : StrCast(this.activeItem.presEaseFunc)) : 'ease'} + selectedVal={this.activeItem.presentation_easeFunc ? (StrCast(this.activeItem.presentation_easeFunc).startsWith('cubic') ? 'custom' : StrCast(this.activeItem.presentation_easeFunc)) : 'ease'} setSelectedVal={val => { if (typeof val === 'string') { if (val !== 'custom') { @@ -2017,7 +2017,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { type={Type.TERT} icon={this.isLoading ? <ReactLoading type="spin" color="#ffffff" width={20} height={20} /> : <AiOutlineSend />} iconPlacement="right" - color={StrCast(Doc.UserDoc().userVariantColor)} + color={SnappingManager.userVariantColor} onClick={this.customizeAnimations} /> </div> @@ -2053,7 +2053,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { mass: elem.mass, }); }}> - <SlideEffect dir={elem.direction as PresEffectDirection} presEffect={elem.effect as PresEffect} tension={elem.stiffness} friction={elem.damping} mass={elem.mass} infinite> + <SlideEffect dir={elem.direction} presEffect={elem.effect} springSettings={elem} infinite> <div className="presBox-effect-demo-box" style={{ backgroundColor: springPreviewColors[i] }} /> </SlideEffect> </div> @@ -2062,7 +2062,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { </div> {/* Effect dropdown */} <Dropdown - color={StrCast(Doc.UserDoc().userColor)} + color={SnappingManager.userColor} formLabel="Slide Effect" closeOnSelect items={effectItems} @@ -2126,7 +2126,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { {effect !== PresEffect.Lightspeed && ( <> <Dropdown - color={StrCast(Doc.UserDoc().userColor)} + color={SnappingManager.userColor} formLabel="Effect Timing" closeOnSelect items={effectTimings} @@ -2208,7 +2208,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { Preview Effect <div className="presBox-option-block presBox-option-center"> <div className="presBox-effect-container"> - <SlideEffect dir={direction as PresEffectDirection} presEffect={effect as PresEffect} tension={timingConfig.stiffness} friction={timingConfig.damping} mass={timingConfig.mass} infinite> + <SlideEffect dir={direction} presEffect={effect} springSettings={timingConfig} infinite> <div className="presBox-effect-demo-box" style={{ backgroundColor: springPreviewColors[0] }} /> </SlideEffect> </div> @@ -2224,9 +2224,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { <Toggle formLabel="Play Audio Annotation" toggleType={ToggleType.SWITCH} - toggleStatus={BoolCast(activeItem.presPlayAudio)} + toggleStatus={BoolCast(activeItem.presentation_playAudio)} onClick={() => { - activeItem.presPlayAudio = !BoolCast(activeItem.presPlayAudio); + activeItem.presentation_playAudio = !BoolCast(activeItem.presentation_playAudio); }} color={SnappingManager.userColor} /> @@ -2239,7 +2239,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { }} color={SnappingManager.userColor} /> - <Button text="Apply to all" type={Type.TERT} color={StrCast(Doc.UserDoc().userVariantColor)} onClick={() => this.applyTo(this.childDocs)} /> + <Button text="Apply to all" type={Type.TERT} color={SnappingManager.userVariantColor} onClick={() => this.applyTo(this.childDocs)} /> </div> </div> </> diff --git a/src/client/views/nodes/trails/PresEnums.ts b/src/client/views/nodes/trails/PresEnums.ts index 564829d54..67cad9c5d 100644 --- a/src/client/views/nodes/trails/PresEnums.ts +++ b/src/client/views/nodes/trails/PresEnums.ts @@ -7,7 +7,7 @@ export enum PresMovement { } export enum PresEffect { - Zoom = 'Zoom', + Expand = 'Expand', Lightspeed = 'Lightspeed', Fade = 'Fade in', Flip = 'Flip', diff --git a/src/client/views/nodes/trails/SlideEffect.scss b/src/client/views/nodes/trails/SlideEffect.scss index cc851354e..aa2e5bbd9 100644 --- a/src/client/views/nodes/trails/SlideEffect.scss +++ b/src/client/views/nodes/trails/SlideEffect.scss @@ -8,7 +8,7 @@ .flip-side { position: absolute; will-change: transform, opacity; - backface-visibility: hidden; + // backface-visibility: hidden; } .flip-front { diff --git a/src/client/views/nodes/trails/SlideEffect.tsx b/src/client/views/nodes/trails/SlideEffect.tsx index 03cd88f45..00039e3cb 100644 --- a/src/client/views/nodes/trails/SlideEffect.tsx +++ b/src/client/views/nodes/trails/SlideEffect.tsx @@ -5,358 +5,116 @@ import { Doc } from '../../../../fields/Doc'; import { NumCast } from '../../../../fields/Types'; import { PresEffect, PresEffectDirection } from './PresEnums'; import './SlideEffect.scss'; +import { emptyFunction } from '../../../../Utils'; interface SlideEffectProps { - // pass in doc to extract width, height, bg - doc?: Doc; + doc?: Doc; // pass in doc to extract width, height, bg dir: PresEffectDirection; presEffect: PresEffect; - // stiffness (figma) = tension (react-spring) - tension: number; - // damping (figma) = friction (react-spring) - friction: number; - mass: number; + springSettings: { + stiffness: number; + damping: number; + mass: number; + }; children: React.ReactNode; infinite?: boolean; + startOpacity?: number; // set to zero to linearly fade in while animating } const DEFAULT_WIDTH = 40; const PREVIEW_OFFSET = 60; const ACTUAL_OFFSET = 200; -const infiniteOptions = { - loop: true, - delay: 500, -}; /** * This component wraps around the doc to create an effect animation, and also wraps the preview animations * for the effects as well. */ -export default function SpringAnimation({ doc, dir, friction, tension, mass, presEffect, children, infinite }: SlideEffectProps) { - const [springs, api] = useSpring( - () => ({ - from: { - x: 0, - y: 0, - opacity: 0, - scale: 1, - }, - config: { - tension, - friction, - mass, - }, - onStart: () => {}, - onRest: () => {}, - }), - [tension, friction, mass] - ); - const [ref, inView] = useInView({ - once: true, - }); - - const zoomConfig = { - from: { - scale: 0, - x: 0, - y: 0, - opacity: 1, - }, - to: { - scale: 1, - x: 0, - y: 0, - opacity: 1, - config: { - tension: tension, - friction: friction, - mass: mass, - }, - }, +export default function SpringAnimation({ doc, dir, springSettings, presEffect, children, infinite, startOpacity }: SlideEffectProps) { + const expandConfig = { + to: { scale: 1, x: 0, y: 0 }, + from: { scale: 0, x: 0, y: 0 }, }; - const fadeConfig = { - from: { - opacity: 0, - scale: 1, - x: 0, - y: 0, - }, - to: { - opacity: 1, - scale: 1, - x: 0, - y: 0, - config: { - tension: tension, - friction: friction, - mass: mass, - }, - }, + to: { x: 0, y: 0 }, + from: { x: 0, y: 0 }, }; - const rotateConfig = { - from: { - x: 0, - }, - to: { - x: 360, - config: { - tension: tension, - friction: friction, - mass: mass, - }, - }, + to: { x: 360, y: 0 }, + from: { x: 0, y: 0 }, }; - - const getBounceConfigFrom = () => { - switch (dir) { - case PresEffectDirection.Left: - return { - from: { - opacity: 0, - x: infinite ? -PREVIEW_OFFSET : -ACTUAL_OFFSET, - y: 0, - }, - }; - case PresEffectDirection.Right: - return { - from: { - opacity: 0, - x: infinite ? PREVIEW_OFFSET : ACTUAL_OFFSET, - y: 0, - }, - }; - case PresEffectDirection.Top: - return { - from: { - opacity: 0, - x: 0, - y: infinite ? -PREVIEW_OFFSET : -ACTUAL_OFFSET, - }, - }; - case PresEffectDirection.Bottom: - return { - from: { - opacity: 0, - x: 0, - y: infinite ? PREVIEW_OFFSET : ACTUAL_OFFSET, - }, - }; - default: - // no movement for center - return { - from: { - opacity: 0, - x: 0, - y: 0, - }, - }; - } - }; - - const bounceConfig = { - ...getBounceConfigFrom(), - to: [ - { - opacity: 1, - x: 0, - y: 0, - config: { - tension: tension, - friction: friction, - mass: mass, - }, - }, - ], - }; - const flipConfig = { - from: { - x: 0, - }, - to: { - x: 180, - config: { - tension: tension, - friction: friction, - mass: mass, - }, - }, + to: { x: 180, y: 0 }, + from: { x: 0, y: 0 }, }; - - // only left and right for now - const getRollConfigFrom = () => { - switch (dir) { - case PresEffectDirection.Left: - return { - from: { - opacity: 0, - x: -100, - y: -120, - }, - }; - case PresEffectDirection.Right: - return { - from: { - opacity: 0, - x: 100, - y: 120, - }, - }; - case PresEffectDirection.Top: - return { - from: { - opacity: 0, - x: -100, - y: -120, - }, - }; - case PresEffectDirection.Bottom: - return { - from: { - opacity: 0, - x: -100, - y: -120, - }, - }; - default: - // no movement for center - return { - from: { - opacity: 0, - x: 0, - y: 0, - }, - }; - } + const bounceConfig = { + to: { x: 0, y: 0 }, + from: (() => { + const offset = infinite ? PREVIEW_OFFSET : ACTUAL_OFFSET; + switch (dir) { + case PresEffectDirection.Left: return { x: -offset, y: 0, }; + case PresEffectDirection.Right: return { x: offset, y: 0, }; + case PresEffectDirection.Top: return { x: 0, y: -offset, }; + case PresEffectDirection.Bottom:return { x: 0, y: offset, }; + default: return { x: 0, y: 0, }; // no movement for center + }})(), // prettier-ignore }; - const rollConfig = { - ...getRollConfigFrom(), - to: { - opacity: 1, - x: 0, - y: 0, - config: { - tension: tension, - friction: friction, - mass: mass, - }, - }, + to: { x: 0, y: 0 }, + from: (() => { + switch (dir) { + case PresEffectDirection.Left: return { x: -100, y: -120, }; + case PresEffectDirection.Right: return { x: 100, y: 120, }; + case PresEffectDirection.Top: return { x: -100, y: -120, }; + case PresEffectDirection.Bottom: return { x: -100, y: -120, }; + default: return { x: 0, y: 0, }; // no movement for center + }})(), // prettier-ignore }; - // Switch animation depending on slide effect - const startAnimation = () => { - api.stop(); - let config: any = zoomConfig; + // prettier-ignore + const effectConfig = (() => { switch (presEffect) { - case PresEffect.Bounce: - config = bounceConfig; - break; - case PresEffect.Zoom: - config = zoomConfig; - break; - case PresEffect.Rotate: - config = rotateConfig; - break; - case PresEffect.Fade: - config = fadeConfig; - break; - case PresEffect.Flip: - config = flipConfig; - break; - case PresEffect.Roll: - config = rollConfig; - break; - case PresEffect.Lightspeed: - break; - default: - break; - } - - if (infinite) { - config = { ...config, ...infiniteOptions }; - } + case PresEffect.Fade: return fadeConfig; + case PresEffect.Bounce: return bounceConfig; + case PresEffect.Rotate: return rotateConfig; + case PresEffect.Flip: return flipConfig; + case PresEffect.Roll: return rollConfig; + case PresEffect.Lightspeed: return { from: {}, to: {} }; + case PresEffect.Expand: + default: return expandConfig; + } // prettier-ignore + })(); - api.start(config); - }; - - const getRenderDoc = () => { - switch (presEffect) { - case PresEffect.Rotate: - return ( - <animated.div ref={ref} style={{ transform: to(springs.x, val => `rotate(${val}deg)`) }}> - {children} - </animated.div> - ); - case PresEffect.Flip: - return ( - // Pass in doc dimensions - <div className="flip-container" ref={ref}> - {dir === PresEffectDirection.Bottom || dir === PresEffectDirection.Top ? ( - <> - <animated.div - className="flip-side flip-back" - style={{ - transform: to(springs.x, val => `perspective(600px) rotateX(${val}deg)`), - width: doc ? NumCast(doc.width) : DEFAULT_WIDTH, - height: doc ? NumCast(doc.height) : DEFAULT_WIDTH, - backgroundColor: infinite ? '#a825ff' : 'rgb(223, 223, 223);', - }} - /> - <animated.div - className="flip-side flip-front" - style={{ transform: to(springs.x, val => `perspective(600px) rotateX(${val}deg)`), rotateX: '180deg', width: doc ? NumCast(doc.width) : DEFAULT_WIDTH, height: doc ? NumCast(doc.height) : DEFAULT_WIDTH }}> - {children} - </animated.div> - </> - ) : ( - <> - <animated.div - className="flip-side flip-back" - style={{ transform: to(springs.x, val => `perspective(600px) rotateY(${val}deg)`), width: doc ? NumCast(doc.width) : DEFAULT_WIDTH, height: doc ? NumCast(doc.height) : DEFAULT_WIDTH }} - /> - <animated.div - className="flip-side flip-front" - style={{ transform: to(springs.x, val => `perspective(600px) rotateY(${val}deg)`), rotateY: '180deg', width: doc ? NumCast(doc.width) : DEFAULT_WIDTH, height: doc ? NumCast(doc.height) : DEFAULT_WIDTH }}> - {children} - </animated.div> - </> - )} - </div> - ); - case PresEffect.Roll: - return ( - <animated.div ref={ref} style={{ opacity: springs.opacity, transform: to([springs.x, springs.y], (val, val2) => `translate3d(${val}%, 0, 0) rotate3d(0, 0, 1, ${val2}deg)`) }}> - {children} - </animated.div> - ); - default: - return ( - <animated.div - ref={ref} - style={{ - ...springs, - }}> - {children} - </animated.div> - ); - } - }; - - useEffect(() => { - if (infinite || !inView) return; - setTimeout(() => { - startAnimation(); - }, 100); - }, [inView]); + const [springs, api] = useSpring( + () => ({ + to: { ...effectConfig.to, opacity: 1 }, + from: { ...effectConfig.from, opacity: startOpacity ?? 1 }, + config: { tension: springSettings.stiffness, friction: springSettings.damping, mass: springSettings.mass }, + onStart: emptyFunction, + onRest: emptyFunction, + }), + [springSettings] + ); + const [ref, inView] = useInView({ + once: true, + }); useEffect(() => { - if (infinite) { - startAnimation(); + if (inView) { + api.start({ loop: infinite, delay: infinite ? 500 : 0 }); } - }, [presEffect, tension, friction, mass]); - - return <div>{getRenderDoc()}</div>; + }, [inView]); + const animatedDiv = (style: any) => ( + <animated.div ref={ref} style={{ ...style, opacity: to(springs.opacity, val => `${val}`) }}> + {children} + </animated.div> + ); + const [width, height] = [NumCast(doc?.width, DEFAULT_WIDTH), NumCast(doc?.height, DEFAULT_WIDTH)]; + const flipAxis = dir === PresEffectDirection.Bottom || dir === PresEffectDirection.Top ? 'X' : 'Y'; + const [rotateX, rotateY] = flipAxis === 'X' ? ['180deg', undefined] : [undefined, '180deg']; + switch (presEffect) { + case PresEffect.Flip: return animatedDiv({ transform: to(springs.x, val => `perspective(600px) rotate${flipAxis}(${val}deg)`), width, height, rotateX, rotateY }) + case PresEffect.Rotate:return animatedDiv({ transform: to(springs.x, val => `rotate(${val}deg)`) }); + case PresEffect.Roll: return animatedDiv({ transform: to([springs.x, springs.y], (val, val2) => `translate3d(${val}%, 0, 0) rotate3d(0, 0, 1, ${val2}deg)`) }); + default: return animatedDiv(springs); + } // prettier-ignore } diff --git a/src/client/views/nodes/trails/SpringUtils.ts b/src/client/views/nodes/trails/SpringUtils.ts index bfb22c46a..73e1e14f1 100644 --- a/src/client/views/nodes/trails/SpringUtils.ts +++ b/src/client/views/nodes/trails/SpringUtils.ts @@ -80,7 +80,7 @@ export const effectItems = Object.values(PresEffect) export const presEffectDefaultTimings: { [key: string]: SpringSettings; } = { - Zoom: { type: SpringType.GENTLE, stiffness: 100, damping: 15, mass: 1 }, + Expand: { type: SpringType.GENTLE, stiffness: 100, damping: 15, mass: 1 }, Bounce: { type: SpringType.BOUNCY, stiffness: 600, |
