From 6ebd91e989463b5ccda27c23a98bf0268e5479e9 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Fri, 29 Dec 2023 15:56:03 +0800 Subject: [PATCH] fix: fix issue with conical cache not work as expect --- .../fix-conical-memory_2023-12-29-07-56.json | 10 ++++ .../src/canvas/conical-gradient.ts | 46 +++++++++------ .../__tests__/browser/src/pages/arc.ts | 58 +++++++++---------- 3 files changed, 67 insertions(+), 47 deletions(-) create mode 100644 common/changes/@visactor/vrender-core/fix-conical-memory_2023-12-29-07-56.json diff --git a/common/changes/@visactor/vrender-core/fix-conical-memory_2023-12-29-07-56.json b/common/changes/@visactor/vrender-core/fix-conical-memory_2023-12-29-07-56.json new file mode 100644 index 000000000..6f1463406 --- /dev/null +++ b/common/changes/@visactor/vrender-core/fix-conical-memory_2023-12-29-07-56.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vrender-core", + "comment": "fix: fix issue with conical cache not work as expect", + "type": "none" + } + ], + "packageName": "@visactor/vrender-core" +} \ No newline at end of file diff --git a/packages/vrender-core/src/canvas/conical-gradient.ts b/packages/vrender-core/src/canvas/conical-gradient.ts index c5d6aac6d..547bdffbd 100644 --- a/packages/vrender-core/src/canvas/conical-gradient.ts +++ b/packages/vrender-core/src/canvas/conical-gradient.ts @@ -22,7 +22,7 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ -import { pi2 } from '@visactor/vutils'; +import { pi2, LRU } from '@visactor/vutils'; import { application } from '../application'; import type { IConicalGradient, IContext2d } from '../interface'; import { interpolateColor } from '../color-string'; @@ -52,10 +52,25 @@ class ConicalCanvas { } // todo 目前环形渐变缓存还是依赖于x和y,后续优化环形渐变 -export class ColorInterpolate { +export class ColorInterpolate extends LRU { private readonly rgbaSet: Uint8ClampedArray; + private cacheParams: { + CLEAN_THRESHOLD?: number; + L_TIME?: number; + R_COUNT?: number; + R_TIMESTAMP_MAX_SIZE?: number; + } = { CLEAN_THRESHOLD: 100, L_TIME: 1e3 }; + static _instance: ColorInterpolate; + + static getInstance() { + if (!ColorInterpolate._instance) { + ColorInterpolate._instance = new ColorInterpolate(); + } + return ColorInterpolate._instance; + } constructor(stops: [number, string][] = [], precision = 100) { + super(); const canvas = ConicalCanvas.GetCanvas(); const conicalCtx = ConicalCanvas.GetCtx(); canvas.width = precision; @@ -84,7 +99,7 @@ export class ColorInterpolate { return `rgba(${rgba[0]}, ${rgba[1]}, ${rgba[2]}, ${rgba[3] / 255})`; } - static dataMap: Map = new Map(); + dataMap: Map = new Map(); // static lastCache: { // stops: [number, string][], // precision: number, @@ -95,24 +110,19 @@ export class ColorInterpolate { // lineWidth: number, // } | null = null; - static GetOrCreate(stops: [number, string][] = [], precision = 100) { - let str = ''; + GetOrCreate(x: number, y: number, w: number, h: number, stops: [number, string][] = [], precision = 100) { + let str = `${x}${y}${w}${h}`; stops.forEach(item => (str += item.join())); str += precision; - let colorInter = ColorInterpolate.dataMap.get(str); + let colorInter = this.dataMap.get(str); if (!colorInter) { - colorInter = new ColorInterpolate(stops, precision); - ColorInterpolate.dataMap.set(str, colorInter); + const data = new ColorInterpolate(stops, precision); + colorInter = { data, timestamp: [] }; + this.addLimitedTimestamp(colorInter, Date.now(), {}); + this.dataMap.set(str, colorInter); } - return colorInter; - } - - static SetColorInterpolateInstance(stops: string, ins: ColorInterpolate) { - ColorInterpolate.dataMap.set(stops, ins); - } - - static GetColorInterpolateInstance(stops: string): ColorInterpolate | undefined { - return ColorInterpolate.dataMap.get(stops); + this.clearCache(this.dataMap, this.cacheParams); + return colorInter.data; } } @@ -269,7 +279,7 @@ export function createConicalGradient( // 每一度一个三角形 const stepNum = deltaDeg + 1; const step = deltaAngle / Math.max(1, stepNum - 1); - const colorInter = ColorInterpolate.GetOrCreate(stops, stepNum); + const colorInter = ColorInterpolate.getInstance().GetOrCreate(x, y, width, height, stops, stepNum); const lineWidth = (2 * Math.PI * r) / 360; diff --git a/packages/vrender/__tests__/browser/src/pages/arc.ts b/packages/vrender/__tests__/browser/src/pages/arc.ts index d91649287..06df7a9e5 100644 --- a/packages/vrender/__tests__/browser/src/pages/arc.ts +++ b/packages/vrender/__tests__/browser/src/pages/arc.ts @@ -113,36 +113,36 @@ export const page = () => { // cap: false // })); - // graphics.push(createArc({ - // innerRadius: 60, - // outerRadius: 137.8, - // startAngle: 0, - // endAngle: Math.PI * 2, - // x: 500, - // y: 200, - // fill: { - // gradient: 'linear', - // x0: 0, - // y0: 0, - // x1: 1, - // y1: 0, - // stops: [ - // { offset: 0, color: 'green' }, - // { offset: 0.5, color: 'orange' }, - // { offset: 1, color: 'red' } - // ] - // }, - // fillOpacity: 0.3, - // background: - // '', - // texture: 'circle', - // textureColor: 'orange', - // stroke: 'green', - // lineWidth: 2, - // cap: false - // })); + const arc = createArc({ + innerRadius: 60, + outerRadius: 137.8, + startAngle: 0, + endAngle: Math.PI * 2, + x: 500, + y: 200, + fill: { + x: 0.5, + y: 0.5, + startAngle: 0, + endAngle: 6.283185307179586, + stops: [ + { offset: 0, color: '#ed2f6a' }, + { offset: 0.2, color: '#621d34' }, + { offset: 0.4, color: '#c08eaf' }, + { offset: 0.6, color: '#806d9e' }, + { offset: 0.8, color: '#2b73af' }, + { offset: 1, color: '#2f90b9' } + ], + gradient: 'conical' + }, + stroke: 'green', + lineWidth: 2, + cap: false + }); + graphics.push(arc); + + arc.animate().from({ endAngle: 0 }, 10000, 'linear'); - graphics.length = 0; graphics.push( createArc({ visible: true,