diff options
Diffstat (limited to 'src/client/views/nodes/trails/PresBox.tsx')
| -rw-r--r-- | src/client/views/nodes/trails/PresBox.tsx | 173 |
1 files changed, 171 insertions, 2 deletions
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx index d330c8157..deb59d03f 100644 --- a/src/client/views/nodes/trails/PresBox.tsx +++ b/src/client/views/nodes/trails/PresBox.tsx @@ -46,6 +46,7 @@ import { DictationManager } from '../../../util/DictationManager'; import CubicBezierEditor, { TIMING_DEFAULT_MAPPINGS } from './CubicBezierEditor'; import Slider from '@mui/material/Slider'; import { FaArrowDown, FaArrowLeft, FaArrowRight, FaArrowUp, FaCompressArrowsAlt } from 'react-icons/fa'; +import SpringAnimationPreview from './SlideEffectPreview'; export interface pinDataTypes { scrollable?: boolean; @@ -74,6 +75,23 @@ export interface PinProps { pinData?: pinDataTypes; } +// the type of slide effect timing (spring-driven) +export enum SpringType { + DEFAULT = 'default', + GENTLE = 'gentle', + BOUNCY = 'bouncy', + CUSTOM = 'custom', + QUICK = 'quick', +} + +// settings that control slide effect spring settings +export interface SpringSettings { + type: SpringType; + stiffness: number; + damping: number; + mass: number; +} + const easeItems = [ { text: 'Ease', @@ -116,6 +134,59 @@ const effectItems = Object.values(PresEffect) val: effect, })); +const effectTimings = [ + { text: 'Default', val: SpringType.DEFAULT }, + { + text: 'Gentle', + val: SpringType.GENTLE, + }, + { + text: 'Quick', + val: SpringType.QUICK, + }, + { + text: 'Bouncy', + val: SpringType.BOUNCY, + }, + { + text: 'Custom', + val: SpringType.CUSTOM, + }, +]; + +const springMappings: { + [key: string]: { stiffness: number; damping: number; mass: number }; +} = { + default: { + // stiffness: 300, + // damping: 12, + // mass: 2, + stiffness: 600, + damping: 15, + mass: 1, + }, + gentle: { + stiffness: 100, + damping: 15, + mass: 1, + }, + quick: { + stiffness: 300, + damping: 20, + mass: 1, + }, + bouncy: { + stiffness: 600, + damping: 15, + mass: 1, + }, + custom: { + stiffness: 100, + damping: 10, + mass: 1, + }, +}; + @observer export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { public static LayoutString(fieldKey: string) { @@ -1689,6 +1760,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { @undoBatch updateEffect = (effect: PresEffect, bullet: boolean, all?: boolean) => (all ? this.childDocs : this.selectedArray).forEach(doc => (bullet ? (doc.presBulletEffect = effect) : (doc.presentation_effect = effect))); + @undoBatch + updateEffectTiming = (activeItem: Doc, timing: SpringSettings) => { + activeItem.presEffectTiming = JSON.stringify(timing); + this.selectedArray.forEach(doc => (doc.presEffectTiming = activeItem.presEffectTiming)); + }; + static _sliderBatch: any; static endBatch = () => { PresBox._sliderBatch.end(); @@ -1935,6 +2012,25 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { @computed get transitionDropdown() { const activeItem = this.activeItem; + // Retrieving spring timing properties + let timing = StrCast(activeItem.presEffectTiming); + let timingConfig: SpringSettings | undefined; + if (timing) { + timingConfig = JSON.parse(timing); + } + + if (!timingConfig) { + timingConfig = { + type: SpringType.DEFAULT, + // stiffness: 300, + // damping: 12, + // mass: 2, + stiffness: 600, + damping: 15, + mass: 1, + }; + } + const preseEffect = (effect: PresEffect) => ( <div className={`presBox-dropdownOption ${activeItem.presentation_effect === effect || (effect === PresEffect.None && !activeItem.presentation_effect) ? 'active' : ''}`} @@ -2105,7 +2201,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { <div className="slider-text">Slow</div> </div> {/* Easing function */} - <div className="presBox-option-block presBox-option-cente"> + <div className="presBox-option-block presBox-option-center"> <Dropdown color={StrCast(Doc.UserDoc().userColor)} formLabel={'Easing Function'} @@ -2129,7 +2225,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { <CubicBezierEditor setFunc={this.setBezierControlPoints} currPoints={this.currCPoints} easeFunc={StrCast(this.activeItem.presEaseFunc)} /> </div> </div> - <div className="presBox-option-block"> + <div className="presBox-option-block" style={{ padding: '16px' }}> Effects <Toggle formLabel={'Play Audio Annotation'} @@ -2258,6 +2354,79 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() { {presDirection(PresEffectDirection.Center, '', 2, 2, { width: 10, height: 10, alignSelf: 'center' })} </div> */} {/* Effect spring settings */} + <Dropdown + color={StrCast(Doc.UserDoc().userColor)} + formLabel={'Effect Timing'} + closeOnSelect={true} + items={effectTimings} + selectedVal={timingConfig.type} + setSelectedVal={val => { + console.log('effect timing', val); + this.updateEffectTiming(activeItem, { + type: val as SpringType, + ...springMappings[val], + }); + }} + dropdownType={DropdownType.SELECT} + type={Type.TERT} + /> + <div>Tension</div> + <div + onPointerDown={e => { + e.stopPropagation(); + }}> + <Slider + min={1} + max={1000} + step={5} + size="small" + value={timingConfig.stiffness} + onChange={(e, val) => { + if (!timingConfig) return; + this.updateEffectTiming(activeItem, { ...timingConfig, stiffness: val as number }); + }} + valueLabelDisplay="auto" + /> + </div> + <div>Damping</div> + <div + onPointerDown={e => { + e.stopPropagation(); + }}> + <Slider + min={1} + max={100} + step={1} + size="small" + value={timingConfig.damping} + onChange={(e, val) => { + if (!timingConfig) return; + this.updateEffectTiming(activeItem, { ...timingConfig, damping: val as number }); + }} + valueLabelDisplay="auto" + /> + </div> + <div>Mass</div> + <div + onPointerDown={e => { + e.stopPropagation(); + }}> + <Slider + min={1} + max={10} + step={1} + size="small" + value={timingConfig.mass} + onChange={(e, val) => { + if (!timingConfig) return; + this.updateEffectTiming(activeItem, { ...timingConfig, mass: val as number }); + }} + valueLabelDisplay="auto" + /> + </div> + <SpringAnimationPreview tension={timingConfig.stiffness} friction={timingConfig.damping} mass={timingConfig.mass}> + <div style={{ width: '40px', height: '40px', backgroundColor: '#2e96ff', borderRadius: '4px' }}></div> + </SpringAnimationPreview> </div> <div className="ribbon-final-box"> <div className="ribbon-final-button-hidden" onClick={() => this.applyTo(this.childDocs)}> |
