Skip to content

Commit

Permalink
[chnobli] add first animator implementation (allows to update values …
Browse files Browse the repository at this point in the history
…dynamically like on mouse move)
  • Loading branch information
soerenmeier committed Jun 2, 2024
1 parent c997ca4 commit 8949065
Show file tree
Hide file tree
Showing 5 changed files with 256 additions and 187 deletions.
4 changes: 4 additions & 0 deletions chnobli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@
"import": "./dist/scroll/index.js",
"types": "./dist/scroll/index.d.ts"
},
"./animator": {
"import": "./dist/animator/index.js",
"types": "./dist/animator/index.d.ts"
},
".": {
"import": "./dist/chnobli.js",
"types": "./dist/chnobli.d.ts"
Expand Down
187 changes: 0 additions & 187 deletions chnobli/src/animator.js

This file was deleted.

130 changes: 130 additions & 0 deletions chnobli/src/animator/Animator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import Property, { newProperty } from '../property/Property.js';
import { Target } from '../target/Target.js';
import Ticker from '../timing/Ticker.js';
import Timing, { STATE_AFTER } from '../timing/Timing.js';

export type Settings = {
duration: number;
ease?: (t: number) => number;
};

/*
const opacity = animator(obj, {
duration: 200,
ease: sinInOut
});
opacity.set({ opacity: 0 });
opacity.to({ opacity: 1 });
opacity.to({ opacity: 2 }, 1000);
*/

export default class Animator {
setts: Settings;
target: Target;
private props: Map<string, PropertyAnimator<any>>;

private ticker: Ticker;

constructor(target: any, ticker: Ticker, setts: Settings) {
this.setts = setts;
this.target = ticker.registerTarget(target);

this.ticker = ticker;

this.props = new Map();
}

private getProp(name: string): PropertyAnimator<any> {
const prop = this.props.get(name);
if (prop) return prop;

const newProp = new PropertyAnimator(name, this.setts, this.target);
this.props.set(name, newProp);
return newProp;
}

set(props: Record<string, any>) {
for (const prop in props) {
const propAni = this.getProp(prop);
console.log('got prop ani', propAni);
propAni.set(this.target, props[prop]);
console.log('got prop ani', propAni);
}
}

to(props: Record<string, any>, duration?: number) {
for (const prop in props) {
const propAni = this.getProp(prop);
propAni.to(this.target, props[prop], duration);
}
}

/// returns if the ticker should keep running
_tick(change: number): boolean {
let shouldStop = true;

for (const prop of this.props.values()) {
prop.advance(change);
prop.render(this.target);

if (prop.timing.state < STATE_AFTER) {
shouldStop = false;
}
}

return !shouldStop;
}
}

export class PropertyAnimator<V> {
prop: Property<V>;
timing: Timing;

private initialized: boolean;

constructor(prop: string, setts: Settings, target: Target) {
this.prop = newProperty(prop, target.type());

this.timing = new Timing(setts);
this.initialized = false;
}

set(target: Target, value: any) {
const val = this.prop.parseValue(value);

this.prop.init(target, val, val);

this.timing.seek(2);
}

to(target: Target, value: any, duration?: number) {
const val = this.prop.parseValue(value);

let current = null;
if (this.initialized) {
current = this.prop.interpolate(this.timing.position);
}

this.prop.init(target, current, val);
this.initialized = true;

this.timing.seek(0);
if (typeof duration === 'number') {
this.timing.setDuration(duration);
}
}

advance(change: number) {
this.timing.advance(change);
}

// call advance first
render(target: Target) {
const pos = this.timing.position;

this.prop.setValue(target, this.prop.interpolate(pos));
}
}
56 changes: 56 additions & 0 deletions chnobli/src/animator/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
const obj = { opacity: 1 };
// maybe we could even have stagger?
const opacity = animator(obj, {
// initial value
// might also be able to be set with stagger?
// for example
opacity: 1,
duration: 200,
ease: sineInOut
});
// or maybe instead
const animator = animator();
animator.add(obj, {
opacity: 1,
duration: 200,
ease: sineInOut
});
// what is the reason why we would wan't one animator with
// multiple objects with different timings
// could we not just use multiple animators
opacity.set(obj, { opacity: 0 });
let's make the most basic animator first
const opacity = animator(obj, {
duration: 200,
ease: sinInOut
});
opacity.set({ opacity: 0 });
opacity.to({ opacity: 1 });
opacity.to({ opacity: 2 }, 1000);
*/

import Animator, { AnimatorProps } from './public.js';

export { Animator };
export type { AnimatorProps };

export function animator(target: any, props?: AnimatorProps): Animator {
return new Animator(target, props);
}
Loading

0 comments on commit 8949065

Please sign in to comment.