-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[chnobli] add first animator implementation (allows to update values …
…dynamically like on mouse move)
- Loading branch information
1 parent
c997ca4
commit 8949065
Showing
5 changed files
with
256 additions
and
187 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} |
Oops, something went wrong.