import Animate from 'tween-animate';
const { Easing } = Animate;
// internal requestAnimationFrame start
Animate.play();
const animate = Animate({
x: 100,
y: (v) => v + 100,
}, {
time: 1000,
easing:Easing.Quadratic.In,
isAssign: false,
}).transform('yoyo').on('update', e => console.log(e));
animate.apply({
x: 0,
y: 0
});
// tween to {x: 100, y: 100}
const animate = Animate(to, options);
const instance = animate.apply(from);
const instance = Animate(from, to, options);
number
Animate(100, 1000).apply(0);
object
Animate({ x: 100, y: 100 }, 1000).apply({ x: 0, y: 0 });
function
Animate((from, options) => ({ x: from.x + 100, y: from.y + 100, }), 1000).apply({ x: 0, y: 0 });
- the above types can be nested
number
: time// tween from 0 to 1 last 1000ms Animate(1, 1000).apply(0);
- object
{ time: number, easing: (v: number) => number; isAssign: boolean; list: any[]; }
- easing - default
Easing.Linear.None
all Easing functionAnimate(0, 1, { time: 1000, easing: Animate.Easing.Linear.None, });
- isAssign - default
true
const a = Animate({ x: 100, y: 100 }, { time: 1000, isAssign: true, }); const b = a.config({ isAssign: false, }) const v1 = {x: 0, y: 0}; const v2 = { x: 0, y: 0}; a.apply(v1); b.apply(v2); // after tweening console.log(v1); // { x: 100, y: 100} console.log(v2); // {x: 0, y: 0};
- list - you can use custom list to control
const customList = []; const a = Animate(100, { time: 1000, isAssign: true, list: customList, }).apply(0); Animate.update(); // don't work; Animate.update(customList); // work
- parser - (optional) must contain parse and apply methods;
const el = document.createElement('div'); el.style.width = el.style.height = '100px'; el.style.background = 'black'; el.style.position = 'absolute'; document.body.append(el); Animate({ x: 100, y: 100, }, { time: 1000, parser: { parse(from) { return { x: parseInt(from.style.left || 0), y: parseInt(from.style.top || 0), } }, apply(el, v) { el.style.left = v.x + 'px'; el.style.top = v.y + 'px'; }, } }).apply(el);
- easing - default
- play -
function
// internal requestAnimationFrame start Animate.play();
- stop -
function
// internal requestAnimationFrame stop Animate.stop();
- update -
function
update(list?: any[])
const { update } = Animate; function ticker() { requestAnimationFrame(animate) update(); } requestAnimationFrame(ticker);
- updateElpased -
function
update(elpased: number, list?: any[])
const { updateElpased } = Animate; updateElpased(1000); // update 1000 ms;
- Easing -
Easing funciton list
const { Easing } = Animate;
animate is generated by Animate Function
const animate = Animate({
x: 100,
y: 100
}, 1000);
const animate2 = animate.config({
time: 600
});
const animate3 = animate({
time: 600
});
animate2 !== animate3;// but they behaves in same way
// add listener
animate.on('start', () => {});
// add listener only excute once
animate.once('update', () => {});
// remove listener
animate.off('complete', () => {});
events will listen to "instance", please see instance events
animate.transform('loop', 2);
all transforms please see transform section in the following
animate.apply({x: 0, y: 0});
animate.apply({x: 0, y: 0}, {x: 50, y: 50});
instance generated by animate
const instance = animate.apply({
x: 0,
y: 0
})
- start
- update
Animate(1, 1000).apply(0); // update 0.5 Animate(1, 1000).apply(0, 0, 0); // update [0.5, 0.5, 0.5]
- complete
transforms will directly change instance, but you can call transform in animate
to avoid
const animate = Animate(1, 1000);
const ins_loop2 = animate.apply(0).transform('loop', 2);
const animate_loop2 = animate.transform('loop', 2);
const animate_loop4 = animate_loop2.transform('loop', 2);
const a = animate_loop2.apply(0); // loop 2
const b = animate_loop4.apply(0); // loop 4
- loop -
transform('loop', count)
- reverse
- yoyo
- delay -
transform('delay', delayTime)
- step -
transform('step', steps)
Animate(0, 1, 1000).transform('step', 10).on('update', console.log); /* log: 0.1 0.2 ... 1.0; */
- the above transforms can be nested
animate.transform('loop', 2).transform('yoyo'); animate.transform('yoyo').transform('loop',2); // the above two behave different
see https://github.com/voderl/tween-animate/blob/v3/src/transform/index.ts
Animate.registerTransform('speed', (ins: AnimateInstance, speed: number) => {
ins.fullTime /= speed;
});
https://voderl.github.io/tween-animate/performance/
32*32 image's imageData (array of 4096 values),use tween-animate and tween.js to transform,you can open chrome devtools "performance" tab to test
parseFromTo(
{ x: [1, 2, 3], y: 1 }, // from
{ x: [1, 2, 6], y: 3 }, // to
{ isAssign: false },
);
/** update function is generated by "from" and "to"
* @param a - from
* @param b - status - range 0 - 1
*/
function anonymous(a,b) {
var a={};var a0=a["x"]=[];a0["2"]=3+b*3;a["y"]=1+b*2;return a;
}
// when options "isAssign" is `true` (default);
function anonymous(a,b) {
var a0=a["x"];a0["2"]=3+b*3;a["y"]=1+b*2;return a;
}
when "from" and "to" value have different structure, console will receive friendly error message
<script src="https://unpkg.com/tween-animate/dist/tween-animate.umd.js"></script>
yarn add tween-animate
npm install tween-animate
- beizer easing function
- more test cases
yarn
yarn watch
yarn test
yarn template
then open http://localhost: 3000
yarn build