From cb2451ec805ee8ba9846d30cadf3f4029be378d3 Mon Sep 17 00:00:00 2001 From: youxia <243802688@qq.com> Date: Fri, 1 Mar 2024 14:20:45 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9EbindTicker=EF=BC=8C?= =?UTF-8?q?=E5=8F=AF=E4=BB=A5=E7=BB=91=E5=AE=9A=E8=87=AA=E5=AE=9A=E4=B9=89?= =?UTF-8?q?=E5=88=B7=E6=96=B0=E5=99=A8=EF=BC=8C=E6=96=B0=E5=A2=9EcreateUpd?= =?UTF-8?q?ate=EF=BC=8C=E5=8F=AF=E4=BB=A5=E5=88=9B=E5=BB=BA=E4=B8=80?= =?UTF-8?q?=E4=B8=AA=E5=8F=AF=E7=94=A8update?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 22 +++++- example/index.html | 25 ++++--- example/index.ts | 15 ++++ package.json | 2 +- src/hease.ts | 176 +++++++++++++++++++++------------------------ 5 files changed, 132 insertions(+), 108 deletions(-) create mode 100644 example/index.ts diff --git a/README.md b/README.md index b4561cd..475b9c6 100644 --- a/README.md +++ b/README.md @@ -27,4 +27,24 @@ const ani = hease(0, 1, 2000, EASE.linear) ani.stop(); // 立即完成动画 ani.complete(); -``` \ No newline at end of file +``` +### 如何播放无数次动画? +```ts +// ... +// 只需要在播放数传入Infinity +ani.play(Infinity) +// ... +``` +`注意:`无限播放动画将无法触发`onComplete`,但是可以通过手动调用`complete`方法触发 + +## 相关API补充 +``hease(from: number|number[], to: number|number[], duration = 1000, ease = EASE.linear)`` +创建一个缓动器 +``Hease.play()`` +直接播放1次动画,或者继续播放动画 +``Hease.play(num: number)`` +播放num次动画 +``bindTicker(fn: HeaseTicker)`` +绑定自定义刷新器 +``createUpdate(fn: (dt: number) => void)`` +创建一个刷新运行对象 \ No newline at end of file diff --git a/example/index.html b/example/index.html index a75b783..ff31f3c 100644 --- a/example/index.html +++ b/example/index.html @@ -1,13 +1,16 @@ - - - - Vite + TS - - -
-
- - - + + + + + Vite + TS + + + +
+
+ + + + \ No newline at end of file diff --git a/example/index.ts b/example/index.ts new file mode 100644 index 0000000..e73e55d --- /dev/null +++ b/example/index.ts @@ -0,0 +1,15 @@ +import { hease } from '../src/index'; +const ani = hease(0, 1); +ani.onComplete(() => { + console.log('complate'); +}).onUpdate(val => { + console.log('update', val); +}); +setTimeout(() => { + console.log('stop'); + ani.complete(); +}, 1000); +setTimeout(() => { + ani.play(); +}, 2000); +console.log(ani.play()); \ No newline at end of file diff --git a/package.json b/package.json index 536a04b..1155ba9 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "hease", "private": false, - "version": "0.1.1", + "version": "0.2.1", "repository": "https://github.com/hxg2050/hease.git", "license": "MIT", "main": "./dist/index.cjs.js", diff --git a/src/hease.ts b/src/hease.ts index 6e73dbd..90788cf 100644 --- a/src/hease.ts +++ b/src/hease.ts @@ -1,12 +1,11 @@ import { EASE } from "./ease"; -import EE from 'eventemitter3' export interface Hease { // [props: string]: any; onComplete: (callback: Function) => this; onUpdate: (callback: EasingUpdateFunc) => this; update: (progress: number) => void; - play: () => this + play: (times?: number) => this complete: () => this stop: () => this } @@ -18,94 +17,19 @@ type en = never extends T ? K : never; type a = en; -class _Hease extends EE { - /** - * 起始属性 - */ - from: T; - /** - * 结束属性 - */ - to: T; - /** - * 动画时长 - */ - duration = 1000; - - constructor(public config: { - from: T, - to: T, - duration?: number, - ease?: (x: number) => number - }) { - super(); - this.from = config.from; - this.to = config.to; - if (Number.isFinite(config.duration)) { - this.duration = config.duration!; - } - } - - /** - * 缓动函数 - */ - ease() { - - } - - /** - * 循环次数 - */ - repeat() { - - } - - /** - * 播放动画 - */ - play() { - - } - - /** - * 暂停动画(时间暂停) - */ - pause() { - - } - - /** - * 停止动画,不会触发complete - */ - stop() { - - } - - /** - * 立即完成动画 - */ - complete() { - - } - - /** - * 更新 - */ - update() { - - } -} - // const he = new _Hease({ // 'from': [1], // 'to': [1] // }); // const he2 = he.from([1, 2]);//.to(1); // he2.to(1); + +export type HeaseTicker = (callback: (dt: number) => void) => () => void + /** * 简易刷新器 */ -const update = (callback: Function) => { +const update = (callback: Parameters[0]) => { let lastTime = performance.now(); let animationFrame: number; const run = () => { @@ -121,8 +45,44 @@ const update = (callback: Function) => { } } +let ticker = update; + +export const bindTicker = (fn: HeaseTicker) => { + ticker = fn; +} + type EasingUpdateFunc = (newVal: T, dx: T) => void; +export const createUpdate = (fn: (value: number) => void) => { + let isPause = false; + + let stopHandler: ReturnType | null = null; + + const stop = () => { + isPause = true; + stopHandler && stopHandler(); + stopHandler = null; + } + + const play = () => { + isPause = false; + if (stopHandler) { + return; + } + stopHandler = ticker((x) => { + if (!isPause) { + fn(x); + } + }); + } + + return { + play, + stop, + isPause + } +} + /** * * @param from 起始值 @@ -142,10 +102,36 @@ export const hease = (from: T, to: T, duration = 10 let updateCallback: EasingUpdateFunc; let completeCallback: Function; - let stopUpdate: Function; - let timeout: number | NodeJS.Timeout; + let count = 1; + + let isPause = false; + + let passTime = 0; + + const { play, stop } = createUpdate((dt: number) => { + passTime += dt; + const progress = Math.min(passTime / duration, 1); + actions.update(progress); + }); + + const finish = () => { + if (isPause) { + return actions; + } + actions.update(1); + actions.stop(); + count--; + if (count > 0) { + passTime = 0; + actions.play(); + } else { + actions.complete(); + } + return actions; + } + const actions: Hease = { /** * 播放完成事件 @@ -163,6 +149,7 @@ export const hease = (from: T, to: T, duration = 10 }, /** * 更新 + * @param progress 进度 0-1 */ update: (progress: number) => { @@ -191,21 +178,18 @@ export const hease = (from: T, to: T, duration = 10 }, /** * 开始 + * @param times 执行次数 */ - play: () => { - if (!updateCallback) { - return actions; + play: (times?: number) => { + if (times !== undefined) { + count = times; } - let passTime = 0; - stopUpdate = update((dt: number) => { - passTime += dt; - const progress = Math.min(passTime / duration, 1); - actions.update(progress); - }); + play(); + clearTimeout(timeout); timeout = setTimeout(() => { - actions.complete(); - }, duration); + finish(); + }, duration - passTime); return actions; }, @@ -216,6 +200,8 @@ export const hease = (from: T, to: T, duration = 10 complete: () => { actions.update(1); actions.stop(); + count = 0; + passTime = 0; completeCallback && completeCallback(); return actions; }, @@ -223,7 +209,7 @@ export const hease = (from: T, to: T, duration = 10 * 停止 */ stop: () => { - stopUpdate && stopUpdate(); + stop(); clearTimeout(timeout); return actions; }