feat(createPerspectiveManager): create perspective manager to work with perspective, moving objects along the z axis
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
import { Spring } from 'svelte/motion';
|
||||
|
||||
export interface PerspectiveConfig {
|
||||
/**
|
||||
* How many px to move back per level
|
||||
*/
|
||||
depthStep?: number;
|
||||
/**
|
||||
* Scale reduction per level
|
||||
*/
|
||||
scaleStep?: number;
|
||||
/**
|
||||
* Blur amount per level
|
||||
*/
|
||||
blurStep?: number;
|
||||
/**
|
||||
* Opacity reduction per level
|
||||
*/
|
||||
opacityStep?: number;
|
||||
/**
|
||||
* Parallax intensity per level
|
||||
*/
|
||||
parallaxIntensity?: number;
|
||||
/**
|
||||
* Horizontal offset for each plan (x-axis positioning)
|
||||
* Positive = right, Negative = left
|
||||
*/
|
||||
horizontalOffset?: number;
|
||||
/**
|
||||
* Layout mode: 'center' (default) or 'split' for Swiss-style side-by-side
|
||||
*/
|
||||
layoutMode?: 'center' | 'split';
|
||||
}
|
||||
|
||||
/**
|
||||
* Manages perspective state with a simple boolean flag.
|
||||
*
|
||||
* Drastically simplified from the complex camera/index system.
|
||||
* Just manages whether content is in "back" or "front" state.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const perspective = createPerspectiveManager({
|
||||
* depthStep: 100,
|
||||
* scaleStep: 0.5,
|
||||
* blurStep: 4,
|
||||
* });
|
||||
*
|
||||
* // Toggle back/front
|
||||
* perspective.toggle();
|
||||
*
|
||||
* // Check state
|
||||
* const isBack = perspective.isBack; // reactive boolean
|
||||
* ```
|
||||
*/
|
||||
export class PerspectiveManager {
|
||||
/**
|
||||
* Spring for smooth back/front transitions
|
||||
*/
|
||||
spring = new Spring(0, {
|
||||
stiffness: 0.2,
|
||||
damping: 0.8,
|
||||
});
|
||||
|
||||
/**
|
||||
* Reactive boolean: true when in back position (blurred, scaled down)
|
||||
*/
|
||||
isBack = $derived(this.spring.current > 0.5);
|
||||
|
||||
/**
|
||||
* Reactive boolean: true when in front position (fully visible, interactive)
|
||||
*/
|
||||
isFront = $derived(this.spring.current < 0.5);
|
||||
|
||||
/**
|
||||
* Configuration values for style computation
|
||||
*/
|
||||
private config: Required<PerspectiveConfig>;
|
||||
|
||||
constructor(config: PerspectiveConfig = {}) {
|
||||
this.config = {
|
||||
depthStep: config.depthStep ?? 100,
|
||||
scaleStep: config.scaleStep ?? 0.5,
|
||||
blurStep: config.blurStep ?? 4,
|
||||
opacityStep: config.opacityStep ?? 0.5,
|
||||
parallaxIntensity: config.parallaxIntensity ?? 0,
|
||||
horizontalOffset: config.horizontalOffset ?? 0,
|
||||
layoutMode: config.layoutMode ?? 'center',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle between front (0) and back (1) positions.
|
||||
* Smooth spring animation handles the transition.
|
||||
*/
|
||||
toggle = () => {
|
||||
const target = this.spring.current < 0.5 ? 1 : 0;
|
||||
this.spring.target = target;
|
||||
};
|
||||
|
||||
/**
|
||||
* Force to back position
|
||||
*/
|
||||
setBack = () => {
|
||||
this.spring.target = 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Force to front position
|
||||
*/
|
||||
setFront = () => {
|
||||
this.spring.target = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get configuration for style computation
|
||||
* @internal
|
||||
*/
|
||||
getConfig = () => this.config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory function to create a PerspectiveManager instance.
|
||||
*
|
||||
* @param config - Configuration options
|
||||
* @returns Configured PerspectiveManager instance
|
||||
*/
|
||||
export function createPerspectiveManager(config: PerspectiveConfig = {}) {
|
||||
return new PerspectiveManager(config);
|
||||
}
|
||||
Reference in New Issue
Block a user