diff --git a/common/changes/@visactor/vrender/perf-raf-based-sto_2023-08-03-11-24.json b/common/changes/@visactor/vrender/perf-raf-based-sto_2023-08-03-11-24.json new file mode 100644 index 000000000..cbac3147c --- /dev/null +++ b/common/changes/@visactor/vrender/perf-raf-based-sto_2023-08-03-11-24.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vrender", + "comment": "perf: enhance the effect of requestAnimationFrame in miniapp", + "type": "patch" + } + ], + "packageName": "@visactor/vrender" +} \ No newline at end of file diff --git a/packages/vrender/src/common/utils.ts b/packages/vrender/src/common/utils.ts index 140444d53..81ed7a26f 100644 --- a/packages/vrender/src/common/utils.ts +++ b/packages/vrender/src/common/utils.ts @@ -1,20 +1,6 @@ -import { - isBoolean, - isNumber, - halfPi, - pi, - pi2, - max, - min, - sin, - cos, - IBounds, - IPointLike, - isArray, - pointAt, - Point -} from '@visactor/vutils'; -import { IGraphicAttribute, IStrokeStyle } from '../interface'; +import type { IBounds, IPointLike } from '@visactor/vutils'; +import { isBoolean, isNumber, halfPi, pi, pi2, max, min, sin, cos, isArray, pointAt, Point } from '@visactor/vutils'; +import type { IGraphicAttribute, IStrokeStyle } from '../interface'; // todo: 迁移到@visactor/vutils @@ -329,3 +315,45 @@ export function getAttributeFromDefaultAttrList(attr: Record | Reco } return attr[key]; } + +export class RafBasedSTO { + static TimeOut = 1000 / 60; + durations: number[]; + timeout: number; + lastDate: number; + durationsListThreshold: number; + + constructor() { + this.durations = []; + this.timeout = RafBasedSTO.TimeOut; + this.lastDate = 0; + this.durationsListThreshold = 30; + } + + call(cb: FrameRequestCallback) { + this.lastDate = Date.now(); + return setTimeout( + () => { + this.appendDuration(Date.now() - this.lastDate); + cb(0); + }, + this.timeout, + true + ); + } + + clear(h: number) { + clearTimeout(h); + } + + appendDuration(d: number) { + this.durations.push(d); + if (this.durations.length > this.durationsListThreshold) { + this.durations.shift(); + } + // 最多60fps + this.timeout = Math.max(this.durations.reduce((a, b) => a + b, 0) / this.durations.length, 1000 / 60); + } +} + +export const rafBasedSto = new RafBasedSTO(); diff --git a/packages/vrender/src/core/contributions/env/feishu-contribution.ts b/packages/vrender/src/core/contributions/env/feishu-contribution.ts index 4413fcfc6..fc4118bc1 100644 --- a/packages/vrender/src/core/contributions/env/feishu-contribution.ts +++ b/packages/vrender/src/core/contributions/env/feishu-contribution.ts @@ -9,6 +9,7 @@ import type { ITTCanvas } from '../../../interface'; import { BaseEnvContribution } from './base-contribution'; +import { rafBasedSto } from '../../../common/utils'; declare const tt: { getSystemInfoSync: () => { pixelRatio: number }; @@ -167,14 +168,17 @@ export class FeishuEnvContribution extends BaseEnvContribution implements IEnvCo // 飞书小组件,在云文档浏览器环境中,没有requestAnimationFrame // 但是在小组件工作台环境和模拟器中正常 // 反馈飞书修改,目前先使用setTimeout模拟,进行测试,飞书修复后替换回requestAnimationFrame + // return function (callback: FrameRequestCallback) { + // return setTimeout(callback, 1000 / 60, true); + // } as any; return function (callback: FrameRequestCallback) { - return setTimeout(callback, 1000 / 60, true); + return rafBasedSto.call(callback); } as any; } getCancelAnimationFrame(): (h: number) => void { return (h: number) => { - clearTimeout(h); + rafBasedSto.clear(h); }; } diff --git a/packages/vrender/src/core/contributions/env/lynx-contribution.ts b/packages/vrender/src/core/contributions/env/lynx-contribution.ts index fbd4b9c56..deb254edb 100644 --- a/packages/vrender/src/core/contributions/env/lynx-contribution.ts +++ b/packages/vrender/src/core/contributions/env/lynx-contribution.ts @@ -9,6 +9,7 @@ import type { ILynxCanvas } from '../../../interface'; import { BaseEnvContribution } from './base-contribution'; +import { rafBasedSto } from '../../../common/utils'; declare const lynx: { getSystemInfoSync: () => { pixelRatio: number }; @@ -192,14 +193,17 @@ export class LynxEnvContribution extends BaseEnvContribution implements IEnvCont // 飞书小组件,在云文档浏览器环境中,没有requestAnimationFrame // 但是在小组件工作台环境和模拟器中正常 // 反馈飞书修改,目前先使用setTimeout模拟,进行测试,飞书修复后替换回requestAnimationFrame + // return function (callback: FrameRequestCallback) { + // return setTimeout(callback, 1000 / 60, true); + // } as any; return function (callback: FrameRequestCallback) { - return setTimeout(callback, 1000 / 60, true); + return rafBasedSto.call(callback); } as any; } getCancelAnimationFrame(): (h: number) => void { return (h: number) => { - clearTimeout(h); + rafBasedSto.clear(h); }; } diff --git a/packages/vrender/src/core/contributions/env/node-contribution.ts b/packages/vrender/src/core/contributions/env/node-contribution.ts index 9fecb38ce..4961f88d5 100644 --- a/packages/vrender/src/core/contributions/env/node-contribution.ts +++ b/packages/vrender/src/core/contributions/env/node-contribution.ts @@ -4,6 +4,7 @@ import type { EnvType, ICreateCanvasParams, IEnvContribution, IGlobal } from '.. import { ICanvasLike } from '../../../interface'; import { BaseEnvContribution } from './base-contribution'; import { createImageElement } from './browser-contribution'; +import { rafBasedSto } from '../../../common/utils'; type Canvas = any; @@ -148,14 +149,17 @@ export class NodeEnvContribution extends BaseEnvContribution implements IEnvCont } getRequestAnimationFrame(): (callback: FrameRequestCallback) => number { + // return function (callback: FrameRequestCallback) { + // return setTimeout(callback, 1000 / 60, true); + // } as any; return function (callback: FrameRequestCallback) { - return setTimeout(callback, 1000 / 60, true); + return rafBasedSto.call(callback); } as any; } getCancelAnimationFrame(): (h: number) => void { return (h: number) => { - clearTimeout(h); + rafBasedSto.clear(h); }; } diff --git a/packages/vrender/src/core/contributions/env/wx-contribution.ts b/packages/vrender/src/core/contributions/env/wx-contribution.ts index 9ec45bf8a..1d2858d57 100644 --- a/packages/vrender/src/core/contributions/env/wx-contribution.ts +++ b/packages/vrender/src/core/contributions/env/wx-contribution.ts @@ -9,6 +9,7 @@ import type { ITTCanvas } from '../../../interface'; import { BaseEnvContribution } from './base-contribution'; +import { rafBasedSto } from '../../../common/utils'; declare const wx: { getSystemInfoSync: () => { pixelRatio: number }; @@ -181,14 +182,17 @@ export class WxEnvContribution extends BaseEnvContribution implements IEnvContri // 飞书小组件,在云文档浏览器环境中,没有requestAnimationFrame // 但是在小组件工作台环境和模拟器中正常 // 反馈飞书修改,目前先使用setTimeout模拟,进行测试,飞书修复后替换回requestAnimationFrame + // return function (callback: FrameRequestCallback) { + // return setTimeout(callback, 1000 / 60, true); + // } as any; return function (callback: FrameRequestCallback) { - return setTimeout(callback, 1000 / 60, true); + return rafBasedSto.call(callback); } as any; } getCancelAnimationFrame(): (h: number) => void { return (h: number) => { - clearTimeout(h); + rafBasedSto.clear(h); }; }