-
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.
- Loading branch information
1 parent
d68a1e8
commit b1f8a74
Showing
11 changed files
with
732 additions
and
2 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 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,188 @@ | ||
import { takeProp } from '../utils/internal.js'; | ||
import Value from '../utils/value.js'; | ||
// import Ease from '../easing/ease.js'; | ||
import Timing from '../timing/timing.js'; | ||
import Ticker from '../timing/ticker.js'; | ||
import { newProperty } from './property.js'; | ||
|
||
|
||
export default class Animation { | ||
// targets; | ||
// #timing; | ||
|
||
constructor(targets, props = {}) { | ||
this._timing = new Timing(props); | ||
// todo allow to set a custom ticker | ||
this._ticker = Ticker.global(); | ||
this.targets = new Targets(targets, this._ticker); | ||
|
||
this._props = []; | ||
|
||
for (const prop in props) { | ||
if (prop in this) | ||
throw new Error('prop: ' + prop + ' is not allowed'); | ||
|
||
this[prop] = new PropertyAnimation( | ||
prop, | ||
props[prop], | ||
this | ||
); | ||
this._props.push(this[prop]); | ||
} | ||
|
||
|
||
// transform | ||
// we need to setup our "world" | ||
} | ||
|
||
play() { | ||
// let's register into the global ticker | ||
console.log('play'); | ||
|
||
this._ticker.add((change, opts) => { | ||
let shouldKeepListener = false; | ||
|
||
this._timing.advance(change); | ||
if (!this._timing.ended) | ||
shouldKeepListener = true; | ||
|
||
// loop through all props and check if they have the same timing | ||
for (const prop of this._props) { | ||
if (prop._timing === this._timing) | ||
continue; | ||
|
||
prop._timing.advance(change); | ||
if (!prop._timing.ended) | ||
shouldKeepListener = true; | ||
} | ||
|
||
// now render | ||
for (const prop of this._props) { | ||
prop.render(this.targets, opts.changes); | ||
} | ||
|
||
if (!shouldKeepListener) | ||
opts.remove(); | ||
}); | ||
} | ||
|
||
// t = 0-1 | ||
seek(t) {} | ||
|
||
pause() {} | ||
|
||
reset() { | ||
this.seek(0); | ||
} | ||
} | ||
|
||
class Targets { | ||
constructor(targets, ticker) { | ||
if (Array.from(targets).length > 0) | ||
throw new Error('only one target supported'); | ||
|
||
// this.target = targets; | ||
|
||
this._globalTargets = ticker._targets; | ||
|
||
this.target = this._globalTargets.register(targets); | ||
|
||
// somewhere global probably in the ticker | ||
// we need to store the property changes for each target | ||
// which will then be applied | ||
// this allows to merge transform stuff for example | ||
// optimize to only call the dom if necessary | ||
} | ||
|
||
type() { | ||
return this.target.type(); | ||
} | ||
|
||
// get the start value | ||
getStartValue(prop) { | ||
return this.target.getStartValue(prop); | ||
} | ||
|
||
setValue(prop, value) { | ||
return this.target.setValue(prop, value); | ||
} | ||
} | ||
|
||
class PropertyAnimation { | ||
constructor(prop, value, animation) { | ||
this.prop = newProperty(prop, animation.targets.type()); | ||
// we will get the from the targets | ||
|
||
this.to = this.prop.parseValue(value); | ||
|
||
// either the timing is custom which then only exists in this property | ||
// or it is shared between the animation | ||
this._timing = animation._timing; | ||
} | ||
|
||
render(targets, changes) { | ||
|
||
const pos = this._timing.position; | ||
|
||
const from = targets.getStartValue(this.prop); | ||
|
||
if (this.to.unit !== from.unit) | ||
throw new Error(from.unit + ' != ' + this.to.unit); | ||
|
||
const dif = this.to.num - from.num; | ||
|
||
|
||
targets.setValue(this.prop, from.cloneAdd(pos * dif)); | ||
} | ||
} | ||
|
||
/* | ||
animate(target, { | ||
// special | ||
// translate | ||
x | ||
y | ||
scale | ||
scaleX | ||
scaleY | ||
rotation | ||
skew | ||
skewX | ||
skewY | ||
// stagger | ||
repeatDelay | ||
stagger: { | ||
// wrap advanced options in an object | ||
each: 0.1, | ||
from: "center", | ||
grid: "auto", | ||
ease: "power2.inOut", | ||
repeat: -1, // Repeats immediately, not waiting for the other staggered animations to finish | ||
}, | ||
ease, | ||
duration, | ||
repeat, true|false|0-x | ||
repeatDelay? | ||
delay, | ||
alternate | ||
}) | ||
const tl new Timeline; | ||
tl.add([ | ||
animation() | ||
], 100) | ||
tl.addGroup() | ||
tl.add() | ||
*/ |
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,108 @@ | ||
import Value from '../utils/value.js'; | ||
|
||
export default class Property { | ||
constructor(name) { | ||
// this is the property name | ||
this.name = name; | ||
} | ||
|
||
parseValue(val) { | ||
return Value.parse(val); | ||
} | ||
|
||
defaultValue() { | ||
throw new Error('default value for ' + this.name + ' not known'); | ||
} | ||
|
||
// try to access the value from the target | ||
getCurrentValue(target) { | ||
return this.defaultValue(); | ||
} | ||
|
||
// if this property is a transform function return its name | ||
transformFunction() { | ||
return null; | ||
} | ||
|
||
styleName() { | ||
return null; | ||
} | ||
} | ||
|
||
const TRANSFORM_PROPS = ['x', 'y', 'scale', 'scaleX', 'scaleY']; | ||
|
||
export class Transform extends Property { | ||
constructor(name) { | ||
super(name); | ||
|
||
if (name === 'x' || name === 'y') { | ||
this._defUnit = 'px'; | ||
this._defVal = 0; | ||
this._transformFunction = 'translate' + name.toUpperCase(); | ||
// } else if (name === 'rotation') { | ||
// this.defUnit = 'deg'; | ||
// this.defVal = 0; | ||
} else if (name.startsWith('scale')) { | ||
this._defUnit = null; | ||
this._defVal = 1; | ||
this._transformFunction = name; | ||
} else { | ||
throw new Error('unknown prop ' + name); | ||
} | ||
} | ||
|
||
parseValue(val) { | ||
return Value.parse(val, this._defUnit); | ||
} | ||
|
||
defaultValue() { | ||
return new Value(this._defVal, this._defUnit); | ||
} | ||
|
||
transformFunction() { | ||
return this._transformFunction; | ||
} | ||
} | ||
|
||
const STYLE_PROPS = ['width', 'height', 'top', 'left', 'right', 'bottom']; | ||
|
||
export class StyleProp extends Property { | ||
// constructor(name) { | ||
// super(name); | ||
// } | ||
|
||
parseValue(val) { | ||
// maybe keep it unitless as long as possible, maybe until we need to | ||
// write it | ||
return Value.parse(val, 'px'); | ||
} | ||
|
||
defaultValue() { | ||
return new Value(0, 'px'); | ||
} | ||
|
||
getCurrentValue(target) { | ||
if (target.type() !== 'dom') | ||
throw new Error('error not dom'); | ||
|
||
const style = getComputedStyle(target.target); | ||
|
||
return Value.parse(style[this.name]); | ||
} | ||
|
||
styleName() { | ||
return this.name; | ||
} | ||
} | ||
|
||
export function newProperty(prop, targetType = '') { | ||
if (targetType !== 'dom') | ||
throw new Error('only dom is supported as target'); | ||
|
||
if (TRANSFORM_PROPS.includes(prop)) | ||
return new Transform(prop); | ||
if (STYLE_PROPS.includes(prop)) | ||
return new StyleProp(prop); | ||
|
||
throw new Error('unknown prop ' + prop); | ||
} |
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 |
---|---|---|
@@ -1 +1,60 @@ | ||
export default {}; | ||
import { takeProp } from './utils/internal.js'; | ||
import Animation from './animation/animation.js'; | ||
|
||
|
||
export function animate(target, props = {}) { | ||
const autoplay = parseAutoplay(takeProp(props, 'autoplay', true)); | ||
|
||
const animation = new Animation(target, props); | ||
if (autoplay) | ||
animation.play(); | ||
|
||
return animation; | ||
} | ||
|
||
function parseAutoplay(autoplay) { | ||
if (autoplay !== true && autoplay !== false) | ||
throw new Error('autoplay needs to be true|false'); | ||
|
||
return autoplay; | ||
} | ||
|
||
/* | ||
animate(target, { | ||
// special | ||
// translate | ||
x | ||
y | ||
scale | ||
scaleX | ||
scaleY | ||
rotation | ||
skew | ||
skewX | ||
skewY | ||
// stagger | ||
repeatDelay | ||
stagger: { | ||
// wrap advanced options in an object | ||
each: 0.1, | ||
from: "center", | ||
grid: "auto", | ||
ease: "power2.inOut", | ||
repeat: -1, // Repeats immediately, not waiting for the other staggered animations to finish | ||
}, | ||
ease, | ||
duration, | ||
repeat, (-1?) | ||
repeatDelay? | ||
delay, | ||
alternate | ||
}) | ||
*/ |
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,16 @@ | ||
export default class Ease { | ||
constructor(prop) { | ||
// parse prop | ||
if (prop !== null && typeof prop !== 'function') | ||
throw new Error('ease needs to be a function'); | ||
|
||
this.fn = prop; | ||
} | ||
|
||
apply(t) { | ||
if (this.fn === null) | ||
return t; | ||
|
||
return this.fn(t); | ||
} | ||
} |
File renamed without changes.
Oops, something went wrong.