From 783d46177f58d041c4af6bcfa6e8f83b1bb6500a Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Tue, 17 Oct 2023 19:27:57 +0800 Subject: [PATCH 01/40] feat: enhance getTheme performance --- .../graphic-service/graphic-service.ts | 2 +- packages/vrender-core/src/graphic/group.ts | 20 + packages/vrender-core/src/graphic/theme.ts | 184 +- .../__tests__/browser/src/pages/arc.ts | 28 +- .../__tests__/browser/src/pages/chart.ts | 3986 +++++++++++++---- .../__tests__/browser/src/pages/theme.ts | 2 +- 6 files changed, 3255 insertions(+), 967 deletions(-) diff --git a/packages/vrender-core/src/graphic/graphic-service/graphic-service.ts b/packages/vrender-core/src/graphic/graphic-service/graphic-service.ts index 3703a7c99..cee901f0d 100644 --- a/packages/vrender-core/src/graphic/graphic-service/graphic-service.ts +++ b/packages/vrender-core/src/graphic/graphic-service/graphic-service.ts @@ -1469,7 +1469,7 @@ export class DefaultGraphicService implements IGraphicService { } = attribute; const tb1 = this.tempAABBBounds1; const tb2 = this.tempAABBBounds2; - if (stroke) { + if (stroke && lineWidth) { const scaledHalfLineWidth = lineWidth / Math.abs(scaleX + scaleY); boundStroke(tb1, scaledHalfLineWidth, miter, strokeBoundsBuffer); aabbBounds.union(tb1); diff --git a/packages/vrender-core/src/graphic/group.ts b/packages/vrender-core/src/graphic/group.ts index b6dbf92ab..dfe030819 100644 --- a/packages/vrender-core/src/graphic/group.ts +++ b/packages/vrender-core/src/graphic/group.ts @@ -18,6 +18,7 @@ import { getTheme, Theme } from './theme'; import { parsePadding } from '../common/utils'; import { UpdateTag, IContainPointMode } from '../common/enums'; import { GROUP_NUMBER_TYPE } from './constants'; +import { DefaultTransform } from './config'; // Group更新AABBBounds的策略 export enum GroupUpdateAABBBoundsMode { @@ -153,6 +154,25 @@ export class Group extends Graphic implements IGroup { return bounds; } + /** + * 大部分group不需要更新matrix,这里特殊优化一下 + * 更新局部matrix的具体函数 + */ + protected doUpdateLocalMatrix() { + const { + x = DefaultTransform.x, + y = DefaultTransform.y, + scaleX = DefaultTransform.scaleX, + scaleY = DefaultTransform.scaleY, + angle = DefaultTransform.angle, + postMatrix + } = this.attribute; + if (x === 0 && y === 0 && scaleX === 1 && scaleY === 1 && angle === 0 && !postMatrix) { + return; + } + return super.doUpdateLocalMatrix(); + } + protected doUpdateAABBBounds(): AABBBounds { const attribute = this.attribute; const groupTheme = getTheme(this).group; diff --git a/packages/vrender-core/src/graphic/theme.ts b/packages/vrender-core/src/graphic/theme.ts index e91e61830..bcbd8d5cb 100644 --- a/packages/vrender-core/src/graphic/theme.ts +++ b/packages/vrender-core/src/graphic/theme.ts @@ -58,39 +58,50 @@ export function newThemeObj(): IFullThemeSpec { }; } -// 将t合并到out中 -function combineTheme(out: IThemeSpec, t: IThemeSpec, rewrite: boolean = true) { - if (!t) { - return; - } - if (rewrite) { - Object.keys(t).forEach(k => { - if (out[k]) { - Object.assign(out[k], t[k]); - } else { - out[k] = t[k]; - } - }); - } else { - Object.keys(t).forEach(k => { - if (out[k]) { - // Object.assign(out[k], t[k]); - const outItem = out[k]; - const tItem = t[k]; - Object.keys(t[k]).forEach(kItem => { - if (outItem[kItem] === undefined) { - outItem[kItem] = tItem[kItem]; - } - }); - } else { - out[k] = t[k]; - } - }); - } +// /** +// * 将t合并到out中 +// * @param out +// * @param t +// * @param rewrite 是否重写out的属性 +// * @returns +// */ +// function combineTheme(out: IThemeSpec, t: IThemeSpec, rewrite: boolean = true) { +// if (!t) { +// return; +// } +// if (rewrite) { +// Object.keys(t).forEach(k => { +// if (out[k]) { +// Object.assign(out[k], t[k]); +// } else { +// out[k] = t[k]; +// } +// }); +// } else { +// Object.keys(t).forEach(k => { +// if (out[k]) { +// // Object.assign(out[k], t[k]); +// const outItem = out[k]; +// const tItem = t[k]; +// Object.keys(t[k]).forEach(kItem => { +// if (outItem[kItem] === undefined) { +// outItem[kItem] = tItem[kItem]; +// } +// }); +// } else { +// out[k] = t[k]; +// } +// }); +// } +// } + +function combine(out: Record, t: Record) { + Object.keys(t).forEach(k => { + out[k] = t[k]; + }); } -// 全局创建60个theme,节省打点耗时时间 -const staticThemePools = new Array(60).fill(0).map(() => newThemeObj()); +const globalThemeObj = newThemeObj(); // // 性能优化,没有修改的theme都使用这个 // const defaultCommontTheme = newThemeObj(); @@ -105,29 +116,35 @@ const staticThemePools = new Array(60).fill(0).map(() => newThemeObj()); // 3. parentTheme // 4. defaultTheme +// 使用原型链来保存主题,避免大量的merge操作 export class Theme implements ITheme { // 当前的总theme,最终合并后的theme combinedTheme: IFullThemeSpec; - // 记录累计应用的所有用户设置上的theme userTheme?: IThemeSpec; - // 公共属性,有些属性所有图元都生效,那就放在common位置 - commonTheme?: Partial; - - // // 记录下一次设置的theme,同时也作为一个dirty位,记录是否存在没有合并的theme - // nextTheme?: IThemeSpec; protected _defaultTheme: IFullThemeSpec; dirty: boolean; constructor() { - // group数量不多,问题不大 - this._defaultTheme = staticThemePools.pop() || newThemeObj(); - this.combinedTheme = this._defaultTheme; + this.initTheme(); this.dirty = false; } + initTheme() { + this._defaultTheme = {} as any; + themeKeys.forEach(key => { + this._defaultTheme[key] = Object.create(globalThemeObj[key]); + }); + this.combinedTheme = this._defaultTheme; + } + + /** + * 获取group上应该有的主题配置 + * @param group + * @returns + */ getTheme(group?: IGroup) { if (!group) { return this.combinedTheme; @@ -165,25 +182,18 @@ export class Theme implements ITheme { // 强制apply所有的上层 parentTheme.applyTheme(parentGroup, pt, true); } - // 将parentTheme.userTheme设置给自己的userTheme - if (!this.userTheme) { - this.userTheme = clone(parentTheme.userTheme); - } else { - combineTheme(this.userTheme, parentTheme.userTheme, false); - } - combineTheme(pt, parentTheme.userTheme); } - // 如果当前节点没有userTheme的话,直接复用上层 + // 如果当前节点没有userTheme的话,直接复用上层的combinedTheme + // 或者直接用默认的theme if (!this.userTheme) { if (parentGroup) { this.combinedTheme = parentGroup.theme.combinedTheme; } else { - this.combinedTheme = this._defaultTheme; console.warn('未知错误,走到不应该走的区域里'); } this.dirty = false; } else { - this.doCombine(pt); + this.doCombine(parentGroup && parentGroup.theme.combinedTheme); } } @@ -191,36 +201,39 @@ export class Theme implements ITheme { } // 合并userTheme到combinedTheme - protected doCombine(parentTheme: IThemeSpec) { + protected doCombine(parentCombinedTheme?: IThemeSpec) { const userTheme = this.userTheme; - const defaultTheme = this._defaultTheme; const combinedTheme = this.combinedTheme; - const parentCommonTheme = parentTheme.common || {}; - const commonTheme = Object.assign(parentCommonTheme, this.commonTheme); - // combineTheme({}, this.userTheme, this._defaultTheme); + + // 1. userTheme + // 2. combinedTheme + // 3. parentCombinedTheme + // 4. defaultTheme themeKeys.forEach(k => { - if (userTheme[k] || commonTheme || parentTheme[k]) { - combinedTheme[k] = Object.assign( - {}, - defaultTheme[k], - commonTheme ?? {}, - parentTheme[k] ?? {}, - userTheme[k] ?? {} - ); - } else { - combinedTheme[k] = defaultTheme[k]; + // init defaultTheme + const obj = Object.create(globalThemeObj[k]); + // merge parentCombinedTheme + if (parentCombinedTheme && parentCombinedTheme[k]) { + combine(obj, parentCombinedTheme[k]); } + // merge combinedTheme + if (combinedTheme[k]) { + combine(obj, combinedTheme[k]); + } + // merge userTheme + if (userTheme[k]) { + combine(obj, userTheme[k]); + } + this.combinedTheme[k] = obj; }); + if (userTheme.common) { + themeKeys.forEach(k => { + combine(this.combinedTheme[k], userTheme.common); + }); + } this.dirty = false; } - resetTheme(t: IThemeSpec, g: IGroup) { - this.userTheme = t; - // 设置自己和子节点的theme都为dirty - this.dirty = true; - this.dirtyChildren(g); - } - setTheme(t: IThemeSpec, g: IGroup) { // 设置自己的nextTheme let userTheme = this.userTheme; @@ -236,19 +249,19 @@ export class Theme implements ITheme { } else { userTheme = t; } - if (t.common) { - if (!this.commonTheme) { - this.commonTheme = t.common; - } else { - Object.assign(this.commonTheme, t.common); - } - } this.userTheme = userTheme; // 设置自己和子节点的theme都为dirty this.dirty = true; this.dirtyChildren(g); } + resetTheme(t: IThemeSpec, g: IGroup) { + this.userTheme = t; + // 设置自己和子节点的theme都为dirty + this.dirty = true; + this.dirtyChildren(g); + } + dirtyChildren(g: IGroup) { g.forEachChildren(item => { if ((item as IGroup).isContainer) { @@ -259,19 +272,6 @@ export class Theme implements ITheme { } }); } - - // // 设置theme到子元素,直接设置到currentTheme中去 - // setThemeToChildrenCurrentTheme(t :IThemeSpec, g: IGroup) { - // g.forEachChildren((item) => { - // if ((item as IGroup).isContainer) { - // const currentTheme = (item as IGroup).theme.currentTheme; - // Object.keys(t).forEach(k => { - // Object.assign(currentTheme[k], t[k]); - // }); - // this.setThemeToChildrenCurrentTheme(t, item as IGroup); - // } - // }) - // } } export const globalTheme = new Theme(); diff --git a/packages/vrender/__tests__/browser/src/pages/arc.ts b/packages/vrender/__tests__/browser/src/pages/arc.ts index c84277ce7..ef9389776 100644 --- a/packages/vrender/__tests__/browser/src/pages/arc.ts +++ b/packages/vrender/__tests__/browser/src/pages/arc.ts @@ -8,12 +8,38 @@ import { createRect, createGlyph, createSymbol, - createText + createText, + createGroup } from '@visactor/vrender'; import { addShapesToStage, colorPools } from '../utils'; import { pi, pi2 } from '@visactor/vutils'; export const page = () => { + // 构建场景树 + const tree = [1, 2, 2, 3, 3, 12]; + function abc(count: number, group: any) { + for (let i = 0; i < count; i++) { + const g = createGroup({}); + group.add(g); + } + return group.children; + } + + const g = createGroup({}); + let children = [g]; + tree.forEach(item => { + const nextChildren = []; + children.forEach(g => { + nextChildren.push(...abc(item, g)); + }); + children = nextChildren; + }); + console.time(); + console.log(g.AABBBounds); + console.timeEnd(); + console.log(g); + return; + const graphics: IGraphic[] = []; const startAngle = pi + pi / 20; const endAngle = pi2 - pi / 20; diff --git a/packages/vrender/__tests__/browser/src/pages/chart.ts b/packages/vrender/__tests__/browser/src/pages/chart.ts index 213c85dcf..9b0725761 100644 --- a/packages/vrender/__tests__/browser/src/pages/chart.ts +++ b/packages/vrender/__tests__/browser/src/pages/chart.ts @@ -25,75 +25,2337 @@ import { roughModule } from '@visactor/vrender-kits'; const json = { attribute: {}, - _uid: 267, + _uid: 3, type: 'group', children: [ { attribute: {}, - _uid: 271, + _uid: 9, type: 'group', children: [ { attribute: { x: 0, y: 0, - width: 500, + width: 981, height: 500, sizeAttrs: { x: 0, y: 0, - width: 500, + width: 981, height: 500 } }, - _uid: 276, + _uid: 14, type: 'group', name: 'root', children: [ + { + attribute: { + visible: true, + clip: true, + x: 68, + y: 70, + width: 845, + height: 334, + sizeAttrs: { + x: 68, + y: 70, + width: 845, + height: 334 + }, + pickable: false, + zIndex: 450 + }, + _uid: 53, + type: 'group', + name: 'regionGroup_4', + children: [ + { + attribute: { + visible: true, + x: 0, + y: 0, + clip: false, + sizeAttrs: { + x: 0, + y: 0 + }, + pickable: false, + zIndex: 0 + }, + _uid: 54, + type: 'group', + name: 'seriesGroup_area_5_7', + children: [ + { + attribute: { + pickable: false, + zIndex: 300 + }, + _uid: 223, + type: 'group', + name: 'area_8', + children: [ + { + attribute: { + y1: 0, + defined: true, + points: [ + { + x: 66.71052631578947, + y: 305.75028000000003, + context: 0, + y1: 334 + }, + { + x: 155.65789473684208, + y: 307.73424, + context: 4, + y1: 334 + }, + { + x: 244.60526315789474, + y: 299.12372, + context: 8, + y1: 334 + }, + { + x: 333.5526315789474, + y: 272.16992, + context: 12, + y1: 334 + }, + { + x: 422.5, + y: 311.90256, + context: 16, + y1: 334 + }, + { + x: 511.4473684210526, + y: 297.71424, + context: 20, + y1: 334 + }, + { + x: 600.3947368421053, + y: 242.47732000000002, + context: 24, + y1: 334 + }, + { + x: 689.3421052631578, + y: 307.22656, + context: 28, + y1: 334 + }, + { + x: 778.2894736842105, + y: 209.00384, + context: 32, + y1: 334 + } + ], + segments: null, + visible: true, + lineWidth: 2, + lineCap: 'round', + lineJoin: 'round', + fillOpacity: 0.2, + fill: '#1664FF', + stroke: ['#1664FF', false, false, false], + connectedType: 'none', + x: 0, + y: 0, + x1: 0, + pickable: true + }, + _uid: 224, + type: 'area', + children: [] + }, + { + attribute: { + y1: 0, + defined: true, + points: [ + { + x: 66.71052631578947, + y: 276.5186, + context: 1, + y1: 305.75028000000003 + }, + { + x: 155.65789473684208, + y: 281.10108, + context: 5, + y1: 307.73424 + }, + { + x: 244.60526315789474, + y: 275.24940000000004, + context: 9, + y1: 299.12372 + }, + { + x: 333.5526315789474, + y: 242.93824, + context: 13, + y1: 272.16992 + }, + { + x: 422.5, + y: 281.3616, + context: 17, + y1: 311.90256 + }, + { + x: 511.4473684210526, + y: 274.88867999999997, + context: 21, + y1: 297.71424 + }, + { + x: 600.3947368421053, + y: 207.53424, + context: 25, + y1: 242.47732000000002 + }, + { + x: 689.3421052631578, + y: 276.6856, + context: 29, + y1: 307.22656 + }, + { + x: 778.2894736842105, + y: 168.02872, + context: 33, + y1: 209.00384 + } + ], + segments: null, + visible: true, + lineWidth: 2, + lineCap: 'round', + lineJoin: 'round', + fillOpacity: 0.2, + fill: '#1AC6FF', + stroke: ['#1AC6FF', false, false, false], + connectedType: 'none', + x: 0, + y: 0, + x1: 0, + pickable: true + }, + _uid: 225, + type: 'area', + children: [] + }, + { + attribute: { + y1: 0, + defined: true, + points: [ + { + x: 66.71052631578947, + y: 256.11788, + context: 2, + y1: 276.5186 + }, + { + x: 155.65789473684208, + y: 247.25352, + context: 6, + y1: 281.10108 + }, + { + x: 244.60526315789474, + y: 228.46268000000003, + context: 10, + y1: 275.24940000000004 + }, + { + x: 333.5526315789474, + y: 182.45752, + context: 14, + y1: 242.93824 + }, + { + x: 422.5, + y: 200.91436, + context: 18, + y1: 281.3616 + }, + { + x: 511.4473684210526, + y: 174.24111999999997, + context: 22, + y1: 274.88867999999997 + }, + { + x: 600.3947368421053, + y: 139.93932, + context: 26, + y1: 207.53424 + }, + { + x: 689.3421052631578, + y: 196.23835999999997, + context: 30, + y1: 276.6856 + }, + { + x: 778.2894736842105, + y: 98.42979999999999, + context: 34, + y1: 168.02872 + } + ], + segments: null, + visible: true, + lineWidth: 2, + lineCap: 'round', + lineJoin: 'round', + fillOpacity: 0.2, + fill: '#FF8A00', + stroke: ['#FF8A00', false, false, false], + connectedType: 'none', + x: 0, + y: 0, + x1: 0, + pickable: true + }, + _uid: 226, + type: 'area', + children: [] + }, + { + attribute: { + y1: 0, + defined: true, + points: [ + { + x: 66.71052631578947, + y: 170.52036, + context: 3, + y1: 256.11788 + }, + { + x: 155.65789473684208, + y: 160.33336, + context: 7, + y1: 247.25352 + }, + { + x: 244.60526315789474, + y: 150.81436000000002, + context: 11, + y1: 228.46268000000003 + }, + { + x: 333.5526315789474, + y: 123.58, + context: 15, + y1: 182.45752 + }, + { + x: 422.5, + y: 114.08772, + context: 19, + y1: 200.91436 + }, + { + x: 511.4473684210526, + y: 91.93683999999999, + context: 23, + y1: 174.24111999999997 + }, + { + x: 600.3947368421053, + y: 70.85476, + context: 27, + y1: 139.93932 + }, + { + x: 689.3421052631578, + y: 42.611720000000005, + context: 31, + y1: 196.23835999999997 + }, + { + x: 778.2894736842105, + y: 23.206319999999995, + context: 35, + y1: 98.42979999999999 + } + ], + segments: null, + visible: true, + lineWidth: 2, + lineCap: 'round', + lineJoin: 'round', + fillOpacity: 0.2, + fill: '#3CC780', + stroke: ['#3CC780', false, false, false], + connectedType: 'none', + x: 0, + y: 0, + x1: 0, + pickable: true + }, + _uid: 227, + type: 'area', + children: [] + } + ] + }, + { + attribute: { + pickable: false, + zIndex: 300 + }, + _uid: 186, + type: 'group', + name: 'point_10', + children: [ + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#1664FF', + x: 66.71052631578947, + y: 305.75028000000003, + imageAttrs: { + fill: '#1664FF' + }, + pickable: true + }, + _uid: 187, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#1AC6FF', + x: 66.71052631578947, + y: 276.5186, + imageAttrs: { + fill: '#1AC6FF' + }, + pickable: true + }, + _uid: 188, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#FF8A00', + x: 66.71052631578947, + y: 256.11788, + imageAttrs: { + fill: '#FF8A00' + }, + pickable: true + }, + _uid: 189, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#3CC780', + x: 66.71052631578947, + y: 170.52036, + imageAttrs: { + fill: '#3CC780' + }, + pickable: true + }, + _uid: 190, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#1664FF', + x: 155.65789473684208, + y: 307.73424, + imageAttrs: { + fill: '#1664FF' + }, + pickable: true + }, + _uid: 191, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#1AC6FF', + x: 155.65789473684208, + y: 281.10108, + imageAttrs: { + fill: '#1AC6FF' + }, + pickable: true + }, + _uid: 192, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#FF8A00', + x: 155.65789473684208, + y: 247.25352, + imageAttrs: { + fill: '#FF8A00' + }, + pickable: true + }, + _uid: 193, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#3CC780', + x: 155.65789473684208, + y: 160.33336, + imageAttrs: { + fill: '#3CC780' + }, + pickable: true + }, + _uid: 194, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#1664FF', + x: 244.60526315789474, + y: 299.12372, + imageAttrs: { + fill: '#1664FF' + }, + pickable: true + }, + _uid: 195, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#1AC6FF', + x: 244.60526315789474, + y: 275.24940000000004, + imageAttrs: { + fill: '#1AC6FF' + }, + pickable: true + }, + _uid: 196, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#FF8A00', + x: 244.60526315789474, + y: 228.46268000000003, + imageAttrs: { + fill: '#FF8A00' + }, + pickable: true + }, + _uid: 197, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#3CC780', + x: 244.60526315789474, + y: 150.81436000000002, + imageAttrs: { + fill: '#3CC780' + }, + pickable: true + }, + _uid: 198, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#1664FF', + x: 333.5526315789474, + y: 272.16992, + imageAttrs: { + fill: '#1664FF' + }, + pickable: true + }, + _uid: 199, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#1AC6FF', + x: 333.5526315789474, + y: 242.93824, + imageAttrs: { + fill: '#1AC6FF' + }, + pickable: true + }, + _uid: 200, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#FF8A00', + x: 333.5526315789474, + y: 182.45752, + imageAttrs: { + fill: '#FF8A00' + }, + pickable: true + }, + _uid: 201, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#3CC780', + x: 333.5526315789474, + y: 123.58, + imageAttrs: { + fill: '#3CC780' + }, + pickable: true + }, + _uid: 202, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#1664FF', + x: 422.5, + y: 311.90256, + imageAttrs: { + fill: '#1664FF' + }, + pickable: true + }, + _uid: 203, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#1AC6FF', + x: 422.5, + y: 281.3616, + imageAttrs: { + fill: '#1AC6FF' + }, + pickable: true + }, + _uid: 204, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#FF8A00', + x: 422.5, + y: 200.91436, + imageAttrs: { + fill: '#FF8A00' + }, + pickable: true + }, + _uid: 205, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#3CC780', + x: 422.5, + y: 114.08772, + imageAttrs: { + fill: '#3CC780' + }, + pickable: true + }, + _uid: 206, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#1664FF', + x: 511.4473684210526, + y: 297.71424, + imageAttrs: { + fill: '#1664FF' + }, + pickable: true + }, + _uid: 207, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#1AC6FF', + x: 511.4473684210526, + y: 274.88867999999997, + imageAttrs: { + fill: '#1AC6FF' + }, + pickable: true + }, + _uid: 208, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#FF8A00', + x: 511.4473684210526, + y: 174.24111999999997, + imageAttrs: { + fill: '#FF8A00' + }, + pickable: true + }, + _uid: 209, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#3CC780', + x: 511.4473684210526, + y: 91.93683999999999, + imageAttrs: { + fill: '#3CC780' + }, + pickable: true + }, + _uid: 210, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#1664FF', + x: 600.3947368421053, + y: 242.47732000000002, + imageAttrs: { + fill: '#1664FF' + }, + pickable: true + }, + _uid: 211, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#1AC6FF', + x: 600.3947368421053, + y: 207.53424, + imageAttrs: { + fill: '#1AC6FF' + }, + pickable: true + }, + _uid: 212, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#FF8A00', + x: 600.3947368421053, + y: 139.93932, + imageAttrs: { + fill: '#FF8A00' + }, + pickable: true + }, + _uid: 213, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#3CC780', + x: 600.3947368421053, + y: 70.85476, + imageAttrs: { + fill: '#3CC780' + }, + pickable: true + }, + _uid: 214, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#1664FF', + x: 689.3421052631578, + y: 307.22656, + imageAttrs: { + fill: '#1664FF' + }, + pickable: true + }, + _uid: 215, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#1AC6FF', + x: 689.3421052631578, + y: 276.6856, + imageAttrs: { + fill: '#1AC6FF' + }, + pickable: true + }, + _uid: 216, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#FF8A00', + x: 689.3421052631578, + y: 196.23835999999997, + imageAttrs: { + fill: '#FF8A00' + }, + pickable: true + }, + _uid: 217, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#3CC780', + x: 689.3421052631578, + y: 42.611720000000005, + imageAttrs: { + fill: '#3CC780' + }, + pickable: true + }, + _uid: 218, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#1664FF', + x: 778.2894736842105, + y: 209.00384, + imageAttrs: { + fill: '#1664FF' + }, + pickable: true + }, + _uid: 219, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#1AC6FF', + x: 778.2894736842105, + y: 168.02872, + imageAttrs: { + fill: '#1AC6FF' + }, + pickable: true + }, + _uid: 220, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#FF8A00', + x: 778.2894736842105, + y: 98.42979999999999, + imageAttrs: { + fill: '#FF8A00' + }, + pickable: true + }, + _uid: 221, + type: 'symbol', + children: [] + }, + { + attribute: { + visible: true, + size: 8, + symbolType: 'circle', + lineWidth: 1, + stroke: '#202226', + fillOpacity: 1, + fill: '#3CC780', + x: 778.2894736842105, + y: 23.206319999999995, + imageAttrs: { + fill: '#3CC780' + }, + pickable: true + }, + _uid: 222, + type: 'symbol', + children: [] + } + ] + } + ] + } + ] + }, + { + attribute: { + pickable: false, + zIndex: 100 + }, + _uid: 15, + type: 'group', + name: 'axis-bottom_20', + children: [ + { + attribute: { + title: { + space: 8, + padding: 0, + textStyle: { + fontSize: 12, + fill: '#888c93', + fontWeight: 'normal', + fillOpacity: 1, + lineHeight: 15.600000000000001 + }, + autoRotate: false, + angle: null, + shape: {}, + background: {}, + state: { + text: null, + shape: null, + background: null + }, + pickable: true, + childrenPickable: true, + text: 'type', + maxWidth: null + }, + label: { + visible: true, + inside: false, + space: 8, + padding: 0, + style: { + fontSize: 12, + fill: '#bbbdc3', + fontWeight: 'normal', + fillOpacity: 1 + }, + formatMethod: null, + state: null + }, + tick: { + visible: true, + inside: false, + alignWithLabel: true, + length: 4, + style: { + lineWidth: 1, + stroke: '#4b4f54', + strokeOpacity: 1 + }, + state: null + }, + subTick: { + visible: false, + inside: false, + count: 4, + length: 2, + style: { + lineWidth: 1, + stroke: '#4b4f54', + strokeOpacity: 1 + }, + state: null + }, + line: { + visible: true, + style: { + lineWidth: 1, + stroke: '#4b4f54', + strokeOpacity: 1 + }, + startSymbol: {}, + endSymbol: {} + }, + x: 68, + y: 404, + start: { + x: 0, + y: 0 + }, + end: { + x: 845, + y: 0 + }, + items: [ + [ + { + id: 'Nail polish', + label: 'Nail polish', + value: 0.07894736842105263, + rawValue: 'Nail polish' + }, + { + id: 'Eyebrow pencil', + label: 'Eyebrow pencil', + value: 0.18421052631578944, + rawValue: 'Eyebrow pencil' + }, + { + id: 'Rouge', + label: 'Rouge', + value: 0.2894736842105263, + rawValue: 'Rouge' + }, + { + id: 'Lipstick', + label: 'Lipstick', + value: 0.3947368421052632, + rawValue: 'Lipstick' + }, + { + id: 'Eyeshadows', + label: 'Eyeshadows', + value: 0.5, + rawValue: 'Eyeshadows' + }, + { + id: 'Eyeliner', + label: 'Eyeliner', + value: 0.6052631578947368, + rawValue: 'Eyeliner' + }, + { + id: 'Foundation', + label: 'Foundation', + value: 0.7105263157894738, + rawValue: 'Foundation' + }, + { + id: 'Lip gloss', + label: 'Lip gloss', + value: 0.8157894736842104, + rawValue: 'Lip gloss' + }, + { + id: 'Mascara', + label: 'Mascara', + value: 0.9210526315789473, + rawValue: 'Mascara' + } + ] + ], + visible: true, + pickable: true, + orient: 'bottom', + panel: { + state: null + }, + verticalFactor: 1, + verticalLimitSize: 150, + verticalMinSize: null + }, + _uid: 16, + type: 'group', + name: 'axis', + children: [ + { + attribute: { + x: 0, + y: 0, + pickable: false + }, + _uid: 127, + type: 'group', + children: [ + { + attribute: { + x: 0, + y: 0, + zIndex: 1 + }, + _uid: 128, + type: 'group', + name: 'axis-container', + children: [ + { + attribute: { + visible: true, + lineStyle: { + lineWidth: 1, + stroke: '#4b4f54', + strokeOpacity: 1 + }, + startSymbol: { + visible: false, + autoRotate: true, + symbolType: 'triangle', + size: 12, + refX: 0, + refY: 0, + refAngle: 0, + style: { + fill: '#000', + zIndex: 1 + } + }, + endSymbol: { + visible: false, + autoRotate: true, + symbolType: 'triangle', + size: 12, + refX: 0, + refY: 0, + refAngle: 0, + style: { + fill: '#000', + zIndex: 1 + } + }, + points: [ + { + x: 0, + y: 0 + }, + { + x: 845, + y: 0 + } + ] + }, + _uid: 129, + type: 'group', + name: 'axis-line', + children: [ + { + attribute: { + points: [ + { + x: 0, + y: 0 + }, + { + x: 845, + y: 0 + } + ], + lineWidth: 1, + stroke: '#4b4f54', + strokeOpacity: 1, + fill: false, + closePath: false + }, + _uid: 130, + type: 'polygon', + name: 'axis-line-line', + children: [] + } + ] + }, + { + attribute: { + x: 0, + y: 0, + pickable: false + }, + _uid: 131, + type: 'group', + name: 'axis-tick-container', + children: [ + { + attribute: { + points: [ + { + x: 66.71052631578947, + y: 0 + }, + { + x: 66.71052631578947, + y: 4 + } + ], + lineWidth: 1, + stroke: '#4b4f54', + strokeOpacity: 1 + }, + _uid: 132, + type: 'line', + name: 'axis-tick', + children: [] + }, + { + attribute: { + points: [ + { + x: 155.65789473684208, + y: 0 + }, + { + x: 155.65789473684208, + y: 4 + } + ], + lineWidth: 1, + stroke: '#4b4f54', + strokeOpacity: 1 + }, + _uid: 133, + type: 'line', + name: 'axis-tick', + children: [] + }, + { + attribute: { + points: [ + { + x: 244.60526315789474, + y: 0 + }, + { + x: 244.60526315789474, + y: 4 + } + ], + lineWidth: 1, + stroke: '#4b4f54', + strokeOpacity: 1 + }, + _uid: 134, + type: 'line', + name: 'axis-tick', + children: [] + }, + { + attribute: { + points: [ + { + x: 333.5526315789474, + y: 0 + }, + { + x: 333.5526315789474, + y: 4 + } + ], + lineWidth: 1, + stroke: '#4b4f54', + strokeOpacity: 1 + }, + _uid: 135, + type: 'line', + name: 'axis-tick', + children: [] + }, + { + attribute: { + points: [ + { + x: 422.5, + y: 0 + }, + { + x: 422.5, + y: 4 + } + ], + lineWidth: 1, + stroke: '#4b4f54', + strokeOpacity: 1 + }, + _uid: 136, + type: 'line', + name: 'axis-tick', + children: [] + }, + { + attribute: { + points: [ + { + x: 511.4473684210526, + y: 0 + }, + { + x: 511.4473684210526, + y: 4 + } + ], + lineWidth: 1, + stroke: '#4b4f54', + strokeOpacity: 1 + }, + _uid: 137, + type: 'line', + name: 'axis-tick', + children: [] + }, + { + attribute: { + points: [ + { + x: 600.3947368421053, + y: 0 + }, + { + x: 600.3947368421053, + y: 4 + } + ], + lineWidth: 1, + stroke: '#4b4f54', + strokeOpacity: 1 + }, + _uid: 138, + type: 'line', + name: 'axis-tick', + children: [] + }, + { + attribute: { + points: [ + { + x: 689.3421052631578, + y: 0 + }, + { + x: 689.3421052631578, + y: 4 + } + ], + lineWidth: 1, + stroke: '#4b4f54', + strokeOpacity: 1 + }, + _uid: 139, + type: 'line', + name: 'axis-tick', + children: [] + }, + { + attribute: { + points: [ + { + x: 778.2894736842105, + y: 0 + }, + { + x: 778.2894736842105, + y: 4 + } + ], + lineWidth: 1, + stroke: '#4b4f54', + strokeOpacity: 1 + }, + _uid: 140, + type: 'line', + name: 'axis-tick', + children: [] + } + ] + }, + { + attribute: { + x: 0, + y: 0, + pickable: false + }, + _uid: 141, + type: 'group', + name: 'axis-label-container', + children: [ + { + attribute: { + x: 0, + y: 0, + pickable: false + }, + _uid: 142, + type: 'group', + name: 'axis-label-container-layer-0', + children: [ + { + attribute: { + x: 66.71052631578947, + y: 12, + text: 'Nail polish', + lineHeight: 12, + textAlign: 'center', + textBaseline: 'top', + fontSize: 12, + fill: '#bbbdc3', + fontWeight: 'normal', + fillOpacity: 1 + }, + _uid: 143, + type: 'text', + name: 'axis-label', + children: [] + }, + { + attribute: { + x: 155.65789473684208, + y: 12, + text: 'Eyebrow pencil', + lineHeight: 12, + textAlign: 'center', + textBaseline: 'top', + fontSize: 12, + fill: '#bbbdc3', + fontWeight: 'normal', + fillOpacity: 1 + }, + _uid: 144, + type: 'text', + name: 'axis-label', + children: [] + }, + { + attribute: { + x: 244.60526315789474, + y: 12, + text: 'Rouge', + lineHeight: 12, + textAlign: 'center', + textBaseline: 'top', + fontSize: 12, + fill: '#bbbdc3', + fontWeight: 'normal', + fillOpacity: 1 + }, + _uid: 145, + type: 'text', + name: 'axis-label', + children: [] + }, + { + attribute: { + x: 333.5526315789474, + y: 12, + text: 'Lipstick', + lineHeight: 12, + textAlign: 'center', + textBaseline: 'top', + fontSize: 12, + fill: '#bbbdc3', + fontWeight: 'normal', + fillOpacity: 1 + }, + _uid: 146, + type: 'text', + name: 'axis-label', + children: [] + }, + { + attribute: { + x: 422.5, + y: 12, + text: 'Eyeshadows', + lineHeight: 12, + textAlign: 'center', + textBaseline: 'top', + fontSize: 12, + fill: '#bbbdc3', + fontWeight: 'normal', + fillOpacity: 1 + }, + _uid: 147, + type: 'text', + name: 'axis-label', + children: [] + }, + { + attribute: { + x: 511.4473684210526, + y: 12, + text: 'Eyeliner', + lineHeight: 12, + textAlign: 'center', + textBaseline: 'top', + fontSize: 12, + fill: '#bbbdc3', + fontWeight: 'normal', + fillOpacity: 1 + }, + _uid: 148, + type: 'text', + name: 'axis-label', + children: [] + }, + { + attribute: { + x: 600.3947368421053, + y: 12, + text: 'Foundation', + lineHeight: 12, + textAlign: 'center', + textBaseline: 'top', + fontSize: 12, + fill: '#bbbdc3', + fontWeight: 'normal', + fillOpacity: 1 + }, + _uid: 149, + type: 'text', + name: 'axis-label', + children: [] + }, + { + attribute: { + x: 689.3421052631578, + y: 12, + text: 'Lip gloss', + lineHeight: 12, + textAlign: 'center', + textBaseline: 'top', + fontSize: 12, + fill: '#bbbdc3', + fontWeight: 'normal', + fillOpacity: 1 + }, + _uid: 150, + type: 'text', + name: 'axis-label', + children: [] + }, + { + attribute: { + x: 778.2894736842105, + y: 12, + text: 'Mascara', + lineHeight: 12, + textAlign: 'center', + textBaseline: 'top', + fontSize: 12, + fill: '#bbbdc3', + fontWeight: 'normal', + fillOpacity: 1 + }, + _uid: 151, + type: 'text', + name: 'axis-label', + children: [] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + attribute: { + pickable: false, + zIndex: 100 + }, + _uid: 25, + type: 'group', + name: 'axis-left_23', + children: [ + { + attribute: { + title: { + space: 12, + padding: 0, + textStyle: { + fontSize: 12, + fill: '#888c93', + fontWeight: 'normal', + fillOpacity: 1, + textAlign: 'center', + textBaseline: 'bottom', + lineHeight: 15.600000000000001 + }, + autoRotate: false, + angle: -1.5707963267948966, + shape: {}, + background: {}, + state: { + text: null, + shape: null, + background: null + }, + pickable: true, + childrenPickable: true, + text: 'value', + maxWidth: null + }, + label: { + visible: true, + inside: false, + space: 12, + padding: 0, + style: { + fontSize: 12, + fill: '#bbbdc3', + fontWeight: 'normal', + fillOpacity: 1 + }, + formatMethod: null, + state: null, + autoLimit: true + }, + tick: { + visible: false, + inside: false, + alignWithLabel: true, + length: 4, + style: { + lineWidth: 1, + stroke: '#4b4f54', + strokeOpacity: 1 + }, + state: null + }, + subTick: { + visible: false, + inside: false, + count: 4, + length: 2, + style: { + lineWidth: 1, + stroke: '#4b4f54', + strokeOpacity: 1 + }, + state: null + }, + line: { + visible: false, + style: { + lineWidth: 1, + stroke: '#4b4f54', + strokeOpacity: 1 + }, + startSymbol: {}, + endSymbol: {} + }, + x: 68, + y: 70, + start: { + x: 0, + y: 0 + }, + end: { + x: 0, + y: 334 + }, + items: [ + [ + { + id: 0, + label: 0, + value: 1, + rawValue: 0 + }, + { + id: 10000, + label: 10000, + value: 0.7999999999999999, + rawValue: 10000 + }, + { + id: 20000, + label: 20000, + value: 0.6, + rawValue: 20000 + }, + { + id: 30000, + label: 30000, + value: 0.39999999999999997, + rawValue: 30000 + }, + { + id: 40000, + label: 40000, + value: 0.19999999999999996, + rawValue: 40000 + }, + { + id: 50000, + label: 50000, + value: 0, + rawValue: 50000 + } + ] + ], + visible: true, + pickable: true, + orient: 'left', + panel: { + state: null + }, + verticalFactor: 1, + verticalLimitSize: 294.3, + verticalMinSize: null + }, + _uid: 26, + type: 'group', + name: 'axis', + children: [ + { + attribute: { + x: 0, + y: 0, + pickable: false + }, + _uid: 152, + type: 'group', + children: [ + { + attribute: { + x: 0, + y: 0, + zIndex: 1 + }, + _uid: 153, + type: 'group', + name: 'axis-container', + children: [ + { + attribute: { + x: 0, + y: 0, + pickable: false + }, + _uid: 154, + type: 'group', + name: 'axis-label-container', + children: [ + { + attribute: { + x: 0, + y: 0, + pickable: false + }, + _uid: 155, + type: 'group', + name: 'axis-label-container-layer-0', + children: [ + { + attribute: { + x: -12, + y: 334, + text: 0, + lineHeight: 12, + textAlign: 'end', + textBaseline: 'middle', + fontSize: 12, + fill: '#bbbdc3', + fontWeight: 'normal', + fillOpacity: 1 + }, + _uid: 156, + type: 'text', + name: 'axis-label', + children: [] + }, + { + attribute: { + x: -12, + y: 267.2, + text: 10000, + lineHeight: 12, + textAlign: 'end', + textBaseline: 'middle', + fontSize: 12, + fill: '#bbbdc3', + fontWeight: 'normal', + fillOpacity: 1 + }, + _uid: 157, + type: 'text', + name: 'axis-label', + children: [] + }, + { + attribute: { + x: -12, + y: 200.4, + text: 20000, + lineHeight: 12, + textAlign: 'end', + textBaseline: 'middle', + fontSize: 12, + fill: '#bbbdc3', + fontWeight: 'normal', + fillOpacity: 1 + }, + _uid: 158, + type: 'text', + name: 'axis-label', + children: [] + }, + { + attribute: { + x: -12, + y: 133.6, + text: 30000, + lineHeight: 12, + textAlign: 'end', + textBaseline: 'middle', + fontSize: 12, + fill: '#bbbdc3', + fontWeight: 'normal', + fillOpacity: 1 + }, + _uid: 159, + type: 'text', + name: 'axis-label', + children: [] + }, + { + attribute: { + x: -12, + y: 66.79999999999998, + text: 40000, + lineHeight: 12, + textAlign: 'end', + textBaseline: 'middle', + fontSize: 12, + fill: '#bbbdc3', + fontWeight: 'normal', + fillOpacity: 1 + }, + _uid: 160, + type: 'text', + name: 'axis-label', + children: [] + }, + { + attribute: { + x: -12, + y: 0, + text: 50000, + lineHeight: 12, + textAlign: 'end', + textBaseline: 'middle', + fontSize: 12, + fill: '#bbbdc3', + fontWeight: 'normal', + fillOpacity: 1 + }, + _uid: 161, + type: 'text', + name: 'axis-label', + children: [] + } + ] + } + ] + } + ] + } + ] + } + ] + } + ] + }, + { + attribute: { + pickable: false, + zIndex: 50 + }, + _uid: 35, + type: 'group', + name: 'axis-left-grid_24', + children: [ + { + attribute: { + style: { + lineWidth: 1, + stroke: '#404349', + strokeOpacity: 1, + lineDash: [] + }, + subGrid: { + visible: false, + style: { + lineWidth: 1, + stroke: '#404349', + strokeOpacity: 1, + lineDash: [4, 4] + }, + type: 'line' + }, + visible: true, + x: 68, + y: 70, + pickable: true, + type: 'line', + start: { + x: 0, + y: 0 + }, + end: { + x: 0, + y: 334 + }, + items: [ + { + id: 0, + label: 0, + value: 1, + rawValue: 0 + }, + { + id: 10000, + label: 10000, + value: 0.7999999999999999, + rawValue: 10000 + }, + { + id: 20000, + label: 20000, + value: 0.6, + rawValue: 20000 + }, + { + id: 30000, + label: 30000, + value: 0.39999999999999997, + rawValue: 30000 + }, + { + id: 40000, + label: 40000, + value: 0.19999999999999996, + rawValue: 40000 + }, + { + id: 50000, + label: 50000, + value: 0, + rawValue: 50000 + } + ], + verticalFactor: 1, + depth: 0, + length: 845 + }, + _uid: 36, + type: 'group', + name: 'axis-grid', + children: [ + { + attribute: { + x: 0, + y: 0, + pickable: false + }, + _uid: 162, + type: 'group', + children: [ + { + attribute: { + path: 'M0,334L845,334', + z: 0, + lineWidth: 1, + stroke: '#404349', + strokeOpacity: 1, + lineDash: [] + }, + _uid: 163, + type: 'path', + name: 'axis-grid-line', + children: [] + }, + { + attribute: { + path: 'M0,267.2L845,267.2', + z: 0, + lineWidth: 1, + stroke: '#404349', + strokeOpacity: 1, + lineDash: [] + }, + _uid: 164, + type: 'path', + name: 'axis-grid-line', + children: [] + }, + { + attribute: { + path: 'M0,200.4L845,200.4', + z: 0, + lineWidth: 1, + stroke: '#404349', + strokeOpacity: 1, + lineDash: [] + }, + _uid: 165, + type: 'path', + name: 'axis-grid-line', + children: [] + }, + { + attribute: { + path: 'M0,133.6L845,133.6', + z: 0, + lineWidth: 1, + stroke: '#404349', + strokeOpacity: 1, + lineDash: [] + }, + _uid: 166, + type: 'path', + name: 'axis-grid-line', + children: [] + }, + { + attribute: { + path: 'M0,66.79999999999998L845,66.79999999999998', + z: 0, + lineWidth: 1, + stroke: '#404349', + strokeOpacity: 1, + lineDash: [] + }, + _uid: 167, + type: 'path', + name: 'axis-grid-line', + children: [] + }, + { + attribute: { + path: 'M0,0L845,0', + z: 0, + lineWidth: 1, + stroke: '#404349', + strokeOpacity: 1, + lineDash: [] + }, + _uid: 168, + type: 'path', + name: 'axis-grid-line', + children: [] + } + ] + } + ] + } + ] + }, { attribute: { pickable: false, - zIndex: 0 + zIndex: 100 }, - _uid: 277, + _uid: 39, type: 'group', - name: 'VGRAMMAR_MARK_8', + name: 'axis-right_27', children: [ { attribute: { title: { - space: 4, - padding: [0, 0, 0, 0], + space: 12, + padding: 0, textStyle: { fontSize: 12, - fill: '#333333', + fill: '#888c93', fontWeight: 'normal', - fillOpacity: 1 + fillOpacity: 1, + textAlign: 'center', + textBaseline: 'bottom', + lineHeight: 15.600000000000001 }, - text: 'theta' + autoRotate: false, + angle: 1.5707963267948966, + shape: {}, + background: {}, + state: { + text: null, + shape: null, + background: null + }, + pickable: true, + childrenPickable: true, + text: 'value', + maxWidth: null }, label: { visible: true, inside: false, - space: 4, + space: 12, padding: 0, style: { fontSize: 12, - fill: '#6F6F6F', + fill: '#bbbdc3', fontWeight: 'normal', fillOpacity: 1 - } + }, + formatMethod: null, + state: null, + autoLimit: true }, tick: { - visible: true, + visible: false, inside: false, alignWithLabel: true, length: 4, style: { lineWidth: 1, - stroke: '#D9DDE4', + stroke: '#4b4f54', strokeOpacity: 1 - } + }, + state: null }, subTick: { visible: false, @@ -102,81 +2364,82 @@ const json = { length: 2, style: { lineWidth: 1, - stroke: '#D9DDE4', + stroke: '#4b4f54', strokeOpacity: 1 - } + }, + state: null }, line: { - visible: true, + visible: false, style: { lineWidth: 1, - stroke: '#D9DDE4', + stroke: '#4b4f54', strokeOpacity: 1 - } + }, + startSymbol: {}, + endSymbol: {} }, - x: 0, - y: 0, + x: 913, + y: 70, start: { x: 0, y: 0 }, end: { x: 0, - y: 0 + y: 334 }, items: [ [ { id: 0, - label: 'test0', - value: 0.08333333333333338, - rawValue: 'test0' + label: 0, + value: 1, + rawValue: 0 }, { - id: 1, - label: 'test1', - value: 0.25000000000000006, - rawValue: 'test1' + id: 10000, + label: 10000, + value: 0.7999999999999999, + rawValue: 10000 }, { - id: 2, - label: 'test2', - value: 0.4166666666666667, - rawValue: 'test2' + id: 20000, + label: 20000, + value: 0.6, + rawValue: 20000 }, { - id: 3, - label: 'test3', - value: 0.5833333333333334, - rawValue: 'test3' + id: 30000, + label: 30000, + value: 0.39999999999999997, + rawValue: 30000 }, { - id: 4, - label: 'test4', - value: 0.75, - rawValue: 'test4' + id: 40000, + label: 40000, + value: 0.19999999999999996, + rawValue: 40000 }, { - id: 5, - label: 'test5', - value: 0.9166666666666666, - rawValue: 'test5' + id: 50000, + label: 50000, + value: 0, + rawValue: 50000 } ] ], - startAngle: 0, - endAngle: 6.283185307179586, - radius: 210, - innerRadius: 0, - center: { - x: 250, - y: 250 + visible: true, + pickable: true, + orient: 'right', + panel: { + state: null }, - grid: { - visible: true - } + verticalFactor: -1, + verticalLimitSize: 294.3, + verticalMinSize: null }, - _uid: 278, + _uid: 40, type: 'group', name: 'axis', children: [ @@ -186,7 +2449,7 @@ const json = { y: 0, pickable: false }, - _uid: 297, + _uid: 169, type: 'group', children: [ { @@ -195,172 +2458,17 @@ const json = { y: 0, zIndex: 1 }, - _uid: 298, + _uid: 170, type: 'group', name: 'axis-container', children: [ - { - attribute: { - x: 250, - y: 250, - startAngle: 0, - endAngle: 6.283185307179586, - radius: 210, - innerRadius: 0, - lineWidth: 1, - stroke: '#D9DDE4', - strokeOpacity: 1 - }, - _uid: 299, - type: 'circle', - name: 'axis-line', - children: [] - }, - { - attribute: { - x: 0, - y: 0, - pickable: false - }, - _uid: 300, - type: 'group', - name: 'axis-tick-container', - children: [ - { - attribute: { - points: [ - { - x: 431.8653347947321, - y: 355.00000000000006 - }, - { - x: 435.32943640986986, - y: 357.00000000000006 - } - ], - lineWidth: 1, - stroke: '#D9DDE4', - strokeOpacity: 1 - }, - _uid: 301, - type: 'line', - name: 'axis-tick', - children: [] - }, - { - attribute: { - points: [ - { - x: 249.99999999999991, - y: 460 - }, - { - x: 249.99999999999991, - y: 464 - } - ], - lineWidth: 1, - stroke: '#D9DDE4', - strokeOpacity: 1 - }, - _uid: 302, - type: 'line', - name: 'axis-tick', - children: [] - }, - { - attribute: { - points: [ - { - x: 68.13466520526788, - y: 355 - }, - { - x: 64.67056359013013, - y: 357 - } - ], - lineWidth: 1, - stroke: '#D9DDE4', - strokeOpacity: 1 - }, - _uid: 303, - type: 'line', - name: 'axis-tick', - children: [] - }, - { - attribute: { - points: [ - { - x: 68.13466520526791, - y: 144.99999999999997 - }, - { - x: 64.67056359013016, - y: 142.99999999999997 - } - ], - lineWidth: 1, - stroke: '#D9DDE4', - strokeOpacity: 1 - }, - _uid: 304, - type: 'line', - name: 'axis-tick', - children: [] - }, - { - attribute: { - points: [ - { - x: 249.99999999999997, - y: 40 - }, - { - x: 249.99999999999997, - y: 36 - } - ], - lineWidth: 1, - stroke: '#D9DDE4', - strokeOpacity: 1 - }, - _uid: 305, - type: 'line', - name: 'axis-tick', - children: [] - }, - { - attribute: { - points: [ - { - x: 431.86533479473206, - y: 144.9999999999999 - }, - { - x: 435.3294364098698, - y: 142.9999999999999 - } - ], - lineWidth: 1, - stroke: '#D9DDE4', - strokeOpacity: 1 - }, - _uid: 306, - type: 'line', - name: 'axis-tick', - children: [] - } - ] - }, { attribute: { x: 0, y: 0, pickable: false }, - _uid: 307, + _uid: 171, type: 'group', name: 'axis-label-container', children: [ @@ -370,114 +2478,114 @@ const json = { y: 0, pickable: false }, - _uid: 308, + _uid: 172, type: 'group', name: 'axis-label-container-layer-0', children: [ { attribute: { - x: 438.79353802500765, - y: 359.00000000000006, - text: 'test0', + x: 12, + y: 334, + text: 0, lineHeight: 12, textAlign: 'start', textBaseline: 'middle', fontSize: 12, - fill: '#6F6F6F', + fill: '#bbbdc3', fontWeight: 'normal', fillOpacity: 1 }, - _uid: 309, + _uid: 173, type: 'text', name: 'axis-label', children: [] }, { attribute: { - x: 249.99999999999991, - y: 468, - text: 'test1', + x: 12, + y: 267.2, + text: 10000, lineHeight: 12, - textAlign: 'center', - textBaseline: 'top', + textAlign: 'start', + textBaseline: 'middle', fontSize: 12, - fill: '#6F6F6F', + fill: '#bbbdc3', fontWeight: 'normal', fillOpacity: 1 }, - _uid: 310, + _uid: 174, type: 'text', name: 'axis-label', children: [] }, { attribute: { - x: 61.20646197499237, - y: 359, - text: 'test2', + x: 12, + y: 200.4, + text: 20000, lineHeight: 12, - textAlign: 'end', + textAlign: 'start', textBaseline: 'middle', fontSize: 12, - fill: '#6F6F6F', + fill: '#bbbdc3', fontWeight: 'normal', fillOpacity: 1 }, - _uid: 311, + _uid: 175, type: 'text', name: 'axis-label', children: [] }, { attribute: { - x: 61.2064619749924, - y: 140.99999999999997, - text: 'test3', + x: 12, + y: 133.6, + text: 30000, lineHeight: 12, - textAlign: 'end', + textAlign: 'start', textBaseline: 'middle', fontSize: 12, - fill: '#6F6F6F', + fill: '#bbbdc3', fontWeight: 'normal', fillOpacity: 1 }, - _uid: 312, + _uid: 176, type: 'text', name: 'axis-label', children: [] }, { attribute: { - x: 249.99999999999997, - y: 32, - text: 'test4', + x: 12, + y: 66.79999999999998, + text: 40000, lineHeight: 12, - textAlign: 'center', - textBaseline: 'bottom', + textAlign: 'start', + textBaseline: 'middle', fontSize: 12, - fill: '#6F6F6F', + fill: '#bbbdc3', fontWeight: 'normal', fillOpacity: 1 }, - _uid: 313, + _uid: 177, type: 'text', name: 'axis-label', children: [] }, { attribute: { - x: 438.7935380250076, - y: 140.9999999999999, - text: 'test5', + x: 12, + y: 0, + text: 50000, lineHeight: 12, textAlign: 'start', textBaseline: 'middle', fontSize: 12, - fill: '#6F6F6F', + fill: '#bbbdc3', fontWeight: 'normal', fillOpacity: 1 }, - _uid: 314, + _uid: 178, type: 'text', name: 'axis-label', children: [] @@ -497,535 +2605,773 @@ const json = { { attribute: { pickable: false, - zIndex: 0 + zIndex: 50 }, - _uid: 315, + _uid: 49, type: 'group', - name: 'VGRAMMAR_MARK_9', + name: 'axis-right-grid_28', children: [ { attribute: { - title: { - space: 4, - padding: 0, - textStyle: { - fontSize: 12, - fill: '#333333', - fontWeight: 'normal', - fillOpacity: 1 - } + style: { + lineWidth: 1, + stroke: '#404349', + strokeOpacity: 1, + lineDash: [] }, - label: { - visible: true, - inside: false, - space: 4, - padding: 0, - style: { - fontSize: 12, - fill: '#89909d', - fontWeight: 'normal', - fillOpacity: 1 - } - }, - tick: { - visible: true, - inside: false, - alignWithLabel: true, - length: 4, - style: { - lineWidth: 1, - stroke: '#D9DDE4', - strokeOpacity: 1 - } - }, - subTick: { - visible: false, - inside: false, - count: 4, - length: 2, - style: { - lineWidth: 1, - stroke: '#D9DDE4', - strokeOpacity: 1 - } - }, - line: { - visible: true, + subGrid: { + visible: false, style: { lineWidth: 1, - stroke: '#D9DDE4', - strokeOpacity: 1 - } + stroke: '#404349', + strokeOpacity: 1, + lineDash: [4, 4] + }, + type: 'line' }, - x: 250, - y: 250, + visible: true, + x: 913, + y: 70, + pickable: true, + type: 'line', start: { x: 0, y: 0 }, end: { - x: 210, - y: 0 + x: 0, + y: 334 }, items: [ - [ - { - id: 0, - label: -1000, - value: 0, - rawValue: -1000 - }, + { + id: 0, + label: 0, + value: 1, + rawValue: 0 + }, + { + id: 10000, + label: 10000, + value: 0.7999999999999999, + rawValue: 10000 + }, + { + id: 20000, + label: 20000, + value: 0.6, + rawValue: 20000 + }, + { + id: 30000, + label: 30000, + value: 0.39999999999999997, + rawValue: 30000 + }, + { + id: 40000, + label: 40000, + value: 0.19999999999999996, + rawValue: 40000 + }, + { + id: 50000, + label: 50000, + value: 0, + rawValue: 50000 + } + ], + verticalFactor: -1, + depth: 0, + length: 845 + }, + _uid: 50, + type: 'group', + name: 'axis-grid', + children: [ + { + attribute: { + x: 0, + y: 0, + pickable: false + }, + _uid: 179, + type: 'group', + children: [ { - id: 1, - label: -500, - value: 0.16666666666666666, - rawValue: -500 + attribute: { + path: 'M0,334L-845,334', + z: 0, + lineWidth: 1, + stroke: '#404349', + strokeOpacity: 1, + lineDash: [] + }, + _uid: 180, + type: 'path', + name: 'axis-grid-line', + children: [] }, { - id: 2, - label: 0, - value: 0.3333333333333333, - rawValue: 0 + attribute: { + path: 'M0,267.2L-845,267.2', + z: 0, + lineWidth: 1, + stroke: '#404349', + strokeOpacity: 1, + lineDash: [] + }, + _uid: 181, + type: 'path', + name: 'axis-grid-line', + children: [] }, { - id: 3, - label: 500, - value: 0.5, - rawValue: 500 + attribute: { + path: 'M0,200.4L-845,200.4', + z: 0, + lineWidth: 1, + stroke: '#404349', + strokeOpacity: 1, + lineDash: [] + }, + _uid: 182, + type: 'path', + name: 'axis-grid-line', + children: [] }, { - id: 4, - label: 1000, - value: 0.6666666666666666, - rawValue: 1000 + attribute: { + path: 'M0,133.6L-845,133.6', + z: 0, + lineWidth: 1, + stroke: '#404349', + strokeOpacity: 1, + lineDash: [] + }, + _uid: 183, + type: 'path', + name: 'axis-grid-line', + children: [] }, { - id: 5, - label: 1500, - value: 0.8333333333333334, - rawValue: 1500 + attribute: { + path: 'M0,66.79999999999998L-845,66.79999999999998', + z: 0, + lineWidth: 1, + stroke: '#404349', + strokeOpacity: 1, + lineDash: [] + }, + _uid: 184, + type: 'path', + name: 'axis-grid-line', + children: [] }, { - id: 6, - label: 2000, - value: 1, - rawValue: 2000 + attribute: { + path: 'M0,0L-845,0', + z: 0, + lineWidth: 1, + stroke: '#404349', + strokeOpacity: 1, + lineDash: [] + }, + _uid: 185, + type: 'path', + name: 'axis-grid-line', + children: [] } ] - ], - grid: { - visible: true, - center: { + } + ] + } + ] + }, + { + attribute: { + textStyle: { + ellipsis: '...', + fill: '#fdfdfd', + fontSize: 16, + fontWeight: 'bold', + textAlign: 'left', + textBaseline: 'top', + width: 941, + lineHeight: 24 + }, + subtextStyle: { + ellipsis: '...', + fill: '#888c93', + fontSize: 14, + fontWeight: 'normal', + textAlign: 'left', + textBaseline: 'top', + width: 941, + lineHeight: 21 + }, + text: 'Stacked area chart of cosmetic products sales', + subtext: '', + x: 20, + y: 24, + width: 941, + align: 'left', + verticalAlign: 'top' + }, + _uid: 55, + type: 'group', + name: 'title', + children: [ + { + attribute: { + x: 0, + y: 0, + zIndex: 1, + width: 941, + height: 26 + }, + _uid: 56, + type: 'group', + name: 'title-container', + children: [ + { + attribute: { + text: ['Stacked area chart of cosmetic products sales'], + ellipsis: '...', + fill: '#fdfdfd', + fontSize: 16, + fontWeight: 'bold', + textAlign: 'left', + textBaseline: 'top', + width: 941, + lineHeight: 24, + maxLineWidth: 941, x: 0, y: 0 }, - type: 'circle', - closed: true, - sides: 10 + _uid: 57, + type: 'text', + name: 'mainTitle', + children: [] + }, + { + attribute: { + text: [''], + ellipsis: '...', + fill: '#888c93', + fontSize: 14, + fontWeight: 'normal', + textAlign: 'left', + textBaseline: 'top', + width: 941, + lineHeight: 21, + maxLineWidth: 941, + x: 0, + y: 26 + }, + _uid: 58, + type: 'text', + name: 'subTitle', + children: [] + } + ] + } + ] + }, + { + attribute: { + layout: 'horizontal', + title: { + align: 'start', + space: 12, + textStyle: { + fontSize: 12, + fontWeight: 'bold', + fill: '#2C3542' + } + }, + item: { + spaceCol: 10, + spaceRow: 6, + shape: { + space: 6, + style: { + size: 10, + cursor: 'pointer', + lineWidth: 0, + fillOpacity: 1, + opacity: 1 + }, + state: { + selectedHover: { + opacity: 0.85 + }, + unSelected: { + opacity: 1, + fillOpacity: 0.2 + } + } + }, + label: { + space: 6, + style: { + fontSize: 12, + fill: '#888c93', + cursor: 'pointer', + lineHeight: 15.600000000000001, + opacity: 1 + }, + state: { + selectedHover: { + opacity: 0.85 + }, + unSelected: { + fill: '#55595f', + opacity: 1 + } + } + }, + value: { + alignRight: false, + style: { + fontSize: 12, + fill: '#ccc', + cursor: 'pointer' + }, + state: { + selectedHover: { + opacity: 0.85 + }, + unSelected: { + fill: '#D8D8D8' + } + } + }, + background: { + style: { + cursor: 'pointer' + }, + state: { + selectedHover: { + fill: '#404349' + }, + unSelectedHover: { + fill: '#404349' + } } }, - _uid: 316, + focus: false, + focusIconStyle: { + size: 10, + symbolType: + 'M8 1C11.866 1 15 4.13401 15 8C15 11.866 11.866 15 8 15C4.13401 15 1 11.866 1 8C1 4.13401 4.13401 1 8 1ZM8.75044 2.55077L8.75 3.75H7.25L7.25006 2.5507C4.81247 2.88304 2.88304 4.81247 2.5507 7.25006L3.75 7.25V8.75L2.55077 8.75044C2.8833 11.1878 4.81264 13.117 7.25006 13.4493L7.25 12.25H8.75L8.75044 13.4492C11.1876 13.1167 13.1167 11.1876 13.4492 8.75044L12.25 8.75V7.25L13.4493 7.25006C13.117 4.81264 11.1878 2.8833 8.75044 2.55077ZM8 5.5C9.38071 5.5 10.5 6.61929 10.5 8C10.5 9.38071 9.38071 10.5 8 10.5C6.61929 10.5 5.5 9.38071 5.5 8C5.5 6.61929 6.61929 5.5 8 5.5ZM8 7C7.44772 7 7 7.44772 7 8C7 8.55228 7.44772 9 8 9C8.55228 9 9 8.55228 9 8C9 7.44772 8.55228 7 8 7Z', + fill: '#333', + cursor: 'pointer' + }, + visible: true, + padding: { + right: 2, + bottom: 2, + left: 2, + top: 2 + } + }, + autoPage: true, + pager: { + space: 12, + handler: { + style: { + size: 10 + }, + space: 4 + } + }, + hover: true, + select: true, + selectMode: 'multiple', + allowAllCanceled: false, + items: [ + { + label: 'Africa', + shape: { + fill: '#1664FF', + symbolType: 'square', + stroke: ['#1664FF', false, false, false], + fillOpacity: 0.2, + strokeOpacity: 1, + opacity: 1, + texture: null, + texturePadding: null, + textureSize: null, + textureColor: null, + innerBorder: null, + outerBorder: null + }, + id: 'Africa', + index: 0 + }, + { + label: 'EU', + shape: { + fill: '#1AC6FF', + symbolType: 'square', + stroke: ['#1AC6FF', false, false, false], + fillOpacity: 0.2, + strokeOpacity: 1, + opacity: 1, + texture: null, + texturePadding: null, + textureSize: null, + textureColor: null, + innerBorder: null, + outerBorder: null + }, + id: 'EU', + index: 1 + }, + { + label: 'China', + shape: { + fill: '#FF8A00', + symbolType: 'square', + stroke: ['#FF8A00', false, false, false], + fillOpacity: 0.2, + strokeOpacity: 1, + opacity: 1, + texture: null, + texturePadding: null, + textureSize: null, + textureColor: null, + innerBorder: null, + outerBorder: null + }, + id: 'China', + index: 2 + }, + { + label: 'USA', + shape: { + fill: '#3CC780', + symbolType: 'square', + stroke: ['#3CC780', false, false, false], + fillOpacity: 0.2, + strokeOpacity: 1, + opacity: 1, + texture: null, + texturePadding: null, + textureSize: null, + textureColor: null, + innerBorder: null, + outerBorder: null + }, + id: 'USA', + index: 3 + } + ], + zIndex: 500, + maxWidth: 893, + maxHeight: 394, + defaultSelected: ['Africa', 'EU', 'China', 'USA'], + width: 58.083953857421875, + height: 27.400000000000002, + dx: 414.95802307128906, + dy: 0, + x: 44, + y: 444 + }, + _uid: 59, + type: 'group', + name: 'legend', + children: [ + { + attribute: { + x: 0, + y: 0, + pickable: true, + childrenPickable: true + }, + _uid: 60, type: 'group', - name: 'axis', + name: 'innerView', children: [ { attribute: { x: 0, - y: 0, - pickable: false + y: 0 }, - _uid: 338, + _uid: 61, type: 'group', children: [ { attribute: { x: 0, y: 0, - zIndex: 1 + cursor: 'pointer', + width: 53.083953857421875, + height: 19.6 }, - _uid: 339, + _uid: 62, type: 'group', - name: 'axis-container', + name: 'legendItem', children: [ { attribute: { - visible: true, - lineStyle: { - lineWidth: 1, - stroke: '#D9DDE4', - strokeOpacity: 1 - }, - startSymbol: { - visible: false, - autoRotate: true, - symbolType: 'triangle', - size: 12, - refX: 0, - refY: 0, - refAngle: 0, - style: { - fill: '#000', - zIndex: 1 - } - }, - endSymbol: { - visible: false, - autoRotate: true, - symbolType: 'triangle', - size: 12, - refX: 0, - refY: 0, - refAngle: 0, - style: { - fill: '#000', - zIndex: 1 - } - }, - points: [ - { - x: 0, - y: 0 - }, - { - x: 210, - y: 0 - } - ] - }, - _uid: 340, - type: 'group', - name: 'axis-line', - children: [ - { - attribute: { - points: [ - { - x: 0, - y: 0 - }, - { - x: 210, - y: 0 - } - ], - lineWidth: 1, - stroke: '#D9DDE4', - strokeOpacity: 1, - fill: false - }, - _uid: 341, - type: 'line', - name: 'axis-line-line', - children: [] - } - ] - }, - { - attribute: { - x: 0, - y: 0, + x: 7, + y: 9.8, pickable: false }, - _uid: 342, + _uid: 63, type: 'group', - name: 'axis-tick-container', children: [ { attribute: { - points: [ - { - x: 0, - y: 0 - }, - { - x: 0, - y: 4 - } - ], - lineWidth: 1, - stroke: '#D9DDE4', - strokeOpacity: 1 - }, - _uid: 343, - type: 'line', - name: 'axis-tick', - children: [] - }, - { - attribute: { - points: [ - { - x: 35, - y: 0 - }, - { - x: 35, - y: 4 - } - ], - lineWidth: 1, - stroke: '#D9DDE4', - strokeOpacity: 1 + x: 0, + y: 0, + symbolType: 'square', + strokeBoundsBuffer: 0, + fill: '#1664FF', + stroke: ['#1664FF', false, false, false], + fillOpacity: 1, + strokeOpacity: 1, + opacity: 1, + texture: null, + texturePadding: null, + textureSize: null, + textureColor: null, + innerBorder: null, + outerBorder: null, + size: 10, + cursor: 'pointer', + lineWidth: 0 }, - _uid: 344, - type: 'line', - name: 'axis-tick', + _uid: 64, + type: 'symbol', + name: 'legendItemShape', children: [] }, { attribute: { - points: [ - { - x: 70, - y: 0 - }, - { - x: 70, - y: 4 - } - ], - lineWidth: 1, - stroke: '#D9DDE4', - strokeOpacity: 1 + x: 11, + y: 0, + textAlign: 'start', + textBaseline: 'middle', + lineHeight: 15.600000000000001, + fontSize: 12, + fill: '#888c93', + cursor: 'pointer', + opacity: 1, + text: 'Africa' }, - _uid: 345, - type: 'line', - name: 'axis-tick', + _uid: 65, + type: 'text', + name: 'legendItemLabel', children: [] - }, + } + ] + } + ] + }, + { + attribute: { + x: 63.083953857421875, + y: 0, + cursor: 'pointer', + width: 36.21199035644531, + height: 19.6 + }, + _uid: 66, + type: 'group', + name: 'legendItem', + children: [ + { + attribute: { + x: 7, + y: 9.8, + pickable: false + }, + _uid: 67, + type: 'group', + children: [ { attribute: { - points: [ - { - x: 105, - y: 0 - }, - { - x: 105, - y: 4 - } - ], - lineWidth: 1, - stroke: '#D9DDE4', - strokeOpacity: 1 + x: 0, + y: 0, + symbolType: 'square', + strokeBoundsBuffer: 0, + fill: '#1AC6FF', + stroke: ['#1AC6FF', false, false, false], + fillOpacity: 1, + strokeOpacity: 1, + opacity: 1, + texture: null, + texturePadding: null, + textureSize: null, + textureColor: null, + innerBorder: null, + outerBorder: null, + size: 10, + cursor: 'pointer', + lineWidth: 0 }, - _uid: 346, - type: 'line', - name: 'axis-tick', + _uid: 68, + type: 'symbol', + name: 'legendItemShape', children: [] }, { attribute: { - points: [ - { - x: 140, - y: 0 - }, - { - x: 140, - y: 4 - } - ], - lineWidth: 1, - stroke: '#D9DDE4', - strokeOpacity: 1 + x: 11, + y: 0, + textAlign: 'start', + textBaseline: 'middle', + lineHeight: 15.600000000000001, + fontSize: 12, + fill: '#888c93', + cursor: 'pointer', + opacity: 1, + text: 'EU' }, - _uid: 347, - type: 'line', - name: 'axis-tick', + _uid: 69, + type: 'text', + name: 'legendItemLabel', children: [] - }, + } + ] + } + ] + }, + { + attribute: { + x: 109.29594421386719, + y: 0, + cursor: 'pointer', + width: 51.895965576171875, + height: 19.6 + }, + _uid: 70, + type: 'group', + name: 'legendItem', + children: [ + { + attribute: { + x: 7, + y: 9.8, + pickable: false + }, + _uid: 71, + type: 'group', + children: [ { attribute: { - points: [ - { - x: 175, - y: 0 - }, - { - x: 175, - y: 4 - } - ], - lineWidth: 1, - stroke: '#D9DDE4', - strokeOpacity: 1 + x: 0, + y: 0, + symbolType: 'square', + strokeBoundsBuffer: 0, + fill: '#FF8A00', + stroke: ['#FF8A00', false, false, false], + fillOpacity: 1, + strokeOpacity: 1, + opacity: 1, + texture: null, + texturePadding: null, + textureSize: null, + textureColor: null, + innerBorder: null, + outerBorder: null, + size: 10, + cursor: 'pointer', + lineWidth: 0 }, - _uid: 348, - type: 'line', - name: 'axis-tick', + _uid: 72, + type: 'symbol', + name: 'legendItemShape', children: [] }, { attribute: { - points: [ - { - x: 210, - y: 0 - }, - { - x: 210, - y: 4 - } - ], - lineWidth: 1, - stroke: '#D9DDE4', - strokeOpacity: 1 + x: 11, + y: 0, + textAlign: 'start', + textBaseline: 'middle', + lineHeight: 15.600000000000001, + fontSize: 12, + fill: '#888c93', + cursor: 'pointer', + opacity: 1, + text: 'China' }, - _uid: 349, - type: 'line', - name: 'axis-tick', + _uid: 73, + type: 'text', + name: 'legendItemLabel', children: [] } ] - }, + } + ] + }, + { + attribute: { + x: 171.19190979003906, + y: 0, + cursor: 'pointer', + width: 44.035980224609375, + height: 19.6 + }, + _uid: 74, + type: 'group', + name: 'legendItem', + children: [ { attribute: { - x: 0, - y: 0, + x: 7, + y: 9.8, pickable: false }, - _uid: 350, + _uid: 75, type: 'group', - name: 'axis-label-container', children: [ { attribute: { x: 0, y: 0, - pickable: false + symbolType: 'square', + strokeBoundsBuffer: 0, + fill: '#3CC780', + stroke: ['#3CC780', false, false, false], + fillOpacity: 1, + strokeOpacity: 1, + opacity: 1, + texture: null, + texturePadding: null, + textureSize: null, + textureColor: null, + innerBorder: null, + outerBorder: null, + size: 10, + cursor: 'pointer', + lineWidth: 0 }, - _uid: 351, - type: 'group', - name: 'axis-label-container-layer-0', - children: [ - { - attribute: { - x: 0, - y: 8, - text: -1000, - lineHeight: 12, - textAlign: 'center', - textBaseline: 'top', - fontSize: 12, - fill: '#89909d', - fontWeight: 'normal', - fillOpacity: 1 - }, - _uid: 352, - type: 'text', - name: 'axis-label', - children: [] - }, - { - attribute: { - x: 35, - y: 8, - text: -500, - lineHeight: 12, - textAlign: 'center', - textBaseline: 'top', - fontSize: 12, - fill: '#89909d', - fontWeight: 'normal', - fillOpacity: 1 - }, - _uid: 353, - type: 'text', - name: 'axis-label', - children: [] - }, - { - attribute: { - x: 70, - y: 8, - text: 0, - lineHeight: 12, - textAlign: 'center', - textBaseline: 'top', - fontSize: 12, - fill: '#89909d', - fontWeight: 'normal', - fillOpacity: 1 - }, - _uid: 354, - type: 'text', - name: 'axis-label', - children: [] - }, - { - attribute: { - x: 105, - y: 8, - text: 500, - lineHeight: 12, - textAlign: 'center', - textBaseline: 'top', - fontSize: 12, - fill: '#89909d', - fontWeight: 'normal', - fillOpacity: 1 - }, - _uid: 355, - type: 'text', - name: 'axis-label', - children: [] - }, - { - attribute: { - x: 140, - y: 8, - text: 1000, - lineHeight: 12, - textAlign: 'center', - textBaseline: 'top', - fontSize: 12, - fill: '#89909d', - fontWeight: 'normal', - fillOpacity: 1 - }, - _uid: 356, - type: 'text', - name: 'axis-label', - children: [] - }, - { - attribute: { - x: 175, - y: 8, - text: 1500, - lineHeight: 12, - textAlign: 'center', - textBaseline: 'top', - fontSize: 12, - fill: '#89909d', - fontWeight: 'normal', - fillOpacity: 1 - }, - _uid: 357, - type: 'text', - name: 'axis-label', - children: [] - }, - { - attribute: { - x: 210, - y: 8, - text: 2000, - lineHeight: 12, - textAlign: 'center', - textBaseline: 'top', - fontSize: 12, - fill: '#89909d', - fontWeight: 'normal', - fillOpacity: 1 - }, - _uid: 358, - type: 'text', - name: 'axis-label', - children: [] - } - ] + _uid: 76, + type: 'symbol', + name: 'legendItemShape', + children: [] + }, + { + attribute: { + x: 11, + y: 0, + textAlign: 'start', + textBaseline: 'middle', + lineHeight: 15.600000000000001, + fontSize: 12, + fill: '#888c93', + cursor: 'pointer', + opacity: 1, + text: 'USA' + }, + _uid: 77, + type: 'text', + name: 'legendItemLabel', + children: [] } ] } @@ -1039,177 +3385,68 @@ const json = { }, { attribute: { - pickable: false, - zIndex: 0 + direction: 'horizontal', + round: true, + sliderSize: 20, + sliderStyle: { + fill: '#ffffff', + fillOpacity: 0.5 + }, + railStyle: { + fill: 'rgba(0, 0, 0, .0)' + }, + padding: 2, + scrollRange: [0, 1], + zIndex: 500, + x: 68, + y: 428, + width: 845, + height: 0, + range: [0, 1] }, - _uid: 359, + _uid: 123, type: 'group', - name: 'VGRAMMAR_MARK_10', + name: 'scrollbar', children: [ { - attribute: { - sectorStyle: { - fill: '#b2bacf', - opacity: 0.2 - }, - start: { - x: 0, - y: 0 - }, - end: { - x: 0, - y: 0 - } - }, - _uid: 360, + attribute: {}, + _uid: 124, type: 'group', - name: 'crosshair', + name: 'scrollbar-container', children: [ { attribute: { - innerRadius: 0, - fill: '#b2bacf', - opacity: 0.2 + x: 0, + y: 0, + width: 845, + height: 0, + fill: 'rgba(0, 0, 0, .0)' + }, + _uid: 125, + type: 'rect', + name: 'scrollbar-rail', + children: [] + }, + { + attribute: { + x: 2, + y: 2, + width: 841, + height: -4, + cornerRadius: -4, + fill: '#ffffff', + fillOpacity: 0.5, + boundsPadding: [2, 2, 2, 2], + pickMode: 'imprecise' }, - _uid: 361, - type: 'arc', - name: 'crosshair-sector', + _uid: 126, + type: 'rect', + name: 'slider', children: [] } ] } ] - }, - { - attribute: { - pickable: false, - zIndex: 0 - }, - _uid: 362, - type: 'group', - name: 'VGRAMMAR_MARK_11', - children: [ - { - attribute: { - y: 250, - angle: 0.5235987755982991, - anchor: [250, 250], - max: 432, - q3: 404, - median: 376, - q1: 369, - min: 355, - boxHeight: 30, - ruleHeight: 20, - stroke: 'black', - fill: '#6690F2', - opacity: 1 - }, - _uid: 363, - type: 'glyph', - children: [] - }, - { - attribute: { - y: 250, - angle: 1.5707963267948968, - anchor: [250, 250], - max: 453, - q3: 390, - median: 348, - q1: 341, - min: 327, - boxHeight: 30, - ruleHeight: 20, - stroke: 'black', - fill: '#70D6A3', - opacity: 1 - }, - _uid: 369, - type: 'glyph', - children: [] - }, - { - attribute: { - y: 250, - angle: 2.6179938779914944, - anchor: [250, 250], - max: 411, - q3: 404, - median: 334, - q1: 313, - min: 285, - boxHeight: 30, - ruleHeight: 20, - stroke: 'black', - fill: '#B4E6E2', - opacity: 1 - }, - _uid: 375, - type: 'glyph', - children: [] - }, - { - attribute: { - y: 250, - angle: 3.6651914291880923, - anchor: [250, 250], - max: 418, - q3: 390, - median: 383, - q1: 376, - min: 355, - boxHeight: 30, - ruleHeight: 20, - stroke: 'black', - fill: '#63B5FC', - opacity: 1 - }, - _uid: 381, - type: 'glyph', - children: [] - }, - { - attribute: { - y: 250, - angle: 4.71238898038469, - anchor: [250, 250], - max: 404, - q3: 355, - median: 348, - q1: 313, - min: 292, - boxHeight: 30, - ruleHeight: 20, - stroke: 'black', - fill: '#FF8F62', - opacity: 1 - }, - _uid: 387, - type: 'glyph', - children: [] - }, - { - attribute: { - y: 250, - angle: 5.759586531581287, - anchor: [250, 250], - max: 418, - q3: 390, - median: 383, - q1: 369, - min: 341, - boxHeight: 30, - ruleHeight: 20, - stroke: 'black', - fill: '#FFDC83', - opacity: 1 - }, - _uid: 393, - type: 'glyph', - children: [] - } - ] } ] } @@ -1244,10 +3481,10 @@ function _add(group, json) { } else if (json.type === 'symbol') { const s = createSymbol({ ...json.attribute, keepDirIn3d: true }); // s.animate().to({ scaleX: 0.5, scaleY: 0.5 }, 1000, 'linear'); - s.addEventListener('mouseenter', () => { - s.setAttribute('fill', 'red'); - }); - console.log(s); + // s.addEventListener('mouseenter', () => { + // s.setAttribute('fill', 'red'); + // }); + // console.log(s); group.add(s); } else if (json.type === 'rect') { group.add(createRect(json.attribute)); @@ -1274,9 +3511,9 @@ export const page = () => { canvas: c as HTMLCanvasElement, width: 802, height: 500, - disableDirtyBounds: true, - canvasControled: true, - autoRender: true + // disableDirtyBounds: true, + // canvasControled: true, + autoRender: false }); const layer = stage.at(0); @@ -1284,15 +3521,20 @@ export const page = () => { json.children[0].children.forEach(item => { _add(layer, item); }); - stage.set3dOptions({ - alpha: 0, - // beta: 0, - enable: true - }); - stage.children[0].children[0].setMode('3d'); + const t = performance.now(); + const b = layer.AABBBounds; + console.log(performance.now() - t); + console.log(b); + // stage.set3dOptions({ + // alpha: 0, + // // beta: 0, + // enable: true + // }); + + // stage.children[0].children[0].setMode('3d'); - const group = stage.defaultLayer.getChildren()[0] as IGroup; + // const group = stage.defaultLayer.getChildren()[0] as IGroup; // group.setAttribute('fill', 'green'); // group @@ -1308,17 +3550,17 @@ export const page = () => { // .wait(3000) // .play(new GroupFadeOut(1000, 'quadIn')); - stage.render(undefined, {}); + // stage.render(undefined, {}); - const button = document.createElement('button'); - button.innerHTML = 'click'; - document.body.appendChild(button); - button.addEventListener('click', () => { - stage.getElementsByType('rect').forEach(r => { - r.setAttribute('fill', 'red'); - }); - stage.render(undefined, {}); - }); + // const button = document.createElement('button'); + // button.innerHTML = 'click'; + // document.body.appendChild(button); + // button.addEventListener('click', () => { + // stage.getElementsByType('rect').forEach(r => { + // r.setAttribute('fill', 'red'); + // }); + // stage.render(undefined, {}); + // }); - stage.enableView3dTransform(); + // stage.enableView3dTransform(); }; diff --git a/packages/vrender/__tests__/browser/src/pages/theme.ts b/packages/vrender/__tests__/browser/src/pages/theme.ts index f988a9bb2..cf126f83d 100644 --- a/packages/vrender/__tests__/browser/src/pages/theme.ts +++ b/packages/vrender/__tests__/browser/src/pages/theme.ts @@ -31,7 +31,7 @@ export const page = () => { y: 200, width: 100, height: 100, - fill: colorPools[3] + fill: 'green' }); l11.name = 'l11'; const l12 = createGroup({ From 3e41660291f8b7e7750e3ad7a640e7694297c4de Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Fri, 13 Oct 2023 17:45:24 +0800 Subject: [PATCH 02/40] feat: fix quick measure text issue, optmize isSafari performance --- .../__tests__/browser/src/pages/chart.ts | 1 - packages/vrender-core/src/core/global.ts | 15 ++++++- .../canvas/contributions/browser/context.ts | 22 ++++++---- .../__tests__/browser/src/pages/text.ts | 40 +++++++++++++++++++ 4 files changed, 68 insertions(+), 10 deletions(-) diff --git a/packages/vrender-core/__tests__/browser/src/pages/chart.ts b/packages/vrender-core/__tests__/browser/src/pages/chart.ts index 235379ab2..681762776 100644 --- a/packages/vrender-core/__tests__/browser/src/pages/chart.ts +++ b/packages/vrender-core/__tests__/browser/src/pages/chart.ts @@ -1096,7 +1096,6 @@ export const page = () => { // .play(new GroupFadeIn(1000, 'quadIn')) // .wait(3000) // .play(new GroupFadeOut(1000, 'quadIn')); - stage.render(undefined, {}); const button = document.createElement('button'); diff --git a/packages/vrender-core/src/core/global.ts b/packages/vrender-core/src/core/global.ts index 4317e5da8..92e93a871 100644 --- a/packages/vrender-core/src/core/global.ts +++ b/packages/vrender-core/src/core/global.ts @@ -19,6 +19,8 @@ const defaultEnv: EnvType = 'browser'; @injectable() export class DefaultGlobal implements IGlobal { private _env: EnvType; + private _isSafari?: boolean; + private _isChrome?: boolean; get env(): EnvType { return this._env; } @@ -303,17 +305,26 @@ export class DefaultGlobal implements IGlobal { } isChrome(): boolean { + if (this._isChrome != null) { + return this._isChrome; + } if (!this._env) { this.setEnv('browser'); } - return this._env === 'browser' && navigator.userAgent.indexOf('Chrome') > -1; + this._isChrome = this._env === 'browser' && navigator.userAgent.indexOf('Chrome') > -1; + return this._isChrome; } isSafari(): boolean { + if (this._isSafari != null) { + return this._isSafari; + } if (!this._env) { this.setEnv('browser'); } - return this._env === 'browser' && /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent); + this._isSafari = + this._env === 'browser' && /Safari/.test(navigator.userAgent) && !/Chrome/.test(navigator.userAgent); + return this._isSafari; } getNativeAABBBounds(dom: string | HTMLElement | any): IAABBBoundsLike { diff --git a/packages/vrender-kits/src/canvas/contributions/browser/context.ts b/packages/vrender-kits/src/canvas/contributions/browser/context.ts index 41a34095b..3d118d181 100644 --- a/packages/vrender-kits/src/canvas/contributions/browser/context.ts +++ b/packages/vrender-kits/src/canvas/contributions/browser/context.ts @@ -841,14 +841,22 @@ export class BrowserContext2d implements IContext2d { return this.nativeContext.measureText(text); } if (!this.mathTextMeasure) { - this.mathTextMeasure = application.graphicUtil.createTextMeasureInstance({}, {}, () => this.canvas); + this.mathTextMeasure = application.graphicUtil.createTextMeasureInstance({}, {}, () => this.canvas.nativeCanvas); + } + + const fontFamily = this.fontFamily ?? DefaultTextStyle.fontFamily; + const fontSize = this.fontSize ?? DefaultTextStyle.fontSize; + if ( + this.mathTextMeasure.textSpec.fontFamily !== fontFamily || + this.mathTextMeasure.textSpec.fontSize !== fontSize + ) { + this.mathTextMeasure.textSpec.fontFamily = fontFamily; + this.mathTextMeasure.textSpec.fontSize = fontSize; + this.mathTextMeasure._numberCharSize = null; + this.mathTextMeasure._fullCharSize = null; + this.mathTextMeasure._letterCharSize = null; + this.mathTextMeasure._specialCharSizeMap = {}; } - this.mathTextMeasure.textSpec.fontFamily = this.fontFamily ?? DefaultTextStyle.fontFamily; - this.mathTextMeasure.textSpec.fontSize = this.fontSize ?? DefaultTextStyle.fontSize; - this.mathTextMeasure._numberCharSize = null; - this.mathTextMeasure._fullCharSize = null; - this.mathTextMeasure._letterCharSize = null; - this.mathTextMeasure._specialCharSizeMap = {}; return this.mathTextMeasure.measure(text, method); } diff --git a/packages/vrender/__tests__/browser/src/pages/text.ts b/packages/vrender/__tests__/browser/src/pages/text.ts index 074e248aa..acb24b209 100644 --- a/packages/vrender/__tests__/browser/src/pages/text.ts +++ b/packages/vrender/__tests__/browser/src/pages/text.ts @@ -7,12 +7,45 @@ import { createRect, createCircle, IGraphic, + createGroup, + vglobal, createWrapText } from '@visactor/vrender'; import { addShapesToStage, colorPools } from '../utils'; // global.setEnv('browser'); +const textStr = + '蛋糕吃起来像已经放了很多年似的。那天晚上达力神气活现地在起居室里走来走去,向家人展示他那套新校服。斯梅廷中学的男生制服是棕红色燕尾服,橙色短灯笼裤和一顶叫硬草帽2的扁平草帽。他们还配了一支多节的手杖,趁老师不注意时用来互相打斗,这也许是对未来生活的一种很好的训练吧。弗农姨父看着身穿崭新灯笼裤的达力,他的声音都沙哑了,他说这是他平生感到最自豪的一刻。佩妮姨妈突然哭起来,她说她的宝贝疙瘩已经长大了,长得这么帅,简直让她不能相信。哈利却不敢开口。为了强忍住不笑,他的两条肋骨都快折断了。第二天早上哈利来吃早饭时,发现厨房里有一股难闻的味儿。这气味似乎是从污水池里的一只大铁盆里散发出来的。他去看了一眼,发现一盆灰黑色的水里泡着像破抹布似的东西。「这是什么?」他问佩妮姨妈。她把嘴唇抿紧,每当哈利大胆问问题时,她总是这样。「你的新校服呀。」她说。哈利又朝盆里扫了一眼。「哦,」他说,「我不知道还得泡得这么湿。」「别冒傻气,」佩妮姨妈斥责说,「我把达力的旧衣服染好给你用。等我染好以后,穿起来就会跟别人的一模一样。」哈利对此非常怀疑,但他还是觉得最好不要跟她争论。他坐下来吃早饭时,竭力不去想第一天去石墙中学上学自己会是什么模样,八成像披着大象的旧象皮吧。达力和弗农姨父进来时,都因为哈利那套新校服散发的味道皱起了鼻子。弗农姨父像通常一样打开报纸,达力则把他从不离身的斯梅廷手杖啪的一声放到桌上。他们听到信箱咔哒响了一声,一些信落到大门口的擦脚垫上。「去拿信,达力。」弗农姨父从报纸后边说。「叫哈利去捡。」「哈利去捡。」「达力去捡。」「用你的斯梅廷手杖赶他去捡。」哈利躲闪着斯梅廷手杖,去捡信。擦脚垫上有三样邮件:一封是弗农姨父的姐姐玛姬姑妈寄来的明信片,她现在在怀特岛3度假;另一封是看来像账单的棕色信封;还有一封是寄给哈利的信。哈利把信捡起来,目不转睛地盯着看,心里像有一根很粗的橡皮筋嘣的一声弹了起来,嗡嗡直响。活到现在,从来没有人给他写过信。这封信可能是谁写的呢?他没有朋友,没有另外的亲戚,他没有借书证,因此不会收到图书馆催还图书的通知单。可现在确实有一封信,地址清清楚楚,不会有错:萨里郡小惠金区女贞路4号楼梯下的碗柜哈利波特先生收信封是用厚重的羊皮纸做的,地址是甩翡翠绿的墨水写的。没有贴邮票。哈利用颤抖的手把信封翻转过来,只见上边有一块蜡封、一个盾牌纹章,大写「H」字母的周围圈着一头狮子、一只鹰、一只獾和一条蛇。「小子,快拿过来!」弗农姨父在厨房里喊起来,「你在干什么,在检查邮包有没有炸弹吗?」他开了个玩笑,自己也咯咯地笑开了。哈利回到厨房里,目光一直盯着他的那封信。他把账单和明信片递给弗农姨父,然后坐下来,慢慢拆开他那个黄色的信封。弗农姨父拆开有账单的信封,厌恶地哼了一声,又把明信片轻轻翻转过来。「玛姬病倒了,」他对佩妮姨妈说,「吃了有问题的油螺……」「老爸!」达力突然说,「老爸,哈利收到什么东西了!」哈利刚要打开他那封写在厚重羊皮纸上的信,信却被弗农姨父一把从手中抢过去了。「那是写给我的!」哈利说,想把信夺回来。「谁会给你写信?」弗农姨父讥讽地说,用一只手把信纸抖开,朝它瞥了一眼。他的脸一下子由红变青,比红绿灯变得还快。事情到这里并没结束。几秒钟之内他的脸就变得像灰色的麦片粥一样灰白了。「佩——佩——佩妮!」他气喘吁吁地说。达力想把信抢过来看,可是弗农姨父把信举得老高,他够不着。佩妮姨妈好奇地把信拿过去,刚看第一行,她就好像要晕倒了。她抓住喉咙,噎了一下,像要背过气去。「德思礼!哎呀!我的天……德思礼!」他们俩你看我,我看你,都不说话,似乎忘了哈利和达力还在屋里。达力是不习惯被人冷落的,他用斯梅廷手杖朝他父亲的头上狠狠地敲了一下。「我要看那封信。」他大声说。「我要看。」哈利气呼呼地说,「因为那封信是写给我的。」「你们俩,统统给我出去。」弗农姨父用低沉而沙哑的声音说,把信重新塞到信封里。哈利没有动。「我要我的信!」他大叫说。「让我看!」达力命令说。「出去!」弗农姨父吼了起来,揪住哈利和达力的脖领,把他们俩扔到了走廊里,砰地一'; + +function performance(stage: any) { + vglobal.measureTextMethod = 'quick'; + const textList = new Array(3000).fill(0).map(item => { + const start = Math.floor(textStr.length * Math.random()); + // return createText({ + // text: textStr.substring(start, Math.min(textStr.length - start - 1, 10)), + // fill: true, + // fontSize: 16 + // }) + return createText({ + text: new Array(10) + .fill(0) + .map(item => String.fromCharCode(97 + Math.floor(Math.random() * 24))) + .join(''), + fill: true, + fontSize: 16 + }); + }); + + const group = createGroup({}); + textList.forEach(t => group.add(t)); + // stage.defaultLayer.add(group); + console.time(); + const bounds = group.AABBBounds; + console.timeEnd(); + console.log(bounds); +} + export const page = () => { const graphics: IGraphic[] = []; const t = createText({ @@ -118,4 +151,11 @@ export const page = () => { graphics.forEach(g => { stage.defaultLayer.add(g); }); + + const btn = document.createElement('button'); + btn.innerHTML = '点击'; + document.body.appendChild(btn); + btn.addEventListener('click', () => { + performance(stage); + }); }; From 63058717f37389009971da8440f0ec8c7f0317a4 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Mon, 16 Oct 2023 10:55:46 +0800 Subject: [PATCH 03/40] feat: optmize little performance --- .../src/allocator/bounds-allocate.ts | 48 +++++++++++++++++++ .../src/allocator/canvas-allocate.ts | 7 +++ .../vrender-core/src/core/graphic-utils.ts | 5 +- packages/vrender-core/src/core/window.ts | 1 - packages/vrender-core/src/graphic/symbol.ts | 10 ++-- .../vrender-core/src/interface/allocator.ts | 1 + packages/vrender-core/src/modules.ts | 4 +- .../vrender-core/src/picker/pick-modules.ts | 4 +- .../contributions/render/draw-contribution.ts | 4 +- .../src/picker/canvas-picker-service.ts | 10 +--- 10 files changed, 73 insertions(+), 21 deletions(-) create mode 100644 packages/vrender-core/src/allocator/bounds-allocate.ts diff --git a/packages/vrender-core/src/allocator/bounds-allocate.ts b/packages/vrender-core/src/allocator/bounds-allocate.ts new file mode 100644 index 000000000..f678ada0f --- /dev/null +++ b/packages/vrender-core/src/allocator/bounds-allocate.ts @@ -0,0 +1,48 @@ +import type { IAABBBounds, IAABBBoundsLike } from '@visactor/vutils'; +import { AABBBounds } from '@visactor/vutils'; +import type { Releaseable, IAllocate } from '../interface'; + +export const BoundsAllocate = Symbol.for('BoundsAllocate'); + +export class DefaultBoundsAllocate implements IAllocate, Releaseable { + protected pools: IAABBBounds[] = []; + constructor() { + // 默认添加10个 + for (let i = 0; i < 10; i++) { + this.pools.push(new AABBBounds()); + } + } + allocate(x1: number, y1: number, x2: number, y2: number): IAABBBounds { + if (!this.pools.length) { + return new AABBBounds().setValue(x1, y1, x2, y2); + } + const b = this.pools.pop(); + b.x1 = x1; + b.y1 = y1; + b.x2 = x2; + b.y2 = y2; + return b; + } + allocateByObj(b: IAABBBounds): IAABBBounds { + if (!this.pools.length) { + return new AABBBounds(b as any); + } + const _b = this.pools.pop() as any; + _b.x1 = b.x1; + _b.y1 = b.y1; + _b.x2 = b.x2; + _b.y2 = b.y2; + return _b; + } + free(b: IAABBBounds) { + this.pools.push(b); + } + get length(): number { + return this.pools.length; + } + release(...params: any): void { + this.pools = []; + } +} + +export const boundsAllocate = new DefaultBoundsAllocate(); diff --git a/packages/vrender-core/src/allocator/canvas-allocate.ts b/packages/vrender-core/src/allocator/canvas-allocate.ts index f91168ab1..8d3883c9e 100644 --- a/packages/vrender-core/src/allocator/canvas-allocate.ts +++ b/packages/vrender-core/src/allocator/canvas-allocate.ts @@ -4,6 +4,13 @@ import { wrapCanvas } from '../canvas/util'; export class DefaultCanvasAllocate implements IAllocate, Releaseable { protected pools: ICanvas[] = []; + protected _commonCanvas: any; + getCommonCanvas(): ICanvas { + if (!this._commonCanvas) { + this._commonCanvas = this.allocate({ width: 100, height: 100, dpr: 2 }); + } + return this._commonCanvas; + } allocate(data: { width: number; height: number; dpr: number }): ICanvas { if (!this.pools.length) { return wrapCanvas({ diff --git a/packages/vrender-core/src/core/graphic-utils.ts b/packages/vrender-core/src/core/graphic-utils.ts index a01bc42f8..77de58ba6 100644 --- a/packages/vrender-core/src/core/graphic-utils.ts +++ b/packages/vrender-core/src/core/graphic-utils.ts @@ -10,6 +10,7 @@ import type { IMatrix, IPointLike, ITextMeasureOption } from '@visactor/vutils'; import { Matrix, TextMeasure } from '@visactor/vutils'; import type { IGraphicUtil, ITransformUtil, TransformType } from '../interface/core'; import { VGlobal } from '../constants'; +import { canvasAllocate } from '../allocator/canvas-allocate'; @injectable() export class DefaultGraphicUtil implements IGraphicUtil { @@ -42,9 +43,7 @@ export class DefaultGraphicUtil implements IGraphicUtil { if (this.configured) { return; } - const canvas = wrapCanvas({ - nativeCanvas: global.createCanvas({ width: 100, height: 100 }) - }); + const canvas = canvasAllocate.getCommonCanvas(); this.canvas = canvas; this.context = canvas.getContext('2d'); this.contributions.getContributions().forEach(contribution => { diff --git a/packages/vrender-core/src/core/window.ts b/packages/vrender-core/src/core/window.ts index 026e43e2f..8d355b5c2 100644 --- a/packages/vrender-core/src/core/window.ts +++ b/packages/vrender-core/src/core/window.ts @@ -98,7 +98,6 @@ export class DefaultWindow implements IWindow { // handlerContribution.configure(this, this.global); // }); this.actived = true; - this._handler; } get style(): CSSStyleDeclaration | Record { diff --git a/packages/vrender-core/src/graphic/symbol.ts b/packages/vrender-core/src/graphic/symbol.ts index 0225f9444..d659c79f1 100644 --- a/packages/vrender-core/src/graphic/symbol.ts +++ b/packages/vrender-core/src/graphic/symbol.ts @@ -12,6 +12,8 @@ import { SVG_PARSE_ATTRIBUTE_MAP, SVG_PARSE_ATTRIBUTE_MAP_KEYS, SYMBOL_NUMBER_TY import { XMLParser } from '../common/xml'; import { isSvg } from '../common/xml/parser'; +const _tempBounds = new AABBBounds(); + const SYMBOL_UPDATE_TAG_KEY = ['symbolType', 'size', ...GRAPHIC_UPDATE_TAG_KEY]; /** @@ -74,7 +76,7 @@ export class Symbol extends Graphic implements ISymbol return null; } const path = isArray(svg.path) ? svg.path : [svg.path]; - const b = new AABBBounds(); + _tempBounds.clear(); const cacheList: { path: CustomPath2D; attribute: Record }[] = []; path.forEach((item: any) => { const cache = new CustomPath2D().fromString(item.d); @@ -91,10 +93,10 @@ export class Symbol extends Graphic implements ISymbol path: cache, attribute }); - b.union(cache.bounds); + _tempBounds.union(cache.bounds); }); - const width = b.width(); - const height = b.height(); + const width = _tempBounds.width(); + const height = _tempBounds.height(); // 规范化到1 const maxWH = max(width, height); const scale = 1 / maxWH; diff --git a/packages/vrender-core/src/interface/allocator.ts b/packages/vrender-core/src/interface/allocator.ts index ea21f3e0f..812448677 100644 --- a/packages/vrender-core/src/interface/allocator.ts +++ b/packages/vrender-core/src/interface/allocator.ts @@ -11,6 +11,7 @@ import type { IText } from './graphic/text'; export interface IAllocate { allocate: (...d: any) => T; + getCommon?: () => T; allocateByObj: (obj: T) => T; free: (d: T) => void; length: number; diff --git a/packages/vrender-core/src/modules.ts b/packages/vrender-core/src/modules.ts index 467abcee3..d88a0dad5 100644 --- a/packages/vrender-core/src/modules.ts +++ b/packages/vrender-core/src/modules.ts @@ -10,7 +10,7 @@ import loadRenderContributions from './render/contributions/modules'; // import loadCanvasContributions from './canvas/contributions/modules'; import { LayerService } from './core/constants'; // import { IMat4Allocate, IMatrixAllocate, Mat4Allocate, MatrixAllocate } from './allocator/matrix-allocate'; -import { GlobalPickerService } from './picker/constants'; +// import { GlobalPickerService } from './picker/constants'; import type { IGlobal, IGraphicService, IPickerService } from './interface'; import { application } from './application'; import type { IGraphicUtil, ILayerService, ITransformUtil } from './interface/core'; @@ -50,6 +50,6 @@ application.graphicService = graphicService; // export const rectAllocate = container.get(RectAllocate); // export const symbolAllocate = container.get(SymbolAllocate); // export const textAllocate = container.get(TextAllocate); -export const pickerService = container.get(GlobalPickerService); +// export const pickerService = container.get(GlobalPickerService); export const layerService = container.get(LayerService); application.layerService = layerService; diff --git a/packages/vrender-core/src/picker/pick-modules.ts b/packages/vrender-core/src/picker/pick-modules.ts index 2add82cff..f35710cd0 100644 --- a/packages/vrender-core/src/picker/pick-modules.ts +++ b/packages/vrender-core/src/picker/pick-modules.ts @@ -14,8 +14,8 @@ import { bindContributionProvider } from '../common/contribution-provider'; export default new ContainerModule(bind => { bind(PickerService).toService(GlobalPickerService); - bind(DefaultGlobalPickerService).toSelf().inSingletonScope(); - bind(GlobalPickerService).toService(DefaultGlobalPickerService); + // bind(DefaultGlobalPickerService).toSelf().inSingletonScope(); + // bind(GlobalPickerService).toService(DefaultGlobalPickerService); // interceptor bind(Canvas3DPickItemInterceptor).toSelf().inSingletonScope(); diff --git a/packages/vrender-core/src/render/contributions/render/draw-contribution.ts b/packages/vrender-core/src/render/contributions/render/draw-contribution.ts index 7539b30ca..8d47c73a3 100644 --- a/packages/vrender-core/src/render/contributions/render/draw-contribution.ts +++ b/packages/vrender-core/src/render/contributions/render/draw-contribution.ts @@ -27,6 +27,7 @@ import { DrawItemInterceptor } from './draw-interceptor'; import { createColor } from '../../../common/canvas-utils'; import type { ILayerService } from '../../../interface/core'; import { VGlobal } from '../../../constants'; +import { boundsAllocate } from '../../../allocator/bounds-allocate'; /** * 默认的渲染contribution,基于树状结构针对图元的渲染 @@ -182,7 +183,7 @@ export class DefaultDrawContribution implements IDrawContribution { return; } - const tempBounds = this.dirtyBounds.clone(); + const tempBounds = boundsAllocate.allocateByObj(this.dirtyBounds); // 变换dirtyBounds const m = group.globalTransMatrix.getInverse(); @@ -221,6 +222,7 @@ export class DefaultDrawContribution implements IDrawContribution { }); this.dirtyBounds.copy(tempBounds); + boundsAllocate.free(tempBounds); } protected _increaseRender(group: IGroup, drawContext: IDrawContext) { diff --git a/packages/vrender-kits/src/picker/canvas-picker-service.ts b/packages/vrender-kits/src/picker/canvas-picker-service.ts index 0cc2d8806..c705501e4 100644 --- a/packages/vrender-kits/src/picker/canvas-picker-service.ts +++ b/packages/vrender-kits/src/picker/canvas-picker-service.ts @@ -40,6 +40,7 @@ import { CanvasTextPicker, CanvasRichTextPicker } from './contributions/constants'; +import { canvasAllocate } from '../../../vrender-core/src/allocator/canvas-allocate'; // 默认的pick-service,提供基本的最优选中策略,尽量不需要用户自己实现contribution // 用户可以写plugin @@ -98,14 +99,7 @@ export class DefaultCanvasPickerService extends DefaultPickService implements IP // }); // 创建pick canvas - const options = { - width: 100, - height: 100, - nativeCanvas: global.createCanvas({ width: 100, height: 100 }), - id: 'for-pick' - }; - - this.pickCanvas = wrapCanvas(options); + this.pickCanvas = canvasAllocate.getCommonCanvas(); this.pickContext = this.pickCanvas.getContext('2d'); } From 9a9b97df78177615ca5832aa80362ca4ba05eab3 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Tue, 17 Oct 2023 19:52:42 +0800 Subject: [PATCH 04/40] fix: fix import issue --- packages/vrender-core/src/index.ts | 1 + .../src/picker/canvas-picker-service.ts | 3 +-- .../__tests__/browser/src/pages/chart.ts | 20 +++++++++++++++---- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/packages/vrender-core/src/index.ts b/packages/vrender-core/src/index.ts index 47a6a9a1b..a98328cec 100644 --- a/packages/vrender-core/src/index.ts +++ b/packages/vrender-core/src/index.ts @@ -43,6 +43,7 @@ export * from './common/enums'; export * from './common/generator'; export * from './plugins/constants'; export * from './allocator/matrix-allocate'; +export * from './allocator/canvas-allocate'; export * from './animate/default-ticker'; export { wrapCanvas, wrapContext } from './canvas/util'; diff --git a/packages/vrender-kits/src/picker/canvas-picker-service.ts b/packages/vrender-kits/src/picker/canvas-picker-service.ts index c705501e4..24ab64bb0 100644 --- a/packages/vrender-kits/src/picker/canvas-picker-service.ts +++ b/packages/vrender-kits/src/picker/canvas-picker-service.ts @@ -10,7 +10,7 @@ import { DrawContribution, PickItemInterceptor, VGlobal, - wrapCanvas + canvasAllocate } from '@visactor/vrender-core'; import type { ICanvas, @@ -40,7 +40,6 @@ import { CanvasTextPicker, CanvasRichTextPicker } from './contributions/constants'; -import { canvasAllocate } from '../../../vrender-core/src/allocator/canvas-allocate'; // 默认的pick-service,提供基本的最优选中策略,尽量不需要用户自己实现contribution // 用户可以写plugin diff --git a/packages/vrender/__tests__/browser/src/pages/chart.ts b/packages/vrender/__tests__/browser/src/pages/chart.ts index 9b0725761..f83d52bdc 100644 --- a/packages/vrender/__tests__/browser/src/pages/chart.ts +++ b/packages/vrender/__tests__/browser/src/pages/chart.ts @@ -3521,11 +3521,23 @@ export const page = () => { json.children[0].children.forEach(item => { _add(layer, item); }); + stage.render(); - const t = performance.now(); - const b = layer.AABBBounds; - console.log(performance.now() - t); - console.log(b); + setTimeout(() => { + stage.render(); + }, 2000); + + // const t = performance.now(); + // const b = layer.AABBBounds; + // console.log(performance.now() - t); + // console.log(b); + + // const btn = document.createElement('button'); + // btn.innerHTML = 'render'; + // document.body.appendChild(btn); + // btn.addEventListener('click', () => { + // stage.render(); + // }); // stage.set3dOptions({ // alpha: 0, // // beta: 0, From 0b5e2f6435f1daa1c64e58429c28e8956a9faf20 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Tue, 17 Oct 2023 20:09:31 +0800 Subject: [PATCH 05/40] fix: group doUpdateLocalMatrix add reset --- packages/vrender-core/src/graphic/group.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/vrender-core/src/graphic/group.ts b/packages/vrender-core/src/graphic/group.ts index dfe030819..410a66734 100644 --- a/packages/vrender-core/src/graphic/group.ts +++ b/packages/vrender-core/src/graphic/group.ts @@ -168,6 +168,7 @@ export class Group extends Graphic implements IGroup { postMatrix } = this.attribute; if (x === 0 && y === 0 && scaleX === 1 && scaleY === 1 && angle === 0 && !postMatrix) { + this._transMatrix.reset(); return; } return super.doUpdateLocalMatrix(); From c508e38d0a229559405192b8e8674b768e60d06d Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Wed, 18 Oct 2023 14:28:11 +0800 Subject: [PATCH 06/40] feat: enhance group matrix performance --- .../graphic/graphic-service/graphic-service.ts | 8 +++++++- packages/vrender-core/src/interface/render.ts | 4 ++-- .../contributions/render/draw-contribution.ts | 18 +++++++++++------- .../contributions/render/draw-interceptor.ts | 15 ++++++++------- 4 files changed, 28 insertions(+), 17 deletions(-) diff --git a/packages/vrender-core/src/graphic/graphic-service/graphic-service.ts b/packages/vrender-core/src/graphic/graphic-service/graphic-service.ts index cee901f0d..c594e076f 100644 --- a/packages/vrender-core/src/graphic/graphic-service/graphic-service.ts +++ b/packages/vrender-core/src/graphic/graphic-service/graphic-service.ts @@ -1485,7 +1485,13 @@ export class DefaultGraphicService implements IGraphicService { // 合并shadowRoot的bounds this.combindShadowAABBBounds(aabbBounds, graphic); - transformBoundsWithMatrix(aabbBounds, aabbBounds, graphic.transMatrix); + // 性能优化逻辑,group类型变换较少,不需要矩阵变换 + let updateMatrix = true; + const m = graphic.transMatrix; + if (graphic && graphic.isContainer) { + updateMatrix = !(m.a === 1 && m.b === 0 && m.c === 0 && m.d === 1 && m.e === 0 && m.f === 0); + } + updateMatrix && transformBoundsWithMatrix(aabbBounds, aabbBounds, m); // TODO 加上锚点 // transformBounds(aabbBounds, x, y, scaleX, scaleY, angle); diff --git a/packages/vrender-core/src/interface/render.ts b/packages/vrender-core/src/interface/render.ts index 430e4408c..a2fef5f4f 100644 --- a/packages/vrender-core/src/interface/render.ts +++ b/packages/vrender-core/src/interface/render.ts @@ -1,4 +1,4 @@ -import type { IAABBBounds, IBounds } from '@visactor/vutils'; +import type { IAABBBounds, IBounds, IMatrixLike } from '@visactor/vutils'; import type { IColor } from './color'; import type { IContext2d } from './context'; import type { IGraphic, IGraphicAttribute } from './graphic'; @@ -70,7 +70,7 @@ export interface IDrawContribution { draw: (renderService: IRenderService, drawParams: IDrawContext) => MaybePromise; afterDraw?: (renderService: IRenderService, drawParams: IDrawContext) => MaybePromise; getRenderContribution: (graphic: IGraphic) => IGraphicRender | null; - renderGroup: (group: IGroup, drawContext: IDrawContext, skipSort?: boolean) => void; + renderGroup: (group: IGroup, drawContext: IDrawContext, matrix: IMatrixLike, skipSort?: boolean) => void; renderItem: (graphic: IGraphic, drawContext: IDrawContext, params?: IGraphicRenderDrawParams) => void; } diff --git a/packages/vrender-core/src/render/contributions/render/draw-contribution.ts b/packages/vrender-core/src/render/contributions/render/draw-contribution.ts index 8d47c73a3..b601fdb3b 100644 --- a/packages/vrender-core/src/render/contributions/render/draw-contribution.ts +++ b/packages/vrender-core/src/render/contributions/render/draw-contribution.ts @@ -18,7 +18,7 @@ import { findNextGraphic, foreach } from '../../../common/sort'; // eslint-disable-next-line @typescript-eslint/consistent-type-imports import { ContributionProvider } from '../../../common/contribution-provider'; import { DefaultAttribute } from '../../../graphic'; -import type { IAABBBounds, IBounds } from '@visactor/vutils'; +import type { IAABBBounds, IBounds, IMatrixLike } from '@visactor/vutils'; import { Bounds, getRectIntersect, isRectIntersect, last } from '@visactor/vutils'; import { LayerService } from '../../../core/constants'; import { container } from '../../../container'; @@ -28,6 +28,7 @@ import { createColor } from '../../../common/canvas-utils'; import type { ILayerService } from '../../../interface/core'; import { VGlobal } from '../../../constants'; import { boundsAllocate } from '../../../allocator/bounds-allocate'; +import { matrixAllocate } from '../../../allocator/matrix-allocate'; /** * 默认的渲染contribution,基于树状结构针对图元的渲染 @@ -140,7 +141,7 @@ export class DefaultDrawContribution implements IDrawContribution { return (a.attribute.zIndex ?? DefaultAttribute.zIndex) - (b.attribute.zIndex ?? DefaultAttribute.zIndex); }) .forEach(group => { - this.renderGroup(group as IGroup, drawContext); + this.renderGroup(group as IGroup, drawContext, matrixAllocate.allocate(1, 0, 0, 1, 0, 0)); }); context.restore(); @@ -169,7 +170,7 @@ export class DefaultDrawContribution implements IDrawContribution { return null; } - renderGroup(group: IGroup, drawContext: IDrawContext, skipSort?: boolean) { + renderGroup(group: IGroup, drawContext: IDrawContext, parentMatrix: IMatrixLike, skipSort?: boolean) { if (drawContext.break || group.attribute.visibleAll === false) { return; } @@ -186,8 +187,10 @@ export class DefaultDrawContribution implements IDrawContribution { const tempBounds = boundsAllocate.allocateByObj(this.dirtyBounds); // 变换dirtyBounds - const m = group.globalTransMatrix.getInverse(); - this.dirtyBounds.copy(this.backupDirtyBounds).transformWithMatrix(m); + const gm = group.transMatrix; + const nextM = matrixAllocate.allocateByObj(parentMatrix).multiply(gm.a, gm.b, gm.c, gm.d, gm.e, gm.f); + // const m = group.globalTransMatrix.getInverse(); + this.dirtyBounds.copy(this.backupDirtyBounds).transformWithMatrix(nextM.getInverse()); this.renderItem(group, drawContext, { drawingCb: () => { @@ -197,7 +200,7 @@ export class DefaultDrawContribution implements IDrawContribution { return; } if (item.isContainer) { - this.renderGroup(item as IGroup, drawContext); + this.renderGroup(item as IGroup, drawContext, nextM); } else { this.renderItem(item, drawContext); } @@ -210,7 +213,7 @@ export class DefaultDrawContribution implements IDrawContribution { return; } if (item.isContainer) { - this.renderGroup(item as IGroup, drawContext); + this.renderGroup(item as IGroup, drawContext, nextM); } else { this.renderItem(item, drawContext); } @@ -223,6 +226,7 @@ export class DefaultDrawContribution implements IDrawContribution { this.dirtyBounds.copy(tempBounds); boundsAllocate.free(tempBounds); + matrixAllocate.free(nextM); } protected _increaseRender(group: IGroup, drawContext: IDrawContext) { diff --git a/packages/vrender-core/src/render/contributions/render/draw-interceptor.ts b/packages/vrender-core/src/render/contributions/render/draw-interceptor.ts index 2c13d065b..9d054398a 100644 --- a/packages/vrender-core/src/render/contributions/render/draw-interceptor.ts +++ b/packages/vrender-core/src/render/contributions/render/draw-interceptor.ts @@ -84,7 +84,7 @@ export class ShadowRootDrawItemInterceptorContribution implements IDrawItemInter } // 设置context的transform到上一个节点 - drawContribution.renderGroup(graphic.shadowRoot, drawContext); + drawContribution.renderGroup(graphic.shadowRoot, drawContext, graphic.parent.globalTransMatrix); context.highPerformanceRestore(); @@ -275,7 +275,7 @@ export class InteractiveDrawItemInterceptorContribution implements IDrawItemInte // context.fillRect(0, 0, 100, 100); // 设置context的transform到上一个节点 baseGraphic.isContainer - ? drawContribution.renderGroup(baseGraphic as IGroup, drawContext) + ? drawContribution.renderGroup(baseGraphic as IGroup, drawContext, baseGraphic.parent.globalTransMatrix) : drawContribution.renderItem(baseGraphic, drawContext); context.highPerformanceRestore(); @@ -390,14 +390,15 @@ export class Canvas3DDrawItemInterceptor implements IDrawItemInterceptorContribu sortedChildren.forEach(c => { graphic.appendChild(c); }); + const m = graphic.parent.globalTransMatrix; drawContext.hack_pieFace = 'outside'; - drawContribution.renderGroup(graphic as IGroup, drawContext); + drawContribution.renderGroup(graphic as IGroup, drawContext, m); // 绘制内部 drawContext.hack_pieFace = 'inside'; - drawContribution.renderGroup(graphic as IGroup, drawContext); + drawContribution.renderGroup(graphic as IGroup, drawContext, m); // 绘制顶部 drawContext.hack_pieFace = 'top'; - drawContribution.renderGroup(graphic as IGroup, drawContext); + drawContribution.renderGroup(graphic as IGroup, drawContext, m); graphic.removeAllChild(); children.forEach(c => { c._next = null; @@ -433,7 +434,7 @@ export class Canvas3DDrawItemInterceptor implements IDrawItemInterceptorContribu graphic.add(i.g); }); - drawContribution.renderGroup(graphic as IGroup, drawContext, true); + drawContribution.renderGroup(graphic as IGroup, drawContext, graphic.parent.globalTransMatrix, true); graphic.removeAllChild(); children.forEach(g => { @@ -445,7 +446,7 @@ export class Canvas3DDrawItemInterceptor implements IDrawItemInterceptorContribu graphic.add(g); }); } else { - drawContribution.renderGroup(graphic as IGroup, drawContext); + drawContribution.renderGroup(graphic as IGroup, drawContext, graphic.parent.globalTransMatrix); } } else { drawContribution.renderItem(graphic, drawContext); From fbf6a1a39b3c06400da1fff12f24a6dd34e12209 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Thu, 2 Nov 2023 15:49:27 +0800 Subject: [PATCH 07/40] feat: optmize frist screen tiem --- .../src/animate/Ticker/default-ticker.ts | 2 +- .../src/common/Reflect-metadata.ts | 1 + .../inversify-lite/container/container.ts | 29 ++- .../inversify-lite/interfaces/interfaces.ts | 4 +- .../planning/queryable_string.ts | 20 +- .../resolution/instantiation.ts | 16 ++ .../inversify-lite/resolution/resolver.ts | 8 + .../layerHandler/canvas2d-contribution.ts | 6 +- .../layerHandler/empty-contribution.ts | 23 ++- .../layerHandler/offscreen2d-contribution.ts | 19 +- .../core/contributions/textMeasure/modules.ts | 3 +- .../vrender-core/src/core/core-modules.ts | 15 +- packages/vrender-core/src/core/global.ts | 7 + .../vrender-core/src/core/graphic-utils.ts | 8 +- .../vrender-core/src/core/layer-service.ts | 6 +- packages/vrender-core/src/core/stage.ts | 10 +- packages/vrender-core/src/core/window.ts | 8 +- .../graphic-service/arc-contribution.ts | 16 +- .../graphic-service/area-contribution.ts | 10 +- .../graphic-service/circle-contribution.ts | 16 +- .../graphic-service/common-contribution.ts | 2 - .../graphic/graphic-service/graphic-module.ts | 39 +--- .../graphic-service/graphic-service.ts | 49 +---- .../graphic-service/path-contribution.ts | 16 +- .../graphic-service/rect-contribution.ts | 16 +- .../graphic-service/symbol-contribution.ts | 5 +- packages/vrender-core/src/interface/global.ts | 3 + packages/vrender-core/src/interface/stage.ts | 2 +- .../src/picker/global-picker-service.ts | 11 +- .../vrender-core/src/picker/picker-service.ts | 8 +- .../src/plugins/plugin-modules.ts | 3 +- .../render/contributions/render/arc-render.ts | 10 + .../contributions/render/area-render.ts | 5 + .../contributions/render/base-render.ts | 28 +-- .../contributions/render/circle-render.ts | 12 +- .../contributions/arc-contribution-render.ts | 23 +-- .../contributions/area-contribution-render.ts | 16 +- .../contributions/base-contribution-render.ts | 6 +- .../circle-contribution-render.ts | 23 +-- .../render/contributions/constants.ts | 1 + .../group-contribution-render.ts | 3 +- .../image-contribution-render.ts | 3 +- .../contributions/path-contribution-render.ts | 24 +-- .../polygon-contribution-render.ts | 24 +-- .../contributions/rect-contribution-render.ts | 29 +-- .../symbol-contribution-render.ts | 21 +-- .../contributions/render/draw-contribution.ts | 14 +- .../contributions/render/group-render.ts | 2 + .../contributions/render/image-render.ts | 2 + .../render/incremental-draw-contribution.ts | 8 +- .../src/render/contributions/render/module.ts | 173 +++++------------- .../contributions/render/path-render.ts | 5 + .../contributions/render/polygon-render.ts | 5 + .../contributions/render/rect-render.ts | 14 ++ .../contributions/render/render-slector.ts | 16 +- .../contributions/render/symbol-render.ts | 10 + .../vrender-core/src/render/render-modules.ts | 3 +- .../canvas/contributions/browser/canvas.ts | 14 +- .../src/picker/canvas-picker-service.ts | 18 +- .../contributions/canvas-picker/module.ts | 48 ++--- .../contributions/math-picker/module.ts | 30 +-- .../src/picker/math-picker-service.ts | 4 +- .../contributions/browser-contribution.ts | 12 +- .../__tests__/browser/src/pages/circle.ts | 12 +- packages/vrender/src/index.ts | 4 +- 65 files changed, 423 insertions(+), 580 deletions(-) diff --git a/packages/vrender-core/src/animate/Ticker/default-ticker.ts b/packages/vrender-core/src/animate/Ticker/default-ticker.ts index 8e1f7a070..af7a066bd 100644 --- a/packages/vrender-core/src/animate/Ticker/default-ticker.ts +++ b/packages/vrender-core/src/animate/Ticker/default-ticker.ts @@ -130,7 +130,7 @@ export class DefaultTicker implements ITicker { init() { this.interval = NaN; this.status = STATUS.INITIAL; - application.global.hooks.onSetEnv.tap('window', () => { + application.global.hooks.onSetEnv.tap('default-ticker', () => { this.initHandler(); }); if (application.global.env) { diff --git a/packages/vrender-core/src/common/Reflect-metadata.ts b/packages/vrender-core/src/common/Reflect-metadata.ts index 6a96f2b69..c6e0bd7ea 100644 --- a/packages/vrender-core/src/common/Reflect-metadata.ts +++ b/packages/vrender-core/src/common/Reflect-metadata.ts @@ -572,6 +572,7 @@ export default (function (Reflect) { // return descriptor; // } function GetOrCreateMetadataMap(O, P, Create) { + // console.count('GetOrCreateMetadataMap'); let targetMetadata = Metadata.get(O); if (IsUndefined(targetMetadata)) { if (!Create) { diff --git a/packages/vrender-core/src/common/inversify-lite/container/container.ts b/packages/vrender-core/src/common/inversify-lite/container/container.ts index 622b28c0d..189e1b9f5 100644 --- a/packages/vrender-core/src/common/inversify-lite/container/container.ts +++ b/packages/vrender-core/src/common/inversify-lite/container/container.ts @@ -254,9 +254,22 @@ class Container implements interfaces.Container { // The runtime identifier must be associated with only one binding // use getAll when the runtime identifier is associated with multiple bindings get(serviceIdentifier: interfaces.ServiceIdentifier): T { + // if (!window.aaa) { + // window.aaa = 0; + // } + // const t = performance.now(); const getArgs = this._getNotAllArgs(serviceIdentifier, false); + // const getArgs = { + // avoidConstraints: false, + // isMultiInject: false, + // serviceIdentifier + // }; - return this._getButThrowIfAsync(getArgs) as T; + const data = this._getButThrowIfAsync(getArgs) as T; + // const delta = performance.now() - t; + // window.aaa += delta; + + return data; } async getAsync(serviceIdentifier: interfaces.ServiceIdentifier): Promise { @@ -527,11 +540,12 @@ class Container implements interfaces.Container { } private _getButThrowIfAsync(getArgs: GetArgs): T | T[] { + // console.count('_getButThrowIfAsync'); const result = this._get(getArgs); - if (isPromiseOrContainsPromise(result)) { - throw new Error(ERROR_MSGS.LAZY_IN_SYNC(getArgs.serviceIdentifier)); - } + // if (isPromiseOrContainsPromise(result)) { + // throw new Error(ERROR_MSGS.LAZY_IN_SYNC(getArgs.serviceIdentifier)); + // } return result as T | T[]; } @@ -569,6 +583,11 @@ class Container implements interfaces.Container { private _planAndResolve(): (args: interfaces.NextArgs) => interfaces.ContainerResolution { return (args: interfaces.NextArgs) => { // create a plan + // if (!window.aaa) { + // window.aaa = 0; + // } + // const t = performance.now(); + // debugger; let context = plan( this._metadataReader, this, @@ -582,7 +601,7 @@ class Container implements interfaces.Container { // apply context interceptor context = args.contextInterceptor(context); - + // window.aaa += performance.now() - t; // resolve plan const result = resolve(context); diff --git a/packages/vrender-core/src/common/inversify-lite/interfaces/interfaces.ts b/packages/vrender-core/src/common/inversify-lite/interfaces/interfaces.ts index f315fdec0..2fdf0b866 100644 --- a/packages/vrender-core/src/common/inversify-lite/interfaces/interfaces.ts +++ b/packages/vrender-core/src/common/inversify-lite/interfaces/interfaces.ts @@ -149,8 +149,8 @@ export namespace interfaces { } export interface QueryableString { - startsWith(searchString: string): boolean; - endsWith(searchString: string): boolean; + // startsWith(searchString: string): boolean; + // endsWith(searchString: string): boolean; contains(searchString: string): boolean; equals(compareString: string): boolean; value(): string; diff --git a/packages/vrender-core/src/common/inversify-lite/planning/queryable_string.ts b/packages/vrender-core/src/common/inversify-lite/planning/queryable_string.ts index 68d214738..ae26efcd4 100644 --- a/packages/vrender-core/src/common/inversify-lite/planning/queryable_string.ts +++ b/packages/vrender-core/src/common/inversify-lite/planning/queryable_string.ts @@ -7,16 +7,16 @@ class QueryableString implements interfaces.QueryableString { this.str = str; } - startsWith(searchString: string): boolean { - return this.str.indexOf(searchString) === 0; - } - - endsWith(searchString: string): boolean { - let reverseString = ''; - const reverseSearchString = searchString.split('').reverse().join(''); - reverseString = this.str.split('').reverse().join(''); - return this.startsWith.call({ str: reverseString }, reverseSearchString); - } + // startsWith(searchString: string): boolean { + // return this.str.indexOf(searchString) === 0; + // } + + // endsWith(searchString: string): boolean { + // let reverseString = ''; + // const reverseSearchString = searchString.split('').reverse().join(''); + // reverseString = this.str.split('').reverse().join(''); + // return this.startsWith.call({ str: reverseString }, reverseSearchString); + // } contains(searchString: string): boolean { return this.str.indexOf(searchString) !== -1; diff --git a/packages/vrender-core/src/common/inversify-lite/resolution/instantiation.ts b/packages/vrender-core/src/common/inversify-lite/resolution/instantiation.ts index 1d9375fc2..54c217d9c 100644 --- a/packages/vrender-core/src/common/inversify-lite/resolution/instantiation.ts +++ b/packages/vrender-core/src/common/inversify-lite/resolution/instantiation.ts @@ -59,14 +59,30 @@ function _createInstance( result = createInstanceWithInjections(createInstanceWithInjectionsArg); } } else { + if (!(window as any).constr) { + (window as any).constr = 0; + (window as any).map = new Map(); + } + const t = performance.now(); result = new constr(); + const delta = performance.now() - t; + (window as any).map.set(result, delta); + (window as any).constr += delta; } return result; } function createInstanceWithInjections(args: CreateInstanceWithInjectionArg): T { + if (!(window as any).constr) { + (window as any).constr = 0; + (window as any).map = new Map(); + } + const t = performance.now(); const instance = new args.constr(...args.constructorInjections); + const delta = performance.now() - t; + (window as any).map.set(instance, delta); + (window as any).constr += delta; args.propertyRequests.forEach((r: interfaces.Request, index: number) => { const property = r.target.identifier; const injection = args.propertyInjections[index]; diff --git a/packages/vrender-core/src/common/inversify-lite/resolution/resolver.ts b/packages/vrender-core/src/common/inversify-lite/resolution/resolver.ts index 5047cb38d..b284a9d25 100644 --- a/packages/vrender-core/src/common/inversify-lite/resolution/resolver.ts +++ b/packages/vrender-core/src/common/inversify-lite/resolution/resolver.ts @@ -41,6 +41,7 @@ const _resolveRequest = }; const _resolveFactoryFromBinding = (binding: interfaces.Binding, context: interfaces.Context): T | Promise => { + // console.count('_resolveFactoryFromBinding'); const factoryDetails = getFactoryDetails(binding); return tryAndThrowErrorIfStackOverflow( () => (factoryDetails.factory as interfaces.FactoryTypeFunction).bind(binding)(context), @@ -59,6 +60,13 @@ const _getResolvedFromBinding = ( request: interfaces.Request, binding: interfaces.Binding ): T | Promise => { + // console.count('_getResolvedFromBinding'); + // console.log('_getResolvedFromBinding', binding); + // if (!(window as any).map) { + // (window as any).map = new Map(); + // } + // const d = (window as any).map.get(binding.serviceIdentifier) || []; + // (window as any).map.set(binding.serviceIdentifier, [...d, binding]); let result: T | Promise | undefined; const childRequests = request.childRequests; diff --git a/packages/vrender-core/src/core/contributions/layerHandler/canvas2d-contribution.ts b/packages/vrender-core/src/core/contributions/layerHandler/canvas2d-contribution.ts index 45ff3f88a..712a8ba42 100644 --- a/packages/vrender-core/src/core/contributions/layerHandler/canvas2d-contribution.ts +++ b/packages/vrender-core/src/core/contributions/layerHandler/canvas2d-contribution.ts @@ -15,7 +15,7 @@ import type { LayerMode } from '../../../interface'; import type { IBounds } from '@visactor/vutils'; -import { VGlobal } from '../../../constants'; +import { application } from '../../../application'; @injectable() export class CanvasLayerHandlerContribution implements ILayerHandlerContribution { @@ -26,11 +26,13 @@ export class CanvasLayerHandlerContribution implements ILayerHandlerContribution main: boolean; window: IWindow; type: LayerMode = 'static'; + global: IGlobal; // 所绑定的副layer handler secondaryHandlers: ILayerHandlerContribution[]; - constructor(@inject(VGlobal) public readonly global: IGlobal) { + constructor() { this.offscreen = false; + this.global = application.global; } setDpr(dpr: number) { diff --git a/packages/vrender-core/src/core/contributions/layerHandler/empty-contribution.ts b/packages/vrender-core/src/core/contributions/layerHandler/empty-contribution.ts index e1a360c71..ad1f55fc2 100644 --- a/packages/vrender-core/src/core/contributions/layerHandler/empty-contribution.ts +++ b/packages/vrender-core/src/core/contributions/layerHandler/empty-contribution.ts @@ -12,22 +12,25 @@ import type { LayerMode } from '../../../interface'; import type { IBounds } from '@visactor/vutils'; -import { VGlobal } from '../../../constants'; +import { application } from '../../../application'; @injectable() export class EmptyLayerHandlerContribution implements ILayerHandlerContribution { - layer: ILayer; - canvas: null; - context: null; - offscreen: boolean; - main: boolean; - window: IWindow; - type: LayerMode = 'virtual'; + declare layer: ILayer; + declare canvas: null; + declare context: null; + declare offscreen: boolean; + declare main: boolean; + declare window: IWindow; + declare type: LayerMode; // 所依赖的主layer handler - mainHandler: ILayerHandlerContribution; + declare mainHandler: ILayerHandlerContribution; + declare global: IGlobal; - constructor(@inject(VGlobal) public readonly global: IGlobal) { + constructor() { this.offscreen = false; + this.type = 'virtual'; + this.global = application.global; } setDpr(dpr: number) { diff --git a/packages/vrender-core/src/core/contributions/layerHandler/offscreen2d-contribution.ts b/packages/vrender-core/src/core/contributions/layerHandler/offscreen2d-contribution.ts index de16ff555..16bf1ebce 100644 --- a/packages/vrender-core/src/core/contributions/layerHandler/offscreen2d-contribution.ts +++ b/packages/vrender-core/src/core/contributions/layerHandler/offscreen2d-contribution.ts @@ -14,20 +14,23 @@ import type { LayerMode } from '../../../interface'; import type { IBoundsLike } from '@visactor/vutils'; -import { VGlobal } from '../../../constants'; +import { application } from '../../../application'; @injectable() export class OffscreenLayerHandlerContribution implements ILayerHandlerContribution { - layer: ILayer; - canvas: ICanvas; - context: IContext2d; - offscreen: boolean; - type: LayerMode = 'dynamic'; + declare layer: ILayer; + declare canvas: ICanvas; + declare context: IContext2d; + declare offscreen: boolean; + declare type: LayerMode; // 所绑定的副layer handler - secondaryHandlers: ILayerHandlerContribution[]; + declare secondaryHandlers: ILayerHandlerContribution[]; + declare global: IGlobal; - constructor(@inject(VGlobal) public readonly global: IGlobal) { + constructor() { this.offscreen = true; + this.type = 'dynamic'; + this.global = application.global; } setDpr(dpr: number) { diff --git a/packages/vrender-core/src/core/contributions/textMeasure/modules.ts b/packages/vrender-core/src/core/contributions/textMeasure/modules.ts index 94e0f1971..8e532a2d9 100644 --- a/packages/vrender-core/src/core/contributions/textMeasure/modules.ts +++ b/packages/vrender-core/src/core/contributions/textMeasure/modules.ts @@ -3,7 +3,6 @@ import { bindContributionProvider } from '../../../common/contribution-provider' import { DefaultTextMeasureContribution, TextMeasureContribution } from './textMeasure-contribution'; export default new ContainerModule(bind => { - bind(DefaultTextMeasureContribution).toSelf().inSingletonScope(); - bind(TextMeasureContribution).toService(DefaultTextMeasureContribution); + bind(TextMeasureContribution).to(DefaultTextMeasureContribution).inSingletonScope(); bindContributionProvider(bind, TextMeasureContribution); }); diff --git a/packages/vrender-core/src/core/core-modules.ts b/packages/vrender-core/src/core/core-modules.ts index f8ae715c3..b2b601af8 100644 --- a/packages/vrender-core/src/core/core-modules.ts +++ b/packages/vrender-core/src/core/core-modules.ts @@ -8,17 +8,12 @@ import { VGlobal } from '../constants'; export default new ContainerModule(bind => { // global对象,全局单例模式 - bind(DefaultGlobal).toSelf().inSingletonScope(); - bind(VGlobal).toService(DefaultGlobal); + bind(VGlobal).to(DefaultGlobal).inSingletonScope(); - bind(DefaultWindow).to(DefaultWindow); - bind(VWindow).toService(DefaultWindow); - bind(DefaultGraphicUtil).toSelf().inSingletonScope(); - bind(GraphicUtil).toService(DefaultGraphicUtil); - bind(DefaultTransformUtil).toSelf().inSingletonScope(); - bind(TransformUtil).toService(DefaultTransformUtil); - bind(DefaultLayerService).toSelf().inSingletonScope(); - bind(LayerService).toService(DefaultLayerService); + bind(VWindow).to(DefaultWindow); + bind(GraphicUtil).to(DefaultGraphicUtil).inSingletonScope(); + bind(TransformUtil).to(DefaultTransformUtil).inSingletonScope(); + bind(LayerService).to(DefaultLayerService).inSingletonScope(); // bind(Stage).to(DefaultStage); // bind<(params: Partial) => IStage>(StageFactory).toFactory((context: interface.Context) => { diff --git a/packages/vrender-core/src/core/global.ts b/packages/vrender-core/src/core/global.ts index 7631c523a..d0cb960ec 100644 --- a/packages/vrender-core/src/core/global.ts +++ b/packages/vrender-core/src/core/global.ts @@ -15,6 +15,10 @@ import { SyncHook } from '../tapable'; import { EnvContribution } from '../constants'; import type { IAABBBoundsLike } from '@visactor/vutils'; +const canvas = document.createElement('canvas'); +canvas.width = 500; +canvas.height = 500; + const defaultEnv: EnvType = 'browser'; @injectable() export class DefaultGlobal implements IGlobal { @@ -103,6 +107,8 @@ export class DefaultGlobal implements IGlobal { this.envContribution.applyStyles = support; } + optimizeVisible: boolean; + envParams?: any; declare measureTextMethod: 'native' | 'simple' | 'quick'; declare hooks: { @@ -119,6 +125,7 @@ export class DefaultGlobal implements IGlobal { onSetEnv: new SyncHook<[EnvType | undefined, EnvType, IGlobal]>(['lastEnv', 'env', 'global']) }; this.measureTextMethod = 'native'; + this.optimizeVisible = false; } protected bindContribution(params?: any): void | Promise { diff --git a/packages/vrender-core/src/core/graphic-utils.ts b/packages/vrender-core/src/core/graphic-utils.ts index 77de58ba6..62caec2fb 100644 --- a/packages/vrender-core/src/core/graphic-utils.ts +++ b/packages/vrender-core/src/core/graphic-utils.ts @@ -4,13 +4,12 @@ import type { ITextMeasure, TextOptionsType } from '../interface/text'; import { TextMeasureContribution } from './contributions/textMeasure/textMeasure-contribution'; // eslint-disable-next-line @typescript-eslint/consistent-type-imports import { ContributionProvider } from '../common/contribution-provider'; -import { wrapCanvas } from '../canvas/util'; import { DefaultTextStyle } from '../graphic/config'; import type { IMatrix, IPointLike, ITextMeasureOption } from '@visactor/vutils'; import { Matrix, TextMeasure } from '@visactor/vutils'; import type { IGraphicUtil, ITransformUtil, TransformType } from '../interface/core'; -import { VGlobal } from '../constants'; import { canvasAllocate } from '../allocator/canvas-allocate'; +import { application } from '../application'; @injectable() export class DefaultGraphicUtil implements IGraphicUtil { @@ -18,14 +17,15 @@ export class DefaultGraphicUtil implements IGraphicUtil { context?: IContext2d | null; _textMeasure: ITextMeasure; configured: boolean; + global: IGlobal; constructor( @inject(ContributionProvider) @named(TextMeasureContribution) - protected readonly contributions: IContributionProvider, - @inject(VGlobal) public readonly global: IGlobal + protected readonly contributions: IContributionProvider ) { this.configured = false; + this.global = application.global; this.global.hooks.onSetEnv.tap('graphic-util', (lastEnv, env, global) => { this.configured = false; this.configure(global, env); diff --git a/packages/vrender-core/src/core/layer-service.ts b/packages/vrender-core/src/core/layer-service.ts index 08810dd9d..108c6da77 100644 --- a/packages/vrender-core/src/core/layer-service.ts +++ b/packages/vrender-core/src/core/layer-service.ts @@ -2,13 +2,13 @@ import { inject, injectable } from '../common/inversify-lite'; import type { ILayer, IStage, IGlobal, ILayerParams, LayerMode, ILayerHandlerContribution } from '../interface'; import { Layer } from './layer'; import type { ILayerService } from '../interface/core'; -import { VGlobal } from '../constants'; import { container } from '../container'; import { DynamicLayerHandlerContribution, StaticLayerHandlerContribution, VirtualLayerHandlerContribution } from './constants'; +import { application } from '../application'; @injectable() export class DefaultLayerService implements ILayerService { @@ -16,8 +16,10 @@ export class DefaultLayerService implements ILayerService { declare staticLayerCountInEnv: number; declare dynamicLayerCountInEnv: number; declare inited: boolean; - constructor(@inject(VGlobal) public readonly global: IGlobal) { + declare global: IGlobal; + constructor() { this.layerMap = new Map(); + this.global = application.global; } tryInit() { diff --git a/packages/vrender-core/src/core/stage.ts b/packages/vrender-core/src/core/stage.ts index f3cadb211..c59dcb7a5 100644 --- a/packages/vrender-core/src/core/stage.ts +++ b/packages/vrender-core/src/core/stage.ts @@ -46,9 +46,9 @@ import { defaultTicker } from '../animate/default-ticker'; import { SyncHook } from '../tapable'; import { DirectionalLight } from './light'; import { OrthoCamera } from './camera'; -import { VGlobal } from '../constants'; import { LayerService } from './constants'; import { DefaultTimeline } from '../animate'; +import { application } from '../application'; const DefaultConfig = { WIDTH: 500, @@ -163,7 +163,7 @@ export class Stage extends Group implements IStage { readonly window: IWindow; private readonly global: IGlobal; readonly renderService: IRenderService; - readonly pickerService: IPickerService; + pickerService?: IPickerService; readonly pluginService: IPluginService; readonly layerService: ILayerService; private readonly eventSystem?: EventSystem; @@ -195,10 +195,9 @@ export class Stage extends Group implements IStage { beforeRender: new SyncHook(['stage']), afterRender: new SyncHook(['stage']) }; - this.global = container.get(VGlobal); + this.global = application.global; this.window = container.get(VWindow); this.renderService = container.get(RenderService); - this.pickerService = container.get(PickerService); this.pluginService = container.get(PluginService); this.layerService = container.get(LayerService); this.pluginService.active(this, params); @@ -774,6 +773,9 @@ export class Stage extends Group implements IStage { throw new Error('暂不支持'); } pick(x: number, y: number): PickResult | false { + if (!this.pickerService) { + this.pickerService = container.get(PickerService); + } // 暂时不提供layer的pick const result = this.pickerService.pick(this.children as unknown as IGraphic[], new Point(x, y), { bounds: this.AABBBounds diff --git a/packages/vrender-core/src/core/window.ts b/packages/vrender-core/src/core/window.ts index 8d355b5c2..00f461745 100644 --- a/packages/vrender-core/src/core/window.ts +++ b/packages/vrender-core/src/core/window.ts @@ -12,7 +12,7 @@ import type { } from '../interface'; import { container } from '../container'; import { SyncHook } from '../tapable'; -import { VGlobal } from '../constants'; +import { application } from '../application'; export const VWindow = Symbol.for('VWindow'); @@ -69,14 +69,14 @@ export class DefaultWindow implements IWindow { declare mainCanvas: ICanvas; declare layerCanvas: ICanvas[]; declare actived: boolean; + declare global: IGlobal; get dpr(): number { return this._handler.getDpr(); } - constructor( - @inject(VGlobal) public readonly global: IGlobal // @inject(ContributionProvider) // @named(WindowHandlerContribution) // protected readonly contributions: ContributionProvider - ) { + constructor() { this._uid = Generator.GenAutoIncrementId(); + this.global = application.global; } @postConstruct() diff --git a/packages/vrender-core/src/graphic/graphic-service/arc-contribution.ts b/packages/vrender-core/src/graphic/graphic-service/arc-contribution.ts index bfbb4b9cd..49d9c07b2 100644 --- a/packages/vrender-core/src/graphic/graphic-service/arc-contribution.ts +++ b/packages/vrender-core/src/graphic/graphic-service/arc-contribution.ts @@ -1,10 +1,10 @@ -import { injectable } from '../../common/inversify-lite'; -import type { IArcBoundsContribution } from '../../interface'; -import { DefaultOuterBorderBoundsContribution } from './common-contribution'; +// import { injectable } from '../../common/inversify-lite'; +// import type { IArcBoundsContribution } from '../../interface'; +// import { DefaultOuterBorderBoundsContribution } from './common-contribution'; -export const ArcBoundsContribution = Symbol.for('ArcBoundsContribution'); +// export const ArcBoundsContribution = Symbol.for('ArcBoundsContribution'); -@injectable() -export class DefaultArcOuterBorderBoundsContribution - extends DefaultOuterBorderBoundsContribution - implements IArcBoundsContribution {} +// @injectable() +// export class DefaultArcOuterBorderBoundsContribution +// extends DefaultOuterBorderBoundsContribution +// implements IArcBoundsContribution {} diff --git a/packages/vrender-core/src/graphic/graphic-service/area-contribution.ts b/packages/vrender-core/src/graphic/graphic-service/area-contribution.ts index ff8f4a496..0c70593d5 100644 --- a/packages/vrender-core/src/graphic/graphic-service/area-contribution.ts +++ b/packages/vrender-core/src/graphic/graphic-service/area-contribution.ts @@ -1,6 +1,6 @@ -export const AreaBoundsContribution = Symbol.for('AreaBoundsContribution'); +// export const AreaBoundsContribution = Symbol.for('AreaBoundsContribution'); -// @injectable() -// export class DefaultArcOuterBorderBoundsContribution -// extends DefaultOuterBorderBoundsContribution -// implements IArcBoundsContribution {} +// // @injectable() +// // export class DefaultArcOuterBorderBoundsContribution +// // extends DefaultOuterBorderBoundsContribution +// // implements IArcBoundsContribution {} diff --git a/packages/vrender-core/src/graphic/graphic-service/circle-contribution.ts b/packages/vrender-core/src/graphic/graphic-service/circle-contribution.ts index 283a0319a..0d0a55b4f 100644 --- a/packages/vrender-core/src/graphic/graphic-service/circle-contribution.ts +++ b/packages/vrender-core/src/graphic/graphic-service/circle-contribution.ts @@ -1,10 +1,10 @@ -import { injectable } from '../../common/inversify-lite'; -import type { ICircleBoundsContribution } from '../../interface'; -import { DefaultOuterBorderBoundsContribution } from './common-contribution'; +// import { injectable } from '../../common/inversify-lite'; +// import type { ICircleBoundsContribution } from '../../interface'; +// import { DefaultOuterBorderBoundsContribution } from './common-contribution'; -export const CircleBoundsContribution = Symbol.for('CircleBoundsContribution'); +// export const CircleBoundsContribution = Symbol.for('CircleBoundsContribution'); -@injectable() -export class DefaultCircleOuterBorderBoundsContribution - extends DefaultOuterBorderBoundsContribution - implements ICircleBoundsContribution {} +// @injectable() +// export class DefaultCircleOuterBorderBoundsContribution +// extends DefaultOuterBorderBoundsContribution +// implements ICircleBoundsContribution {} diff --git a/packages/vrender-core/src/graphic/graphic-service/common-contribution.ts b/packages/vrender-core/src/graphic/graphic-service/common-contribution.ts index 738963483..6541ed214 100644 --- a/packages/vrender-core/src/graphic/graphic-service/common-contribution.ts +++ b/packages/vrender-core/src/graphic/graphic-service/common-contribution.ts @@ -1,8 +1,6 @@ import type { IAABBBounds } from '@visactor/vutils'; -import { injectable } from '../../common/inversify-lite'; import type { IGraphicAttribute, IGraphic } from '../../interface'; -@injectable() export class DefaultOuterBorderBoundsContribution { updateBounds( attribute: Partial, diff --git a/packages/vrender-core/src/graphic/graphic-service/graphic-module.ts b/packages/vrender-core/src/graphic/graphic-service/graphic-module.ts index eb598f011..4a0eacacb 100644 --- a/packages/vrender-core/src/graphic/graphic-service/graphic-module.ts +++ b/packages/vrender-core/src/graphic/graphic-service/graphic-module.ts @@ -1,49 +1,12 @@ import { ContainerModule } from '../../common/inversify-lite'; -import { bindContributionProvider } from '../../common/contribution-provider'; -import { ArcBoundsContribution, DefaultArcOuterBorderBoundsContribution } from './arc-contribution'; -import { CircleBoundsContribution, DefaultCircleOuterBorderBoundsContribution } from './circle-contribution'; // import { DefaultTheme } from './default-theme'; import { DefaultGraphicService } from './graphic-service'; -import { DefaultPathOuterBorderBoundsContribution, PathBoundsContribution } from './path-contribution'; -import { RectBoundsContribution, DefaultRectOuterBorderBoundsContribution } from './rect-contribution'; -import { DefaultSymbolOuterBorderBoundsContribution, SymbolBoundsContribution } from './symbol-contribution'; import { GraphicCreator, GraphicService } from '../constants'; import { graphicCreator } from '../graphic-creator'; // import { DefaultThemeService, Theme, ThemeServce } from './theme-service'; export default new ContainerModule(bind => { - bind(DefaultGraphicService).toSelf().inSingletonScope(); - bind(GraphicService).toService(DefaultGraphicService); - - // rect的bounds contributions - bind(DefaultRectOuterBorderBoundsContribution).toSelf().inSingletonScope(); - bind(RectBoundsContribution).toService(DefaultRectOuterBorderBoundsContribution); - bindContributionProvider(bind, RectBoundsContribution); - - // symbol的bounds contributions - bind(DefaultSymbolOuterBorderBoundsContribution).toSelf().inSingletonScope(); - bind(SymbolBoundsContribution).toService(DefaultSymbolOuterBorderBoundsContribution); - bindContributionProvider(bind, SymbolBoundsContribution); - - // circle的bounds contributions - bind(DefaultCircleOuterBorderBoundsContribution).toSelf().inSingletonScope(); - bind(CircleBoundsContribution).toService(DefaultCircleOuterBorderBoundsContribution); - bindContributionProvider(bind, CircleBoundsContribution); - - // arc的bounds contributions - bind(DefaultArcOuterBorderBoundsContribution).toSelf().inSingletonScope(); - bind(ArcBoundsContribution).toService(DefaultArcOuterBorderBoundsContribution); - bindContributionProvider(bind, ArcBoundsContribution); - - // path的bounds contributions - bind(DefaultPathOuterBorderBoundsContribution).toSelf().inSingletonScope(); - bind(PathBoundsContribution).toService(DefaultPathOuterBorderBoundsContribution); - bindContributionProvider(bind, PathBoundsContribution); + bind(GraphicService).to(DefaultGraphicService).inSingletonScope(); bind(GraphicCreator).toConstantValue(graphicCreator); - // bind(DefaultThemeService).toSelf().inSingletonScope(); - // bind(ThemeServce).toService(DefaultThemeService); - // bind(DefaultTheme).toSelf().inSingletonScope(); - // bind(Theme).toService(DefaultTheme); - // bindContributionProvider(bind, Theme); }); diff --git a/packages/vrender-core/src/graphic/graphic-service/graphic-service.ts b/packages/vrender-core/src/graphic/graphic-service/graphic-service.ts index c594e076f..45981d3ce 100644 --- a/packages/vrender-core/src/graphic/graphic-service/graphic-service.ts +++ b/packages/vrender-core/src/graphic/graphic-service/graphic-service.ts @@ -47,13 +47,9 @@ import type { IPathBoundsContribution, IContributionProvider } from '../../interface'; -import { RectBoundsContribution } from './rect-contribution'; import { textDrawOffsetX } from '../../common/text'; -import { SymbolBoundsContribution } from './symbol-contribution'; +import { DefaultSymbolOuterBorderBoundsContribution } from './symbol-contribution'; import { boundStroke } from '../tools'; -import { CircleBoundsContribution } from './circle-contribution'; -import { ArcBoundsContribution } from './arc-contribution'; -import { PathBoundsContribution } from './path-contribution'; import { mat4Allocate } from '../../allocator/matrix-allocate'; // eslint-disable-next-line @typescript-eslint/consistent-type-imports import { ContributionProvider } from '../../common/contribution-provider'; @@ -61,6 +57,7 @@ import { BoundsContext } from '../../common/bounds-context'; import { renderCommandList } from '../../common/render-command-list'; import { circleBounds } from '../../common/utils'; import { GraphicCreator } from '../constants'; +import { DefaultOuterBorderBoundsContribution } from './common-contribution'; /** * 部分代码参考 https://github.com/toji/gl-matrix @@ -628,24 +625,7 @@ export class DefaultGraphicService implements IGraphicService { // 临时bounds,用作缓存 protected tempAABBBounds1: AABBBounds; protected tempAABBBounds2: AABBBounds; - constructor( - @inject(GraphicCreator) public readonly creator: IGraphicCreator, - @inject(ContributionProvider) - @named(RectBoundsContribution) - protected readonly rectBoundsContribitions: IContributionProvider, - @inject(ContributionProvider) - @named(SymbolBoundsContribution) - protected readonly symbolBoundsContribitions: IContributionProvider, - @inject(ContributionProvider) - @named(CircleBoundsContribution) - protected readonly circleBoundsContribitions: IContributionProvider, - @inject(ContributionProvider) - @named(ArcBoundsContribution) - protected readonly arcBoundsContribitions: IContributionProvider, - @inject(ContributionProvider) - @named(PathBoundsContribution) - protected readonly pathBoundsContribitions: IContributionProvider - ) { + constructor(@inject(GraphicCreator) public readonly creator: IGraphicCreator) { this.hooks = { onAttributeUpdate: new SyncHook<[IGraphic]>(['graphic']), onSetStage: new SyncHook<[IGraphic, IStage]>(['graphic', 'stage']), @@ -669,6 +649,11 @@ export class DefaultGraphicService implements IGraphicService { }; this.tempAABBBounds1 = new AABBBounds(); this.tempAABBBounds2 = new AABBBounds(); + this._rectBoundsContribitions = [new DefaultOuterBorderBoundsContribution()]; + this._symbolBoundsContribitions = [new DefaultSymbolOuterBorderBoundsContribution()]; + this._circleBoundsContribitions = [new DefaultOuterBorderBoundsContribution()]; + this._arcBoundsContribitions = [new DefaultOuterBorderBoundsContribution()]; + this._pathBoundsContribitions = [new DefaultOuterBorderBoundsContribution()]; } onAttributeUpdate(graphic: IGraphic) { if (this.hooks.onAttributeUpdate.taps.length) { @@ -742,9 +727,6 @@ export class DefaultGraphicService implements IGraphicService { const tb2 = this.tempAABBBounds2; tb1.setValue(aabbBounds.x1, aabbBounds.y1, aabbBounds.x2, aabbBounds.y2); tb2.setValue(aabbBounds.x1, aabbBounds.y1, aabbBounds.x2, aabbBounds.y2); - if (!this._rectBoundsContribitions) { - this._rectBoundsContribitions = this.rectBoundsContribitions.getContributions() || []; - } this._rectBoundsContribitions.length && this._rectBoundsContribitions.forEach(c => { c.updateBounds(attribute, rectTheme, tb1, graphic); @@ -930,9 +912,6 @@ export class DefaultGraphicService implements IGraphicService { const tb2 = this.tempAABBBounds2; tb1.setValue(aabbBounds.x1, aabbBounds.y1, aabbBounds.x2, aabbBounds.y2); tb2.setValue(aabbBounds.x1, aabbBounds.y1, aabbBounds.x2, aabbBounds.y2); - if (!this._pathBoundsContribitions) { - this._pathBoundsContribitions = this.pathBoundsContribitions.getContributions() || []; - } this._pathBoundsContribitions.length && this._pathBoundsContribitions.forEach(c => { c.updateBounds(attribute, pathTheme, tb1, graphic); @@ -1226,10 +1205,6 @@ export class DefaultGraphicService implements IGraphicService { const tb2 = this.tempAABBBounds2; tb1.setValue(aabbBounds.x1, aabbBounds.y1, aabbBounds.x2, aabbBounds.y2); tb2.setValue(aabbBounds.x1, aabbBounds.y1, aabbBounds.x2, aabbBounds.y2); - // 额外扩展bounds - if (!this._circleBoundsContribitions) { - this._circleBoundsContribitions = this.circleBoundsContribitions.getContributions() || []; - } this._circleBoundsContribitions.length && this._circleBoundsContribitions.forEach(c => { c.updateBounds(attribute, circleTheme, tb1, graphic); @@ -1291,10 +1266,6 @@ export class DefaultGraphicService implements IGraphicService { const tb2 = this.tempAABBBounds2; tb1.setValue(aabbBounds.x1, aabbBounds.y1, aabbBounds.x2, aabbBounds.y2); tb2.setValue(aabbBounds.x1, aabbBounds.y1, aabbBounds.x2, aabbBounds.y2); - // 额外扩展bounds - if (!this._arcBoundsContribitions) { - this._arcBoundsContribitions = this.arcBoundsContribitions.getContributions() || []; - } this._arcBoundsContribitions.length && this._arcBoundsContribitions.forEach(c => { c.updateBounds(attribute, arcTheme, tb1, graphic); @@ -1371,10 +1342,6 @@ export class DefaultGraphicService implements IGraphicService { const tb2 = this.tempAABBBounds2; tb1.setValue(aabbBounds.x1, aabbBounds.y1, aabbBounds.x2, aabbBounds.y2); tb2.setValue(aabbBounds.x1, aabbBounds.y1, aabbBounds.x2, aabbBounds.y2); - // 额外扩展bounds - if (!this._symbolBoundsContribitions) { - this._symbolBoundsContribitions = this.symbolBoundsContribitions.getContributions() || []; - } this._symbolBoundsContribitions.length && this._symbolBoundsContribitions.forEach(c => { c.updateBounds(attribute, symbolTheme, tb1, graphic); diff --git a/packages/vrender-core/src/graphic/graphic-service/path-contribution.ts b/packages/vrender-core/src/graphic/graphic-service/path-contribution.ts index ea9da9044..3ad36d390 100644 --- a/packages/vrender-core/src/graphic/graphic-service/path-contribution.ts +++ b/packages/vrender-core/src/graphic/graphic-service/path-contribution.ts @@ -1,10 +1,10 @@ -import { injectable } from '../../common/inversify-lite'; -import { DefaultOuterBorderBoundsContribution } from './common-contribution'; -import type { IPathBoundsContribution } from '../../interface/graphic-service'; +// import { injectable } from '../../common/inversify-lite'; +// import { DefaultOuterBorderBoundsContribution } from './common-contribution'; +// import type { IPathBoundsContribution } from '../../interface/graphic-service'; -export const PathBoundsContribution = Symbol.for('PathBoundsContribution'); +// export const PathBoundsContribution = Symbol.for('PathBoundsContribution'); -@injectable() -export class DefaultPathOuterBorderBoundsContribution - extends DefaultOuterBorderBoundsContribution - implements IPathBoundsContribution {} +// @injectable() +// export class DefaultPathOuterBorderBoundsContribution +// extends DefaultOuterBorderBoundsContribution +// implements IPathBoundsContribution {} diff --git a/packages/vrender-core/src/graphic/graphic-service/rect-contribution.ts b/packages/vrender-core/src/graphic/graphic-service/rect-contribution.ts index c2fa8ce00..f096db211 100644 --- a/packages/vrender-core/src/graphic/graphic-service/rect-contribution.ts +++ b/packages/vrender-core/src/graphic/graphic-service/rect-contribution.ts @@ -1,10 +1,10 @@ -import { injectable } from '../../common/inversify-lite'; -import type { IRectBoundsContribution } from '../../interface'; -import { DefaultOuterBorderBoundsContribution } from './common-contribution'; +// import { injectable } from '../../common/inversify-lite'; +// import type { IRectBoundsContribution } from '../../interface'; +// import { DefaultOuterBorderBoundsContribution } from './common-contribution'; -export const RectBoundsContribution = Symbol.for('RectBoundsContribution'); +// export const RectBoundsContribution = Symbol.for('RectBoundsContribution'); -@injectable() -export class DefaultRectOuterBorderBoundsContribution - extends DefaultOuterBorderBoundsContribution - implements IRectBoundsContribution {} +// @injectable() +// export class DefaultRectOuterBorderBoundsContribution +// extends DefaultOuterBorderBoundsContribution +// implements IRectBoundsContribution {} diff --git a/packages/vrender-core/src/graphic/graphic-service/symbol-contribution.ts b/packages/vrender-core/src/graphic/graphic-service/symbol-contribution.ts index 4fe3d5a65..da0717a1a 100644 --- a/packages/vrender-core/src/graphic/graphic-service/symbol-contribution.ts +++ b/packages/vrender-core/src/graphic/graphic-service/symbol-contribution.ts @@ -1,12 +1,11 @@ import type { IAABBBounds } from '@visactor/vutils'; -import { injectable } from '../../common/inversify-lite'; import { boundStroke } from '../tools'; import type { IGraphic, ISymbolBoundsContribution, ISymbolGraphicAttribute } from '../../interface'; import { DefaultOuterBorderBoundsContribution } from './common-contribution'; -export const SymbolBoundsContribution = Symbol.for('SymbolBoundsContribution'); +// export const SymbolBoundsContribution = Symbol.for('SymbolBoundsContribution'); -@injectable() +// @injectable() export class DefaultSymbolOuterBorderBoundsContribution extends DefaultOuterBorderBoundsContribution implements ISymbolBoundsContribution diff --git a/packages/vrender-core/src/interface/global.ts b/packages/vrender-core/src/interface/global.ts index 6f646206d..2ec757e78 100644 --- a/packages/vrender-core/src/interface/global.ts +++ b/packages/vrender-core/src/interface/global.ts @@ -180,6 +180,9 @@ export interface IGlobal extends Omit void; setActiveEnvContribution: (contribution: IEnvContribution) => void; createCanvas: (params: ICreateCanvasParams) => HTMLCanvasElement | any; diff --git a/packages/vrender-core/src/interface/stage.ts b/packages/vrender-core/src/interface/stage.ts index 953b2dd78..f647a0377 100644 --- a/packages/vrender-core/src/interface/stage.ts +++ b/packages/vrender-core/src/interface/stage.ts @@ -125,7 +125,7 @@ export interface IStage extends INode { ticker: ITicker; increaseAutoRender: boolean; readonly renderService: IRenderService; - readonly pickerService: IPickerService; + pickerService?: IPickerService; readonly pluginService: IPluginService; readonly layerService: ILayerService; // 如果传入CanvasId,如果存在相同Id,说明这两个图层使用相同的Canvas绘制 diff --git a/packages/vrender-core/src/picker/global-picker-service.ts b/packages/vrender-core/src/picker/global-picker-service.ts index 210f4255c..0250c18c9 100644 --- a/packages/vrender-core/src/picker/global-picker-service.ts +++ b/packages/vrender-core/src/picker/global-picker-service.ts @@ -11,7 +11,7 @@ import type { IPickParams, PickResult } from '../interface'; -import { VGlobal } from '../constants'; +import { application } from '../application'; // 默认的pick-service,提供基本的最优选中策略,尽量不需要用户自己实现contribution // 用户可以写plugin @@ -20,13 +20,10 @@ export class DefaultGlobalPickerService implements IPickerService { type: 'global'; declare pickerMap: Map; + declare global: IGlobal; - constructor( - // @inject(ContributionProvider) - // @named(PickerContribution) - // protected readonly contributions: ContributionProvider, - @inject(VGlobal) public readonly global: IGlobal - ) { + constructor() { + this.global = application.global; this.global.hooks.onSetEnv.tap('global-picker-service', (lastEnv, env, global) => { this.configure(global, env); }); diff --git a/packages/vrender-core/src/picker/picker-service.ts b/packages/vrender-core/src/picker/picker-service.ts index a7c9dac09..5a07b5b5b 100644 --- a/packages/vrender-core/src/picker/picker-service.ts +++ b/packages/vrender-core/src/picker/picker-service.ts @@ -20,7 +20,7 @@ import type { import { DefaultAttribute, getTheme, mat3Tomat4, multiplyMat4Mat4 } from '../graphic'; import { mat4Allocate, matrixAllocate } from '../allocator/matrix-allocate'; import { PickItemInterceptor } from './pick-interceptor'; -import { VGlobal } from '../constants'; +import { application } from '../application'; @injectable() export abstract class DefaultPickService implements IPickerService { @@ -28,14 +28,16 @@ export abstract class DefaultPickService implements IPickerService { declare pickerMap: Map; declare pickContext?: IContext2d; declare InterceptorContributions: IPickItemInterceptorContribution[]; + declare global: IGlobal; constructor( - @inject(VGlobal) public readonly global: IGlobal, // 拦截器 @inject(ContributionProvider) @named(PickItemInterceptor) protected readonly pickItemInterceptorContributions: IContributionProvider - ) {} + ) { + this.global = application.global; + } protected _init() { this.InterceptorContributions = this.pickItemInterceptorContributions diff --git a/packages/vrender-core/src/plugins/plugin-modules.ts b/packages/vrender-core/src/plugins/plugin-modules.ts index 159b71a04..ff5edd194 100644 --- a/packages/vrender-core/src/plugins/plugin-modules.ts +++ b/packages/vrender-core/src/plugins/plugin-modules.ts @@ -5,8 +5,7 @@ import { bindContributionProviderNoSingletonScope } from '../common/contribution import { AutoEnablePlugins } from './constants'; export default new ContainerModule(bind => { - bind(DefaultPluginService).toSelf(); - bind(PluginService).toService(DefaultPluginService); + bind(PluginService).to(DefaultPluginService); // image 渲染器注入contributions bindContributionProviderNoSingletonScope(bind, AutoEnablePlugins); diff --git a/packages/vrender-core/src/render/contributions/render/arc-render.ts b/packages/vrender-core/src/render/contributions/render/arc-render.ts index fb24976f7..0bc162dce 100644 --- a/packages/vrender-core/src/render/contributions/render/arc-render.ts +++ b/packages/vrender-core/src/render/contributions/render/arc-render.ts @@ -35,6 +35,11 @@ import { ArcRenderContribution } from './contributions/constants'; import { BaseRenderContributionTime } from '../../../common/enums'; import { ARC_NUMBER_TYPE } from '../../../graphic/constants'; import { BaseRender } from './base-render'; +import { + defaultArcBackgroundRenderContribution, + defaultArcRenderContribution, + defaultArcTextureRenderContribution +} from './contributions'; /** * 部分源码参考 https://github.com/d3/d3-shape/ * Copyright 2010-2022 Mike Bostock @@ -63,6 +68,11 @@ export class DefaultCanvasArcRender extends BaseRender implements IGraphic protected readonly arcRenderContribitions: IContributionProvider ) { super(); + this.builtinContributions = [ + defaultArcRenderContribution, + defaultArcBackgroundRenderContribution, + defaultArcTextureRenderContribution + ]; this.init(arcRenderContribitions); } diff --git a/packages/vrender-core/src/render/contributions/render/area-render.ts b/packages/vrender-core/src/render/contributions/render/area-render.ts index 40ba6a4e2..9c3bdb3c6 100644 --- a/packages/vrender-core/src/render/contributions/render/area-render.ts +++ b/packages/vrender-core/src/render/contributions/render/area-render.ts @@ -38,6 +38,10 @@ import { drawAreaSegments } from '../../../common/render-area'; import { AREA_NUMBER_TYPE } from '../../../graphic/constants'; import { drawSegments } from '../../../common/render-curve'; import { BaseRender } from './base-render'; +import { + defaultAreaBackgroundRenderContribution, + defaultAreaTextureRenderContribution +} from './contributions/area-contribution-render'; function calcLineCache( points: IPointLike[], @@ -77,6 +81,7 @@ export class DefaultCanvasAreaRender extends BaseRender implements IGraph protected readonly areaRenderContribitions: IContributionProvider ) { super(); + this.builtinContributions = [defaultAreaTextureRenderContribution, defaultAreaBackgroundRenderContribution]; this.init(areaRenderContribitions); } diff --git a/packages/vrender-core/src/render/contributions/render/base-render.ts b/packages/vrender-core/src/render/contributions/render/base-render.ts index b747a47f9..efb3cee5c 100644 --- a/packages/vrender-core/src/render/contributions/render/base-render.ts +++ b/packages/vrender-core/src/render/contributions/render/base-render.ts @@ -25,7 +25,9 @@ export abstract class BaseRender { camera: ICamera; declare z: number; - declare renderContribitions: IContributionProvider> | null; + builtinContributions: IBaseRenderContribution[]; + + // declare renderContribitions: IContributionProvider> | null; protected _beforeRenderContribitions: IBaseRenderContribution[]; protected _afterRenderContribitions: IBaseRenderContribution[]; @@ -33,17 +35,21 @@ export abstract class BaseRender { init(contributions?: IContributionProvider>) { if (contributions) { - this.renderContribitions = contributions; + // this.renderContribitions = contributions; this._renderContribitions = contributions.getContributions(); - if (this._renderContribitions.length) { - this._renderContribitions.sort((a, b) => b.order - a.order); - this._beforeRenderContribitions = this._renderContribitions.filter( - c => c.time === BaseRenderContributionTime.beforeFillStroke - ); - this._afterRenderContribitions = this._renderContribitions.filter( - c => c.time === BaseRenderContributionTime.afterFillStroke - ); - } + } + if (!this._renderContribitions) { + this._renderContribitions = []; + } + this.builtinContributions && this.builtinContributions.forEach(item => this._renderContribitions.push(item)); + if (this._renderContribitions.length) { + this._renderContribitions.sort((a, b) => b.order - a.order); + this._beforeRenderContribitions = this._renderContribitions.filter( + c => c.time === BaseRenderContributionTime.beforeFillStroke + ); + this._afterRenderContribitions = this._renderContribitions.filter( + c => c.time === BaseRenderContributionTime.afterFillStroke + ); } } diff --git a/packages/vrender-core/src/render/contributions/render/circle-render.ts b/packages/vrender-core/src/render/contributions/render/circle-render.ts index 6f01336d5..95a4f9c0d 100644 --- a/packages/vrender-core/src/render/contributions/render/circle-render.ts +++ b/packages/vrender-core/src/render/contributions/render/circle-render.ts @@ -17,9 +17,12 @@ import { CIRCLE_NUMBER_TYPE } from '../../../graphic/constants'; import { CircleRenderContribution } from './contributions/constants'; // eslint-disable-next-line @typescript-eslint/consistent-type-imports import { ContributionProvider } from '../../../common/contribution-provider'; -import { drawPathProxy, fillVisible, runFill, runStroke, strokeVisible } from './utils'; -import { BaseRenderContributionTime } from '../../../common/enums'; import { BaseRender } from './base-render'; +import { + defaultCircleBackgroundRenderContribution, + defaultCircleRenderContribution, + defaultCircleTextureRenderContribution +} from './contributions'; @injectable() export class DefaultCanvasCircleRender extends BaseRender implements IGraphicRender { @@ -32,6 +35,11 @@ export class DefaultCanvasCircleRender extends BaseRender implements IG protected readonly circleRenderContribitions: IContributionProvider ) { super(); + this.builtinContributions = [ + defaultCircleRenderContribution, + defaultCircleBackgroundRenderContribution, + defaultCircleTextureRenderContribution + ]; this.init(circleRenderContribitions); } diff --git a/packages/vrender-core/src/render/contributions/render/contributions/arc-contribution-render.ts b/packages/vrender-core/src/render/contributions/render/contributions/arc-contribution-render.ts index a60ced61f..02801db29 100644 --- a/packages/vrender-core/src/render/contributions/render/contributions/arc-contribution-render.ts +++ b/packages/vrender-core/src/render/contributions/render/contributions/arc-contribution-render.ts @@ -11,13 +11,12 @@ import type { } from '../../../../interface'; import { getScaledStroke } from '../../../../common/canvas-utils'; import { - DefaultBaseBackgroundRenderContribution, - DefaultBaseTextureRenderContribution + defaultBaseBackgroundRenderContribution, + defaultBaseTextureRenderContribution } from './base-contribution-render'; import { drawArcPath } from '../utils'; import { BaseRenderContributionTime } from '../../../../common/enums'; -@injectable() export class DefaultArcRenderContribution implements IArcRenderContribution { time: BaseRenderContributionTime = BaseRenderContributionTime.afterFillStroke; useStyle: boolean = true; @@ -136,18 +135,6 @@ export class DefaultArcRenderContribution implements IArcRenderContribution { } } -@injectable() -export class DefaultArcBackgroundRenderContribution - extends DefaultBaseBackgroundRenderContribution - implements IArcRenderContribution -{ - time: BaseRenderContributionTime = BaseRenderContributionTime.beforeFillStroke; -} - -@injectable() -export class DefaultArcTextureRenderContribution - extends DefaultBaseTextureRenderContribution - implements IArcRenderContribution -{ - time: BaseRenderContributionTime = BaseRenderContributionTime.afterFillStroke; -} +export const defaultArcRenderContribution = new DefaultArcRenderContribution(); +export const defaultArcTextureRenderContribution = defaultBaseTextureRenderContribution; +export const defaultArcBackgroundRenderContribution = defaultBaseBackgroundRenderContribution; diff --git a/packages/vrender-core/src/render/contributions/render/contributions/area-contribution-render.ts b/packages/vrender-core/src/render/contributions/render/contributions/area-contribution-render.ts index c71f3996c..cc6c5cb7f 100644 --- a/packages/vrender-core/src/render/contributions/render/contributions/area-contribution-render.ts +++ b/packages/vrender-core/src/render/contributions/render/contributions/area-contribution-render.ts @@ -10,21 +10,12 @@ import type { IDrawContext } from '../../../../interface'; import { - DefaultBaseBackgroundRenderContribution, - DefaultBaseTextureRenderContribution + DefaultBaseTextureRenderContribution, + defaultBaseBackgroundRenderContribution } from './base-contribution-render'; import { getAttributeFromDefaultAttrList } from '../../../../common/utils'; import { BaseRenderContributionTime } from '../../../../common/enums'; -@injectable() -export class DefaultAreaBackgroundRenderContribution - extends DefaultBaseBackgroundRenderContribution - implements IAreaRenderContribution -{ - time: BaseRenderContributionTime = BaseRenderContributionTime.beforeFillStroke; -} - -@injectable() export class DefaultAreaTextureRenderContribution extends DefaultBaseTextureRenderContribution implements IAreaRenderContribution @@ -104,3 +95,6 @@ export class DefaultAreaTextureRenderContribution } } } + +export const defaultAreaTextureRenderContribution = new DefaultAreaTextureRenderContribution(); +export const defaultAreaBackgroundRenderContribution = defaultBaseBackgroundRenderContribution; diff --git a/packages/vrender-core/src/render/contributions/render/contributions/base-contribution-render.ts b/packages/vrender-core/src/render/contributions/render/contributions/base-contribution-render.ts index 0777dd796..cc157ee7c 100644 --- a/packages/vrender-core/src/render/contributions/render/contributions/base-contribution-render.ts +++ b/packages/vrender-core/src/render/contributions/render/contributions/base-contribution-render.ts @@ -16,7 +16,6 @@ import { BaseRenderContributionTime } from '../../../../common/enums'; import { ContributionProvider } from '../../../../common/contribution-provider'; import { InteractiveSubRenderContribution } from './constants'; -@injectable() export class DefaultBaseBackgroundRenderContribution implements IBaseRenderContribution { time: BaseRenderContributionTime = BaseRenderContributionTime.beforeFillStroke; useStyle: boolean = true; @@ -73,6 +72,8 @@ export class DefaultBaseBackgroundRenderContribution implements IBaseRenderContr } } +export const defaultBaseBackgroundRenderContribution = new DefaultBaseBackgroundRenderContribution(); + export interface IInteractiveSubRenderContribution { render: ( graphic: IGraphic, @@ -146,7 +147,6 @@ export class DefaultBaseInteractiveRenderContribution implements IBaseRenderCont // // @ts-ignore // 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFEAAABRCAYAAACqj0o2AAAAAXNSR0IArs4c6QAAByRJREFUeF7tnU1oXUUUx/+XLirxA8QGSdA0tGBNRFNBxYJCoRsXKkZQVFSwKKKFLhp14cbiwoWYgoEiorSgolIRQV24KRQUFAzYKMZaaIm1JEgiQtVgF+XKvPvmvbn3zsf/zLs3Hy/vbTMz557fnDkzc2bmJEnTNEXEb2Lfs5g8/HZETWGVS/9lFTZdJqwoLx6rUxIF8fwpJNePID1yAHhqUv61bA0FcPZwVnp0X70gj04g2XsI6e+/ANfdyH5ho5wc4vlTwGt7kLw1j/RJALtrBHn2Y2Dx20yhvqH6QB6dAE4cQvIekD43CLx8XARSBrEJEP/OZwIVRPWrA6QJUNvFVTuAkedFVhIs3ATYsCit0+UykDxEA2BOoP7KKkHaAGo5/buAbY8E2VAFDIAlnQQgOYgFgFaIVVmkD2CVIAsArTqRIMMQLQCdEDsFyQCsAqQFoFMnAqQfogOgF2IsSAnATkA6AHp1CoB0Q/QADEKUgvzjG2DuE8qNlQpJfKQHYFAnD0g7xADAoEDJZLM0DZx5Pw6grjWwBxi6399GACClkwNkGSIBkBLIgKwCoJaz/Qlgy212kARAVbH/GLD4cKA/LSDzEEmAIoiuoV0lQB9IEqBIpwLINkQBQJFAm0XWAdAGUgBQrJMBMoMoBCgWaIK879HOfWDIg6qh/cVHja2c5JfbhTEVmyAziMdexYMvvoLPzjE1uTLjQ1k5aZvju7dn9U6c8Qoa3HIF5pf+4T6GKDXYB8wvEwULRcbvGDECEHWavhKszX9gOIvMLFfYY6ZiOlCxMNcIlKh9PvsTW2Jzq5ufWAQgRQKLM5oOcVUNcvM1wM0vtUNmQjcl0smIFZSXOCRIWqBrkVo1yE19wOh+oG8gb3gCkNQSx7LasC+2CZAUxNC+8+JfwE+vA5cinJGJygVQlyFBUjpZolXubV8AZLDXQgC1gssLwOxUPMgQQAHIIERHuM8fgIjZrJuTCBtmjwXJAiRBeiF64qXhUJgkbBQDMNYipQAJkE6IgYBzGKISzgQwOwEoBRkLMADSCpGI2HMQLSBLAlkfGFq0MUPbF2wIte8BWdKJAKia4yEWQOYEVgVQK/j3WWD2TTuOKgA6QMYevskgGiBjT8ZYQ4EtSFElQAvI1oqDtEDdhBxiE2TjoDvijJaGqAqaIOsAWADZOEuPuJAQB1H5gSRBOvcDsHWniIu4sAKpfq6Aq7hBR4XfTiIZvhUxt2riIC5NI+m/HemPb9R3K6EqOEw7zS1ocssLSBe/F3eYHGJziCV3TiH9Tu1Vh4Ab9gKbr2Y+d+2VMfbwLZ2ErkMG0fBRLYEKS6frttVCWwiC5HQSgOQhFmbLnMD1CFKtR0+/A1z8s9WFJZ2GHwKuvSvYxRxEy3KjJHA9gXQs6PvveReLXz2dh0aca4chnvscWDhe6g0rxPUA0rMjcuoUAOmH6Lna4RS4lkEGtpRenTwg3RADd2O8AjXIHc8AV24L+pQVKUDsyYM6OUDaIRKXi4ICNRnBLFcbTAKgkk3pZAFZhkgApAWuBZBqUpz7lIqcjz3+IWY+eCzclwrk1gdaB2J5iCRAMURVYTUsUnjTYmLqa0zuvzsMUZUw7pBnENWi8/QR4MKvXAOs6RdbW0mQQoBRhtEEmUEUWKDmQvkPW5fsPFj/FlGdIp48SBtERzr172oGZXuW2OAoNoycJequEFikWOBKDmWtj3BIi3Qq+UTT8EmQIoGrAdAEuaKzs8AirftMmxdaTYD6e8h1IjU7U+tEEmTQElV4bEPvWAiQvb1ze9j1ojiGC6oniuOZ5boxnmjVqZJ4ogNkN0a2S3vnSiPbFpDdeMaSm50Fq4qwTywuW3qnfaWFnByiaqJ37pwDGQexdwOiAog66UTvLk4WuBBnIzGTTqgcEFVfq/MFDwTOno6D2fJa1HorzLgxm7v4XjXIrr2f6Es6obq9KpBMsKAKi2TyWpAWyQ3nDXJne+xLYObegiMgQIYhbqDXAxPTwKTt3XlHrwd671jaZhn1jqWTpBMSH8n4QN9Uy17rI56mVfuiqve2z91t1Ns+AmBjgWnmCvNZyjp6ZUrrVAAZ/d45+EDSBLth3juTFqjZ0L2mK3T9y/sackDQ2651XrCdA4KYuYq6ii1RNaB8SddmI1EKCkGKIZrOWHgzQWSs5pawThdVyoujv1IAUgTRtlCtA6RtTy0ASU+WzgxNQpA0RN+WqUqQFeQKo3QK5goTgKQEEpt362tS0fgFsOay1pEggxAZgFpWV+ZPJEDGJp1wGhl5Gy1XnzhYL8mLCapEZ/IMgIxNOuEdqRKQMQC1cEl4jwg2h+OJjuVPbNKJoLtjQHYC0AMyNq8FB9ECsrQckPjAEMmuzLNtGdqxSSdC/Fp/78qM7wWQvf890DYHfjibJtT7Lxi5ARUHEcDYTaOY+XmWHp3RBVfw/7HE6vQ/kFqNtpDetQkAAAAASUVORK5CYII='; -@injectable() export class DefaultBaseTextureRenderContribution implements IBaseRenderContribution { time: BaseRenderContributionTime = BaseRenderContributionTime.afterFillStroke; useStyle: boolean = true; @@ -351,3 +351,5 @@ export class DefaultBaseTextureRenderContribution implements IBaseRenderContribu } } } + +export const defaultBaseTextureRenderContribution = new DefaultBaseTextureRenderContribution(); diff --git a/packages/vrender-core/src/render/contributions/render/contributions/circle-contribution-render.ts b/packages/vrender-core/src/render/contributions/render/contributions/circle-contribution-render.ts index a1a83450f..16819d78c 100644 --- a/packages/vrender-core/src/render/contributions/render/contributions/circle-contribution-render.ts +++ b/packages/vrender-core/src/render/contributions/render/contributions/circle-contribution-render.ts @@ -11,12 +11,11 @@ import type { } from '../../../../interface'; import { getScaledStroke } from '../../../../common/canvas-utils'; import { - DefaultBaseBackgroundRenderContribution, - DefaultBaseTextureRenderContribution + defaultBaseBackgroundRenderContribution, + defaultBaseTextureRenderContribution } from './base-contribution-render'; import { BaseRenderContributionTime } from '../../../../common/enums'; -@injectable() export class DefaultCircleRenderContribution implements ICircleRenderContribution { time: BaseRenderContributionTime = BaseRenderContributionTime.afterFillStroke; useStyle: boolean = true; @@ -124,18 +123,6 @@ export class DefaultCircleRenderContribution implements ICircleRenderContributio } } -@injectable() -export class DefaultCircleBackgroundRenderContribution - extends DefaultBaseBackgroundRenderContribution - implements ICircleRenderContribution -{ - time: BaseRenderContributionTime = BaseRenderContributionTime.beforeFillStroke; -} - -@injectable() -export class DefaultCircleTextureRenderContribution - extends DefaultBaseTextureRenderContribution - implements ICircleRenderContribution -{ - time: BaseRenderContributionTime = BaseRenderContributionTime.afterFillStroke; -} +export const defaultCircleRenderContribution = new DefaultCircleRenderContribution(); +export const defaultCircleTextureRenderContribution = defaultBaseTextureRenderContribution; +export const defaultCircleBackgroundRenderContribution = defaultBaseBackgroundRenderContribution; diff --git a/packages/vrender-core/src/render/contributions/render/contributions/constants.ts b/packages/vrender-core/src/render/contributions/render/contributions/constants.ts index b69d856bc..a349b0721 100644 --- a/packages/vrender-core/src/render/contributions/render/contributions/constants.ts +++ b/packages/vrender-core/src/render/contributions/render/contributions/constants.ts @@ -8,4 +8,5 @@ export const PolygonRenderContribution = Symbol.for('PolygonRenderContribution') export const RectRenderContribution = Symbol.for('RectRenderContribution'); export const SymbolRenderContribution = Symbol.for('SymbolRenderContribution'); export const TextRenderContribution = Symbol.for('TextRenderContribution'); +export const CommonRenderContribution = Symbol.for('CommonRenderContribution'); export const InteractiveSubRenderContribution = Symbol.for('InteractiveSubRenderContribution'); diff --git a/packages/vrender-core/src/render/contributions/render/contributions/group-contribution-render.ts b/packages/vrender-core/src/render/contributions/render/contributions/group-contribution-render.ts index ae90d267d..78fc8fb1c 100644 --- a/packages/vrender-core/src/render/contributions/render/contributions/group-contribution-render.ts +++ b/packages/vrender-core/src/render/contributions/render/contributions/group-contribution-render.ts @@ -10,7 +10,6 @@ import type { import { DefaultBaseBackgroundRenderContribution } from './base-contribution-render'; import { BaseRenderContributionTime } from '../../../../common/enums'; -@injectable() export class DefaultGroupBackgroundRenderContribution extends DefaultBaseBackgroundRenderContribution implements IGroupRenderContribution @@ -57,3 +56,5 @@ export class DefaultGroupBackgroundRenderContribution } } } + +export const defaultGroupBackgroundRenderContribution = new DefaultGroupBackgroundRenderContribution(); diff --git a/packages/vrender-core/src/render/contributions/render/contributions/image-contribution-render.ts b/packages/vrender-core/src/render/contributions/render/contributions/image-contribution-render.ts index f16800a19..2c23a6ad6 100644 --- a/packages/vrender-core/src/render/contributions/render/contributions/image-contribution-render.ts +++ b/packages/vrender-core/src/render/contributions/render/contributions/image-contribution-render.ts @@ -16,7 +16,6 @@ import { isNumber, isObject } from '@visactor/vutils'; import { parsePadding } from '../../../../common/utils'; import { createRectPath } from '../../../../common/shape/rect'; -@injectable() export class DefaultImageBackgroundRenderContribution extends DefaultBaseBackgroundRenderContribution implements IImageRenderContribution @@ -134,3 +133,5 @@ function getActualPosition(graphic: IGraphic) { height }; } + +export const defaultImageBackgroundRenderContribution = new DefaultImageBackgroundRenderContribution(); diff --git a/packages/vrender-core/src/render/contributions/render/contributions/path-contribution-render.ts b/packages/vrender-core/src/render/contributions/render/contributions/path-contribution-render.ts index 869d71049..910b923b0 100644 --- a/packages/vrender-core/src/render/contributions/render/contributions/path-contribution-render.ts +++ b/packages/vrender-core/src/render/contributions/render/contributions/path-contribution-render.ts @@ -1,23 +1,7 @@ -import { injectable } from '../../../../common/inversify-lite'; -import type { IPathRenderContribution } from '../../../../interface'; import { - DefaultBaseBackgroundRenderContribution, - DefaultBaseTextureRenderContribution + defaultBaseBackgroundRenderContribution, + defaultBaseTextureRenderContribution } from './base-contribution-render'; -import { BaseRenderContributionTime } from '../../../../common/enums'; -@injectable() -export class DefaultPathBackgroundRenderContribution - extends DefaultBaseBackgroundRenderContribution - implements IPathRenderContribution -{ - time: BaseRenderContributionTime = BaseRenderContributionTime.beforeFillStroke; -} - -@injectable() -export class DefaultPathTextureRenderContribution - extends DefaultBaseTextureRenderContribution - implements IPathRenderContribution -{ - time: BaseRenderContributionTime = BaseRenderContributionTime.afterFillStroke; -} +export const defaultPathTextureRenderContribution = defaultBaseTextureRenderContribution; +export const defaultPathBackgroundRenderContribution = defaultBaseBackgroundRenderContribution; diff --git a/packages/vrender-core/src/render/contributions/render/contributions/polygon-contribution-render.ts b/packages/vrender-core/src/render/contributions/render/contributions/polygon-contribution-render.ts index e4887bcf7..1f95a5d68 100644 --- a/packages/vrender-core/src/render/contributions/render/contributions/polygon-contribution-render.ts +++ b/packages/vrender-core/src/render/contributions/render/contributions/polygon-contribution-render.ts @@ -1,23 +1,7 @@ -import { injectable } from '../../../../common/inversify-lite'; -import type { IPolygonRenderContribution } from '../../../../interface'; import { - DefaultBaseBackgroundRenderContribution, - DefaultBaseTextureRenderContribution + defaultBaseBackgroundRenderContribution, + defaultBaseTextureRenderContribution } from './base-contribution-render'; -import { BaseRenderContributionTime } from '../../../../common/enums'; -@injectable() -export class DefaultPolygonBackgroundRenderContribution - extends DefaultBaseBackgroundRenderContribution - implements IPolygonRenderContribution -{ - time: BaseRenderContributionTime = BaseRenderContributionTime.beforeFillStroke; -} - -@injectable() -export class DefaultPolygonTextureRenderContribution - extends DefaultBaseTextureRenderContribution - implements IPolygonRenderContribution -{ - time: BaseRenderContributionTime = BaseRenderContributionTime.afterFillStroke; -} +export const defaultPolygonTextureRenderContribution = defaultBaseTextureRenderContribution; +export const defaultPolygonBackgroundRenderContribution = defaultBaseBackgroundRenderContribution; diff --git a/packages/vrender-core/src/render/contributions/render/contributions/rect-contribution-render.ts b/packages/vrender-core/src/render/contributions/render/contributions/rect-contribution-render.ts index 601d70f4f..22a198bf6 100644 --- a/packages/vrender-core/src/render/contributions/render/contributions/rect-contribution-render.ts +++ b/packages/vrender-core/src/render/contributions/render/contributions/rect-contribution-render.ts @@ -12,13 +12,12 @@ import type { } from '../../../../interface'; import { getScaledStroke } from '../../../../common/canvas-utils'; import { - DefaultBaseBackgroundRenderContribution, - DefaultBaseTextureRenderContribution + defaultBaseBackgroundRenderContribution, + defaultBaseTextureRenderContribution } from './base-contribution-render'; import { createRectPath } from '../../../../common/shape/rect'; import { BaseRenderContributionTime } from '../../../../common/enums'; -@injectable() export class DefaultRectRenderContribution implements IRectRenderContribution { time: BaseRenderContributionTime = BaseRenderContributionTime.afterFillStroke; useStyle: boolean = true; @@ -143,23 +142,6 @@ export class DefaultRectRenderContribution implements IRectRenderContribution { } } -@injectable() -export class DefaultRectBackgroundRenderContribution - extends DefaultBaseBackgroundRenderContribution - implements IRectRenderContribution -{ - time: BaseRenderContributionTime = BaseRenderContributionTime.beforeFillStroke; -} - -@injectable() -export class DefaultRectTextureRenderContribution - extends DefaultBaseTextureRenderContribution - implements IRectRenderContribution -{ - time: BaseRenderContributionTime = BaseRenderContributionTime.afterFillStroke; -} - -@injectable() export class SplitRectBeforeRenderContribution implements IRectRenderContribution { time: BaseRenderContributionTime = BaseRenderContributionTime.beforeFillStroke; useStyle: boolean = true; @@ -196,7 +178,6 @@ export class SplitRectBeforeRenderContribution implements IRectRenderContributio } } -@injectable() export class SplitRectAfterRenderContribution implements IRectRenderContribution { time: BaseRenderContributionTime = BaseRenderContributionTime.afterFillStroke; useStyle: boolean = true; @@ -268,3 +249,9 @@ export class SplitRectAfterRenderContribution implements IRectRenderContribution context.stroke(); } } + +export const defaultRectRenderContribution = new DefaultRectRenderContribution(); +export const splitRectBeforeRenderContribution = new SplitRectBeforeRenderContribution(); +export const splitRectAfterRenderContribution = new SplitRectAfterRenderContribution(); +export const defaultRectTextureRenderContribution = defaultBaseTextureRenderContribution; +export const defaultRectBackgroundRenderContribution = defaultBaseBackgroundRenderContribution; diff --git a/packages/vrender-core/src/render/contributions/render/contributions/symbol-contribution-render.ts b/packages/vrender-core/src/render/contributions/render/contributions/symbol-contribution-render.ts index 9ae0b46c5..f5f0e8441 100644 --- a/packages/vrender-core/src/render/contributions/render/contributions/symbol-contribution-render.ts +++ b/packages/vrender-core/src/render/contributions/render/contributions/symbol-contribution-render.ts @@ -11,12 +11,11 @@ import type { } from '../../../../interface'; import { getScaledStroke } from '../../../../common/canvas-utils'; import { - DefaultBaseBackgroundRenderContribution, - DefaultBaseTextureRenderContribution + defaultBaseBackgroundRenderContribution, + defaultBaseTextureRenderContribution } from './base-contribution-render'; import { BaseRenderContributionTime } from '../../../../common/enums'; -@injectable() export class DefaultSymbolRenderContribution implements ISymbolRenderContribution { time: BaseRenderContributionTime = BaseRenderContributionTime.afterFillStroke; useStyle: boolean = true; @@ -130,16 +129,6 @@ export class DefaultSymbolRenderContribution implements ISymbolRenderContributio } } -export class DefaultSymbolBackgroundRenderContribution - extends DefaultBaseBackgroundRenderContribution - implements ISymbolRenderContribution -{ - time: BaseRenderContributionTime = BaseRenderContributionTime.beforeFillStroke; -} - -export class DefaultSymbolTextureRenderContribution - extends DefaultBaseTextureRenderContribution - implements ISymbolRenderContribution -{ - time: BaseRenderContributionTime = BaseRenderContributionTime.afterFillStroke; -} +export const defaultSymbolRenderContribution = new DefaultSymbolRenderContribution(); +export const defaultSymbolTextureRenderContribution = defaultBaseTextureRenderContribution; +export const defaultSymbolBackgroundRenderContribution = defaultBaseBackgroundRenderContribution; diff --git a/packages/vrender-core/src/render/contributions/render/draw-contribution.ts b/packages/vrender-core/src/render/contributions/render/draw-contribution.ts index b601fdb3b..0a260df88 100644 --- a/packages/vrender-core/src/render/contributions/render/draw-contribution.ts +++ b/packages/vrender-core/src/render/contributions/render/draw-contribution.ts @@ -20,15 +20,14 @@ import { ContributionProvider } from '../../../common/contribution-provider'; import { DefaultAttribute } from '../../../graphic'; import type { IAABBBounds, IBounds, IMatrixLike } from '@visactor/vutils'; import { Bounds, getRectIntersect, isRectIntersect, last } from '@visactor/vutils'; -import { LayerService } from '../../../core/constants'; import { container } from '../../../container'; import { GraphicRender, IncrementalDrawContribution, RenderSelector } from './symbol'; import { DrawItemInterceptor } from './draw-interceptor'; import { createColor } from '../../../common/canvas-utils'; import type { ILayerService } from '../../../interface/core'; -import { VGlobal } from '../../../constants'; import { boundsAllocate } from '../../../allocator/bounds-allocate'; import { matrixAllocate } from '../../../allocator/matrix-allocate'; +import { application } from '../../../application'; /** * 默认的渲染contribution,基于树状结构针对图元的渲染 @@ -43,15 +42,15 @@ export class DefaultDrawContribution implements IDrawContribution { declare currentRenderService: IRenderService; declare InterceptorContributions: IDrawItemInterceptorContribution[]; - @inject(VGlobal) global: IGlobal; + declare global: IGlobal; + declare layerService: ILayerService; constructor( // @inject(ContributionProvider) // @named(GraphicRender) // protected readonly contributions: ContributionProvider, @multiInject(GraphicRender) protected readonly contributions: IGraphicRender[], - @inject(RenderSelector) protected readonly renderSelector: IRenderSelector, // 根据图元类型选择对应的renderItem进行渲染 - @inject(LayerService) protected readonly layerService: ILayerService, // 默认的polygonRender + // @inject(RenderSelector) protected readonly renderSelector: IRenderSelector, // 根据图元类型选择对应的renderItem进行渲染 // 拦截器 @inject(ContributionProvider) @named(DrawItemInterceptor) @@ -62,6 +61,8 @@ export class DefaultDrawContribution implements IDrawContribution { this.styleRenderMap = new Map(); this.dirtyBounds = new Bounds(); this.backupDirtyBounds = new Bounds(); + this.global = application.global; + this.layerService = application.layerService; } @postConstruct() @@ -289,7 +290,8 @@ export class DefaultDrawContribution implements IDrawContribution { } getRenderContribution(graphic: IGraphic): IGraphicRender | null { - let renderer = this.renderSelector.selector(graphic); + // let renderer = this.renderSelector.selector(graphic); + let renderer; if (!renderer) { renderer = this.selectRenderByNumberType(graphic.numberType); } diff --git a/packages/vrender-core/src/render/contributions/render/group-render.ts b/packages/vrender-core/src/render/contributions/render/group-render.ts index eb6432144..d2cd0fed2 100644 --- a/packages/vrender-core/src/render/contributions/render/group-render.ts +++ b/packages/vrender-core/src/render/contributions/render/group-render.ts @@ -22,6 +22,7 @@ import { GroupRenderContribution } from './contributions/constants'; import { mat4Allocate } from '../../../allocator/matrix-allocate'; import { GROUP_NUMBER_TYPE } from '../../../graphic/constants'; import { BaseRenderContributionTime } from '../../../common/enums'; +import { defaultGroupBackgroundRenderContribution } from './contributions'; @injectable() export class DefaultCanvasGroupRender implements IGraphicRender { @@ -120,6 +121,7 @@ export class DefaultCanvasGroupRender implements IGraphicRender { if (!this._groupRenderContribitions) { this._groupRenderContribitions = this.groupRenderContribitions.getContributions() || []; + this._groupRenderContribitions.push(defaultGroupBackgroundRenderContribution); } const doFillOrStroke = { diff --git a/packages/vrender-core/src/render/contributions/render/image-render.ts b/packages/vrender-core/src/render/contributions/render/image-render.ts index 8939d79ee..32200e28c 100644 --- a/packages/vrender-core/src/render/contributions/render/image-render.ts +++ b/packages/vrender-core/src/render/contributions/render/image-render.ts @@ -22,6 +22,7 @@ import { BaseRenderContributionTime } from '../../../common/enums'; import { isArray } from '@visactor/vutils'; import { createRectPath } from '../../../common/shape/rect'; import { BaseRender } from './base-render'; +import { defaultImageBackgroundRenderContribution } from './contributions'; const repeatStr = ['', 'repeat-x', 'repeat-y', 'repeat']; @@ -36,6 +37,7 @@ export class DefaultCanvasImageRender extends BaseRender implements IGra protected readonly imageRenderContribitions: IContributionProvider ) { super(); + this.builtinContributions = [defaultImageBackgroundRenderContribution]; this.init(imageRenderContribitions); } diff --git a/packages/vrender-core/src/render/contributions/render/incremental-draw-contribution.ts b/packages/vrender-core/src/render/contributions/render/incremental-draw-contribution.ts index cadfbd834..761a7c75e 100644 --- a/packages/vrender-core/src/render/contributions/render/incremental-draw-contribution.ts +++ b/packages/vrender-core/src/render/contributions/render/incremental-draw-contribution.ts @@ -22,8 +22,6 @@ import { DrawItemInterceptor } from './draw-interceptor'; // eslint-disable-next-line @typescript-eslint/consistent-type-imports import { ContributionProvider } from '../../../common/contribution-provider'; import { foreachAsync } from '../../../common/sort'; -import type { ILayerService } from '../../../interface/core'; -import { VGlobal } from '../../../constants'; enum STATUS { NORMAL = 0, @@ -47,23 +45,21 @@ export class DefaultIncrementalDrawContribution extends DefaultDrawContribution protected lastRenderService: IRenderService; protected lastDrawContext: IDrawContext; protected count: number; - @inject(VGlobal) global: IGlobal; constructor( // @inject(ContributionProvider) // @named(GraphicRender) // protected readonly contributions: ContributionProvider, @multiInject(GraphicRender) protected readonly contributions: IGraphicRender[], - @inject(RenderSelector) protected readonly renderSelector: IRenderSelector, // 根据图元类型选择对应的renderItem进行渲染 + // @inject(RenderSelector) protected readonly renderSelector: IRenderSelector, // 根据图元类型选择对应的renderItem进行渲染 @inject(DefaultIncrementalCanvasLineRender) protected readonly lineRender: IGraphicRender, // 默认的lineRender @inject(DefaultIncrementalCanvasAreaRender) protected readonly areaRender: IGraphicRender, // 默认的lineRender - @inject(LayerService) protected readonly layerService: ILayerService, // 默认的polygonRender // 拦截器 @inject(ContributionProvider) @named(DrawItemInterceptor) protected readonly drawItemInterceptorContributions: IContributionProvider ) { - super(contributions, renderSelector, layerService, drawItemInterceptorContributions); + super(contributions, drawItemInterceptorContributions); } init(): void { diff --git a/packages/vrender-core/src/render/contributions/render/module.ts b/packages/vrender-core/src/render/contributions/render/module.ts index 9efc1275a..9e333eebc 100644 --- a/packages/vrender-core/src/render/contributions/render/module.ts +++ b/packages/vrender-core/src/render/contributions/render/module.ts @@ -4,7 +4,7 @@ import { DefaultCanvasCircleRender } from './circle-render'; import { DefaultCanvasRectRender } from './rect-render'; import { DefaultCanvasArcRender } from './arc-render'; import { DefaultDrawContribution } from './draw-contribution'; -import { DefaultRenderSelector } from './render-slector'; +// import { DefaultRenderSelector } from './render-slector'; import { DefaultCanvasSymbolRender } from './symbol-render'; import { DefaultCanvasTextRender } from './text-render'; import { DefaultCanvasPathRender } from './path-render'; @@ -47,45 +47,10 @@ import { DefaultCanvasRect3dRender } from './rect3d-render'; import { DefaultIncrementalCanvasLineRender } from './incremental-line-render'; import { DefaultIncrementalCanvasAreaRender } from './incremental-area-render'; import { DefaultCanvasRichTextRender } from './richtext-render'; -import { - DefaultRectBackgroundRenderContribution, - DefaultRectRenderContribution, - DefaultRectTextureRenderContribution, - SplitRectAfterRenderContribution, - SplitRectBeforeRenderContribution -} from './contributions/rect-contribution-render'; -import { - DefaultSymbolBackgroundRenderContribution, - DefaultSymbolRenderContribution, - DefaultSymbolTextureRenderContribution -} from './contributions/symbol-contribution-render'; -import { - DefaultCircleBackgroundRenderContribution, - DefaultCircleRenderContribution, - DefaultCircleTextureRenderContribution -} from './contributions/circle-contribution-render'; -import { - DefaultArcBackgroundRenderContribution, - DefaultArcRenderContribution, - DefaultArcTextureRenderContribution -} from './contributions/arc-contribution-render'; +import { DefaultSymbolRenderContribution } from './contributions/symbol-contribution-render'; import { DefaultCanvasGlyphRender } from './glyph-render'; -import { DefaultImageBackgroundRenderContribution } from './contributions/image-contribution-render'; -import { DefaultGroupBackgroundRenderContribution } from './contributions/group-contribution-render'; import { DefaultCanvasArc3DRender } from './arc3d-render'; import { DefaultCanvasPyramid3dRender } from './pyramid3d-render'; -import { - DefaultPolygonBackgroundRenderContribution, - DefaultPolygonTextureRenderContribution -} from './contributions/polygon-contribution-render'; -import { - DefaultPathBackgroundRenderContribution, - DefaultPathTextureRenderContribution -} from './contributions/path-contribution-render'; -import { - DefaultAreaBackgroundRenderContribution, - DefaultAreaTextureRenderContribution -} from './contributions/area-contribution-render'; import { RectRenderContribution, CircleRenderContribution, @@ -99,171 +64,115 @@ import { SymbolRenderContribution, InteractiveSubRenderContribution } from './contributions/constants'; -import { DefaultBaseInteractiveRenderContribution } from './contributions'; +import { + DefaultBaseBackgroundRenderContribution, + DefaultBaseInteractiveRenderContribution, + DefaultBaseTextureRenderContribution +} from './contributions'; export default new ContainerModule(bind => { - bind(DefaultDrawContribution).toSelf(); - bind(DrawContribution).toService(DefaultDrawContribution); - bind(DefaultIncrementalDrawContribution).toSelf(); - bind(IncrementalDrawContribution).toService(DefaultIncrementalDrawContribution); + bind(DefaultBaseBackgroundRenderContribution).toSelf().inSingletonScope(); + bind(DefaultBaseTextureRenderContribution).toSelf().inSingletonScope(); + + bind(DrawContribution).to(DefaultDrawContribution); + bind(IncrementalDrawContribution).to(DefaultIncrementalDrawContribution); - bind(DefaultRenderSelector).toSelf(); - bind(RenderSelector).toService(DefaultRenderSelector); + // bind(RenderSelector).to(DefaultRenderSelector).inSingletonScope(); // circle 渲染器 - bind(DefaultCanvasCircleRender).toSelf().inSingletonScope(); - bind(CircleRender).to(DefaultCanvasCircleRender); - bind(GraphicRender).to(DefaultCanvasCircleRender); + bind(CircleRender).to(DefaultCanvasCircleRender).inSingletonScope(); + bind(GraphicRender).toService(CircleRender); // circle 渲染器注入contributions - bind(DefaultCircleRenderContribution).toSelf().inSingletonScope(); - bind(DefaultCircleBackgroundRenderContribution).toSelf().inSingletonScope(); - bind(DefaultCircleTextureRenderContribution).toSelf().inSingletonScope(); - bind(CircleRenderContribution).toService(DefaultCircleRenderContribution); - bind(CircleRenderContribution).toService(DefaultCircleBackgroundRenderContribution); - bind(CircleRenderContribution).toService(DefaultCircleTextureRenderContribution); bindContributionProvider(bind, CircleRenderContribution); // rect 渲染器 - bind(DefaultCanvasRectRender).toSelf().inSingletonScope(); - bind(RectRender).to(DefaultCanvasRectRender); - bind(GraphicRender).to(DefaultCanvasRectRender); + bind(RectRender).to(DefaultCanvasRectRender).inSingletonScope(); + bind(GraphicRender).toService(RectRender); // rect3d 渲染器 - bind(DefaultCanvasRect3dRender).toSelf().inSingletonScope(); - bind(Rect3DRender).toService(DefaultCanvasRect3dRender); + bind(Rect3DRender).to(DefaultCanvasRect3dRender).inSingletonScope(); bind(GraphicRender).toService(Rect3DRender); + // rect 渲染器注入contributions - bind(DefaultRectRenderContribution).toSelf().inSingletonScope(); - bind(DefaultRectBackgroundRenderContribution).toSelf().inSingletonScope(); - bind(DefaultRectTextureRenderContribution).toSelf().inSingletonScope(); - bind(SplitRectBeforeRenderContribution).toSelf().inSingletonScope(); - bind(SplitRectAfterRenderContribution).toSelf().inSingletonScope(); - bind(RectRenderContribution).toService(DefaultRectRenderContribution); - bind(RectRenderContribution).toService(DefaultRectBackgroundRenderContribution); - bind(RectRenderContribution).toService(DefaultRectTextureRenderContribution); - bind(RectRenderContribution).toService(SplitRectBeforeRenderContribution); - bind(RectRenderContribution).toService(SplitRectAfterRenderContribution); bindContributionProvider(bind, RectRenderContribution); // text 渲染器 - bind(DefaultCanvasTextRender).toSelf().inSingletonScope(); - bind(TextRender).to(DefaultCanvasTextRender); - bind(GraphicRender).to(DefaultCanvasTextRender); + bind(TextRender).to(DefaultCanvasTextRender).inSingletonScope(); + bind(GraphicRender).toService(TextRender); bindContributionProvider(bind, TextRenderContribution); // path 渲染器 - bind(DefaultCanvasPathRender).toSelf().inSingletonScope(); - bind(PathRender).to(DefaultCanvasPathRender); - bind(GraphicRender).to(DefaultCanvasPathRender); + bind(PathRender).to(DefaultCanvasPathRender).inSingletonScope(); + bind(GraphicRender).toService(PathRender); // path 渲染器注入contributions - bind(DefaultPathBackgroundRenderContribution).toSelf().inSingletonScope(); - bind(DefaultPathTextureRenderContribution).toSelf().inSingletonScope(); - bind(PathRenderContribution).toService(DefaultPathBackgroundRenderContribution); - bind(PathRenderContribution).toService(DefaultPathTextureRenderContribution); bindContributionProvider(bind, PathRenderContribution); // symbol渲染器 - bind(DefaultCanvasSymbolRender).toSelf().inSingletonScope(); - bind(SymbolRender).to(DefaultCanvasSymbolRender); - bind(GraphicRender).to(DefaultCanvasSymbolRender); + bind(SymbolRender).to(DefaultCanvasSymbolRender).inSingletonScope(); + bind(GraphicRender).toService(SymbolRender); // symbol 渲染器注入contributions - bind(DefaultSymbolRenderContribution).toSelf().inSingletonScope(); - bind(DefaultSymbolBackgroundRenderContribution).toSelf().inSingletonScope(); - bind(DefaultSymbolTextureRenderContribution).toSelf().inSingletonScope(); - bind(SymbolRenderContribution).toService(DefaultSymbolRenderContribution); - bind(SymbolRenderContribution).toService(DefaultSymbolBackgroundRenderContribution); - bind(SymbolRenderContribution).toService(DefaultSymbolTextureRenderContribution); bindContributionProvider(bind, SymbolRenderContribution); // arc 渲染器 - bind(DefaultCanvasArcRender).toSelf().inSingletonScope(); - bind(ArcRender).to(DefaultCanvasArcRender); - bind(GraphicRender).to(DefaultCanvasArcRender); + bind(ArcRender).to(DefaultCanvasArcRender).inSingletonScope(); + bind(GraphicRender).toService(ArcRender); // arc3d 渲染器 - bind(DefaultCanvasArc3DRender).toSelf().inSingletonScope(); - bind(Arc3dRender).toService(DefaultCanvasArc3DRender); + bind(Arc3dRender).to(DefaultCanvasArc3DRender).inSingletonScope(); bind(GraphicRender).toService(Arc3dRender); // arc 渲染器注入contributions - bind(DefaultArcRenderContribution).toSelf().inSingletonScope(); - bind(DefaultArcBackgroundRenderContribution).toSelf().inSingletonScope(); - bind(DefaultArcTextureRenderContribution).toSelf().inSingletonScope(); - bind(ArcRenderContribution).toService(DefaultArcRenderContribution); - bind(ArcRenderContribution).toService(DefaultArcBackgroundRenderContribution); - bind(ArcRenderContribution).toService(DefaultArcTextureRenderContribution); bindContributionProvider(bind, ArcRenderContribution); // line渲染器 - bind(DefaultCanvasLineRender).toSelf().inSingletonScope(); - bind(LineRender).to(DefaultCanvasLineRender); - bind(GraphicRender).to(DefaultCanvasLineRender); + bind(LineRender).to(DefaultCanvasLineRender).inSingletonScope(); + bind(GraphicRender).toService(LineRender); // incremental-line渲染器 bind(DefaultIncrementalCanvasLineRender).toSelf().inSingletonScope(); bind(DefaultIncrementalCanvasAreaRender).toSelf().inSingletonScope(); // area渲染器 - bind(DefaultCanvasAreaRender).toSelf().inSingletonScope(); - bind(AreaRender).to(DefaultCanvasAreaRender); - bind(GraphicRender).to(DefaultCanvasAreaRender); + bind(AreaRender).to(DefaultCanvasAreaRender).inSingletonScope(); + bind(GraphicRender).toService(AreaRender); // area 渲染器注入contributions - bind(DefaultAreaBackgroundRenderContribution).toSelf().inSingletonScope(); - bind(DefaultAreaTextureRenderContribution).toSelf().inSingletonScope(); - - bind(AreaRenderContribution).toService(DefaultAreaBackgroundRenderContribution); - bind(AreaRenderContribution).toService(DefaultAreaTextureRenderContribution); bindContributionProvider(bind, AreaRenderContribution); // group渲染器 - bind(DefaultCanvasGroupRender).toSelf().inSingletonScope(); - bind(GroupRender).to(DefaultCanvasGroupRender); - bind(GraphicRender).to(DefaultCanvasGroupRender); + bind(GroupRender).to(DefaultCanvasGroupRender).inSingletonScope(); + bind(GraphicRender).toService(GroupRender); - // group 渲染器注入contributions\ - bind(DefaultGroupBackgroundRenderContribution).toSelf().inSingletonScope(); - bind(GroupRenderContribution).toService(DefaultGroupBackgroundRenderContribution); + // group 渲染器注入contributions bindContributionProvider(bind, GroupRenderContribution); // polygon渲染器 - bind(DefaultCanvasPolygonRender).toSelf().inSingletonScope(); - bind(PolygonRender).to(DefaultCanvasPolygonRender); - bind(GraphicRender).to(DefaultCanvasPolygonRender); + bind(PolygonRender).to(DefaultCanvasPolygonRender).inSingletonScope(); + bind(GraphicRender).toService(PolygonRender); // polygon 渲染器注入contributions - bind(DefaultPolygonBackgroundRenderContribution).toSelf().inSingletonScope(); - bind(DefaultPolygonTextureRenderContribution).toSelf().inSingletonScope(); - bind(PolygonRenderContribution).toService(DefaultPolygonBackgroundRenderContribution); - bind(PolygonRenderContribution).toService(DefaultPolygonTextureRenderContribution); bindContributionProvider(bind, PolygonRenderContribution); // glyph渲染器 - bind(DefaultCanvasGlyphRender).toSelf().inSingletonScope(); - bind(GlyphRender).toService(DefaultCanvasGlyphRender); + bind(GlyphRender).to(DefaultCanvasGlyphRender).inSingletonScope(); bind(GraphicRender).toService(GlyphRender); // image渲染器 - bind(DefaultCanvasImageRender).toSelf().inSingletonScope(); - bind(ImageRender).toService(DefaultCanvasImageRender); + bind(ImageRender).to(DefaultCanvasImageRender).inSingletonScope(); bind(GraphicRender).toService(ImageRender); // image 渲染器注入contributions - bind(DefaultImageBackgroundRenderContribution).toSelf().inSingletonScope(); - bind(ImageRenderContribution).toService(DefaultImageBackgroundRenderContribution); bindContributionProvider(bind, ImageRenderContribution); // richtext渲染器 - bind(DefaultCanvasRichTextRender).toSelf().inSingletonScope(); - bind(RichTextRender).toService(DefaultCanvasRichTextRender); + bind(RichTextRender).to(DefaultCanvasRichTextRender).inSingletonScope(); bind(GraphicRender).toService(RichTextRender); // pyramid3d 渲染器 - bind(DefaultCanvasPyramid3dRender).toSelf().inSingletonScope(); - bind(Pyramid3dRender).toService(DefaultCanvasPyramid3dRender); + bind(Pyramid3dRender).to(DefaultCanvasPyramid3dRender).inSingletonScope(); bind(GraphicRender).toService(Pyramid3dRender); // 绑定通用interactive contribution diff --git a/packages/vrender-core/src/render/contributions/render/path-render.ts b/packages/vrender-core/src/render/contributions/render/path-render.ts index 2bcc90d0b..1cbc55dc7 100644 --- a/packages/vrender-core/src/render/contributions/render/path-render.ts +++ b/packages/vrender-core/src/render/contributions/render/path-render.ts @@ -23,6 +23,10 @@ import { PathRenderContribution } from './contributions/constants'; import { BaseRenderContributionTime } from '../../../common/enums'; import { BaseRender } from './base-render'; import { mat4Allocate } from '../../../allocator/matrix-allocate'; +import { + defaultPathBackgroundRenderContribution, + defaultPathTextureRenderContribution +} from './contributions/path-contribution-render'; @injectable() export class DefaultCanvasPathRender extends BaseRender implements IGraphicRender { @@ -35,6 +39,7 @@ export class DefaultCanvasPathRender extends BaseRender implements IGraph protected readonly pathRenderContribitions: IContributionProvider ) { super(); + this.builtinContributions = [defaultPathBackgroundRenderContribution, defaultPathTextureRenderContribution]; this.init(pathRenderContribitions); } diff --git a/packages/vrender-core/src/render/contributions/render/polygon-render.ts b/packages/vrender-core/src/render/contributions/render/polygon-render.ts index de1a9a4a9..2f7094a02 100644 --- a/packages/vrender-core/src/render/contributions/render/polygon-render.ts +++ b/packages/vrender-core/src/render/contributions/render/polygon-render.ts @@ -22,6 +22,10 @@ import { PolygonRenderContribution } from './contributions/constants'; import { ContributionProvider } from '../../../common/contribution-provider'; import { BaseRenderContributionTime } from '../../../common/enums'; import { BaseRender } from './base-render'; +import { + defaultPolygonBackgroundRenderContribution, + defaultPolygonTextureRenderContribution +} from './contributions/polygon-contribution-render'; @injectable() export class DefaultCanvasPolygonRender extends BaseRender implements IGraphicRender { @@ -34,6 +38,7 @@ export class DefaultCanvasPolygonRender extends BaseRender implements protected readonly polygonRenderContribitions: IContributionProvider ) { super(); + this.builtinContributions = [defaultPolygonBackgroundRenderContribution, defaultPolygonTextureRenderContribution]; this.init(polygonRenderContribitions); } diff --git a/packages/vrender-core/src/render/contributions/render/rect-render.ts b/packages/vrender-core/src/render/contributions/render/rect-render.ts index 41b42a57e..5d44eed75 100644 --- a/packages/vrender-core/src/render/contributions/render/rect-render.ts +++ b/packages/vrender-core/src/render/contributions/render/rect-render.ts @@ -21,6 +21,13 @@ import type { import { RectRenderContribution } from './contributions/constants'; import { rectFillVisible, rectStrokeVisible, runFill, runStroke } from './utils'; import { BaseRender } from './base-render'; +import { + defaultRectBackgroundRenderContribution, + defaultRectRenderContribution, + defaultRectTextureRenderContribution, + splitRectAfterRenderContribution, + splitRectBeforeRenderContribution +} from './contributions'; @injectable() export class DefaultCanvasRectRender extends BaseRender implements IGraphicRender { @@ -33,6 +40,13 @@ export class DefaultCanvasRectRender extends BaseRender implements IGraph protected readonly rectRenderContribitions: IContributionProvider ) { super(); + this.builtinContributions = [ + defaultRectRenderContribution, + defaultRectBackgroundRenderContribution, + defaultRectTextureRenderContribution, + splitRectAfterRenderContribution, + splitRectBeforeRenderContribution + ]; this.init(rectRenderContribitions); } diff --git a/packages/vrender-core/src/render/contributions/render/render-slector.ts b/packages/vrender-core/src/render/contributions/render/render-slector.ts index 55cfe21d8..b46d8c7c0 100644 --- a/packages/vrender-core/src/render/contributions/render/render-slector.ts +++ b/packages/vrender-core/src/render/contributions/render/render-slector.ts @@ -1,9 +1,9 @@ -import { injectable } from '../../../common/inversify-lite'; -import type { IGraphic, IGraphicRender, IRenderSelector } from '../../../interface'; +// import { injectable } from '../../../common/inversify-lite'; +// import type { IGraphic, IGraphicRender, IRenderSelector } from '../../../interface'; -@injectable() -export abstract class DefaultRenderSelector implements IRenderSelector { - selector(graphic: IGraphic): IGraphicRender | null { - return null; - } -} +// @injectable() +// export class DefaultRenderSelector implements IRenderSelector { +// selector(graphic: IGraphic): IGraphicRender | null { +// return null; +// } +// } diff --git a/packages/vrender-core/src/render/contributions/render/symbol-render.ts b/packages/vrender-core/src/render/contributions/render/symbol-render.ts index 7c71c9eba..169634ec2 100644 --- a/packages/vrender-core/src/render/contributions/render/symbol-render.ts +++ b/packages/vrender-core/src/render/contributions/render/symbol-render.ts @@ -22,6 +22,11 @@ import { BaseRender } from './base-render'; import { BaseRenderContributionTime } from '../../../common/enums'; import { SymbolRenderContribution } from './contributions/constants'; import { drawPathProxy, fillVisible, runFill, runStroke, strokeVisible } from './utils'; +import { + defaultSymbolBackgroundRenderContribution, + defaultSymbolRenderContribution, + defaultSymbolTextureRenderContribution +} from './contributions'; @injectable() export class DefaultCanvasSymbolRender extends BaseRender implements IGraphicRender { @@ -34,6 +39,11 @@ export class DefaultCanvasSymbolRender extends BaseRender implements IG protected readonly symbolRenderContribitions: IContributionProvider ) { super(); + this.builtinContributions = [ + defaultSymbolRenderContribution, + defaultSymbolBackgroundRenderContribution, + defaultSymbolTextureRenderContribution + ]; this.init(symbolRenderContribitions); } diff --git a/packages/vrender-core/src/render/render-modules.ts b/packages/vrender-core/src/render/render-modules.ts index fa596c117..f761487b3 100644 --- a/packages/vrender-core/src/render/render-modules.ts +++ b/packages/vrender-core/src/render/render-modules.ts @@ -2,6 +2,5 @@ import { ContainerModule } from '../common/inversify-lite'; import { DefaultRenderService, RenderService } from './render-service'; export default new ContainerModule(bind => { - bind(DefaultRenderService).toSelf(); - bind(RenderService).toService(DefaultRenderService); + bind(RenderService).to(DefaultRenderService).inSingletonScope(); }); diff --git a/packages/vrender-kits/src/canvas/contributions/browser/canvas.ts b/packages/vrender-kits/src/canvas/contributions/browser/canvas.ts index 09338c895..74dc91f00 100644 --- a/packages/vrender-kits/src/canvas/contributions/browser/canvas.ts +++ b/packages/vrender-kits/src/canvas/contributions/browser/canvas.ts @@ -40,9 +40,9 @@ export class BrowserCanvas extends BaseCanvas implements ICanvas { if (!isOffscreen) { this.setCanvasStyle(nativeCanvas, this._x, this._y, this._displayWidth, this._displayHeight); } - if (this.id != null) { - nativeCanvas.id = this.id.toString(); - } + // if (this.id != null) { + // nativeCanvas.id = this.id.toString(); + // } if (this._container) { this._container.appendChild(nativeCanvas); } @@ -95,10 +95,10 @@ export class BrowserCanvas extends BaseCanvas implements ICanvas { if (!this.controled) { return; } - canvas.style.padding = '0'; - canvas.style.margin = '0'; - canvas.style.border = '0'; - canvas.style.background = 'transparent'; + // canvas.style.padding = '0'; + // canvas.style.margin = '0'; + // canvas.style.border = '0'; + // canvas.style.background = 'transparent'; // canvas.style.position = 'absolute'; // canvas.style.top = `${y}px`; // canvas.style.left = `${x}px`; diff --git a/packages/vrender-kits/src/picker/canvas-picker-service.ts b/packages/vrender-kits/src/picker/canvas-picker-service.ts index 24ab64bb0..2df868043 100644 --- a/packages/vrender-kits/src/picker/canvas-picker-service.ts +++ b/packages/vrender-kits/src/picker/canvas-picker-service.ts @@ -9,8 +9,8 @@ import { DefaultPickService, DrawContribution, PickItemInterceptor, - VGlobal, - canvasAllocate + canvasAllocate, + application } from '@visactor/vrender-core'; import type { ICanvas, @@ -55,27 +55,15 @@ export class DefaultCanvasPickerService extends DefaultPickService implements IP @inject(ContributionProvider) @named(CanvasPickerContribution) protected readonly contributions: IContributionProvider, - @inject(CanvasCirclePicker) private readonly circlePicker: IGraphicPicker, // 默认的circlePicker - @inject(CanvasRectPicker) private readonly rectPicker: IGraphicPicker, // 默认的rectPicker - @inject(CanvasArcPicker) private readonly arcPicker: IGraphicPicker, // 默认的arcPicker - @inject(CanvasAreaPicker) private readonly areaPicker: IGraphicPicker, // 默认的areaPicker - @inject(CanvasImagePicker) private readonly imagePicker: IGraphicPicker, // 默认的imagePicker - @inject(CanvasLinePicker) private readonly linePicker: IGraphicPicker, // 默认的linePicker - @inject(CanvasPathPicker) private readonly pathPicker: IGraphicPicker, // 默认的pathPicker - @inject(CanvasSymbolPicker) private readonly symbolPicker: IGraphicPicker, // 默认的symbolPicker - @inject(CanvasTextPicker) private readonly textPicker: IGraphicPicker, // 默认的textPicker - @inject(CanvasPolygonPicker) private readonly polygonPicker: IGraphicPicker, // 默认的polygonPicker - @inject(CanvasRichTextPicker) private readonly richtextPicker: IGraphicPicker, // 默认的richtextPicker @inject(DrawContribution) public readonly drawContribution: IDrawContribution, - @inject(VGlobal) public readonly global: IGlobal, // 拦截器 @inject(ContributionProvider) @named(PickItemInterceptor) protected readonly pickItemInterceptorContributions: IContributionProvider ) { - super(global, pickItemInterceptorContributions); + super(pickItemInterceptorContributions); this.global.hooks.onSetEnv.tap('canvas-picker-service', (_, env, global) => { this.configure(global, env); }); diff --git a/packages/vrender-kits/src/picker/contributions/canvas-picker/module.ts b/packages/vrender-kits/src/picker/contributions/canvas-picker/module.ts index e605b8008..ebdfa75fb 100644 --- a/packages/vrender-kits/src/picker/contributions/canvas-picker/module.ts +++ b/packages/vrender-kits/src/picker/contributions/canvas-picker/module.ts @@ -37,81 +37,65 @@ import { DefaultCanvasGroupPicker } from './group-picker'; export default new ContainerModule((bind, unbind, isBound, rebind) => { // circle picker - bind(DefaultCanvasCirclePicker).toSelf().inSingletonScope(); - bind(CanvasCirclePicker).toService(DefaultCanvasCirclePicker); + bind(CanvasCirclePicker).to(DefaultCanvasCirclePicker).inSingletonScope(); bind(CanvasPickerContribution).toService(CanvasCirclePicker); // reat picker - bind(DefaultCanvasRectPicker).toSelf().inSingletonScope(); - bind(CanvasRectPicker).toService(DefaultCanvasRectPicker); + bind(CanvasRectPicker).to(DefaultCanvasRectPicker).inSingletonScope(); bind(CanvasPickerContribution).toService(CanvasRectPicker); // reat3d picker - bind(DefaultCanvasRect3dPicker).toSelf().inSingletonScope(); - bind(CanvasRect3dPicker).toService(DefaultCanvasRect3dPicker); + bind(CanvasRect3dPicker).to(DefaultCanvasRect3dPicker).inSingletonScope(); bind(CanvasPickerContribution).toService(CanvasRect3dPicker); // arc picker - bind(DefaultCanvasArcPicker).toSelf().inSingletonScope(); - bind(CanvasArcPicker).toService(DefaultCanvasArcPicker); + bind(CanvasArcPicker).to(DefaultCanvasArcPicker).inSingletonScope(); bind(CanvasPickerContribution).toService(CanvasArcPicker); // area picker - bind(DefaultCanvasAreaPicker).toSelf().inSingletonScope(); - bind(CanvasAreaPicker).toService(DefaultCanvasAreaPicker); + bind(CanvasAreaPicker).to(DefaultCanvasAreaPicker).inSingletonScope(); bind(CanvasPickerContribution).toService(CanvasAreaPicker); // image picker - bind(DefaultCanvasImagePicker).toSelf().inSingletonScope(); - bind(CanvasImagePicker).toService(DefaultCanvasImagePicker); + bind(CanvasImagePicker).to(DefaultCanvasImagePicker).inSingletonScope(); bind(CanvasPickerContribution).toService(CanvasImagePicker); // line picker - bind(DefaultCanvasLinePicker).toSelf().inSingletonScope(); - bind(CanvasLinePicker).toService(DefaultCanvasLinePicker); + bind(CanvasLinePicker).to(DefaultCanvasLinePicker).inSingletonScope(); bind(CanvasPickerContribution).toService(CanvasLinePicker); // path picker - bind(DefaultCanvasPathPicker).toSelf().inSingletonScope(); - bind(CanvasPathPicker).toService(DefaultCanvasPathPicker); + bind(CanvasPathPicker).to(DefaultCanvasPathPicker).inSingletonScope(); bind(CanvasPickerContribution).toService(CanvasPathPicker); // symbol picker - bind(DefaultCanvasSymbolPicker).toSelf().inSingletonScope(); - bind(CanvasSymbolPicker).toService(DefaultCanvasSymbolPicker); + bind(CanvasSymbolPicker).to(DefaultCanvasSymbolPicker).inSingletonScope(); bind(CanvasPickerContribution).toService(CanvasSymbolPicker); // text picker - bind(DefaultCanvasTextPicker).toSelf().inSingletonScope(); - bind(CanvasTextPicker).toService(DefaultCanvasTextPicker); + bind(CanvasTextPicker).to(DefaultCanvasTextPicker).inSingletonScope(); bind(CanvasPickerContribution).toService(CanvasTextPicker); // polygon picker - bind(DefaultCanvasPolygonPicker).toSelf().inSingletonScope(); - bind(CanvasPolygonPicker).toService(DefaultCanvasPolygonPicker); + bind(CanvasPolygonPicker).to(DefaultCanvasPolygonPicker).inSingletonScope(); bind(CanvasPickerContribution).toService(CanvasPolygonPicker); // pyramid3d picker - bind(DefaultCanvasPyramid3dPicker).toSelf().inSingletonScope(); - bind(CanvasPyramid3dPicker).toService(DefaultCanvasPyramid3dPicker); + bind(CanvasPyramid3dPicker).to(DefaultCanvasPyramid3dPicker).inSingletonScope(); bind(CanvasPickerContribution).toService(CanvasPyramid3dPicker); // arc3d picker - bind(DefaultCanvasArc3dPicker).toSelf().inSingletonScope(); - bind(CanvasArc3dPicker).toService(DefaultCanvasArc3dPicker); + bind(CanvasArc3dPicker).to(DefaultCanvasArc3dPicker).inSingletonScope(); bind(CanvasPickerContribution).toService(CanvasArc3dPicker); // richtext picker - bind(DefaultCanvasRichTextPicker).toSelf().inSingletonScope(); - bind(CanvasRichTextPicker).toService(DefaultCanvasRichTextPicker); + bind(CanvasRichTextPicker).to(DefaultCanvasRichTextPicker).inSingletonScope(); bind(CanvasPickerContribution).toService(CanvasRichTextPicker); // glyph picker - bind(DefaultCanvasGlyphPicker).toSelf().inSingletonScope(); - bind(CanvasGlyphPicker).toService(DefaultCanvasGlyphPicker); + bind(CanvasGlyphPicker).to(DefaultCanvasGlyphPicker).inSingletonScope(); bind(CanvasPickerContribution).toService(CanvasGlyphPicker); // group picker - bind(DefaultCanvasGroupPicker).toSelf().inSingletonScope(); - bind(CanvasGroupPicker).toService(DefaultCanvasGroupPicker); + bind(CanvasGroupPicker).to(DefaultCanvasGroupPicker).inSingletonScope(); bind(CanvasPickerContribution).toService(CanvasGroupPicker); bindContributionProvider(bind, CanvasPickerContribution); diff --git a/packages/vrender-kits/src/picker/contributions/math-picker/module.ts b/packages/vrender-kits/src/picker/contributions/math-picker/module.ts index b4c47de20..9134ee680 100644 --- a/packages/vrender-kits/src/picker/contributions/math-picker/module.ts +++ b/packages/vrender-kits/src/picker/contributions/math-picker/module.ts @@ -25,23 +25,19 @@ import { DefaultMathGlyphPicker } from './glyph-picker'; export default new ContainerModule(bind => { // circle picker - bind(DefaultMathCirclePicker).toSelf().inSingletonScope(); - bind(MathCirclePicker).toService(DefaultMathCirclePicker); + bind(MathCirclePicker).to(DefaultMathCirclePicker).inSingletonScope(); bind(MathPickerContribution).toService(MathCirclePicker); // rect picker - bind(DefaultMathRectPicker).toSelf().inSingletonScope(); - bind(MathRectPicker).toService(DefaultMathRectPicker); + bind(MathRectPicker).to(DefaultMathRectPicker).inSingletonScope(); bind(MathPickerContribution).toService(MathRectPicker); // arc picker - bind(DefaultMathArcPicker).toSelf().inSingletonScope(); - bind(MathArcPicker).toService(DefaultMathArcPicker); + bind(MathArcPicker).to(DefaultMathArcPicker).inSingletonScope(); bind(MathPickerContribution).toService(MathArcPicker); // area picker - bind(DefaultMathAreaPicker).toSelf().inSingletonScope(); - bind(MathAreaPicker).toService(DefaultMathAreaPicker); + bind(MathAreaPicker).to(DefaultMathAreaPicker).inSingletonScope(); bind(MathPickerContribution).toService(MathAreaPicker); // // image picker @@ -50,33 +46,27 @@ export default new ContainerModule(bind => { // bind(PickerContribution).toService(ImagePicker); // line picker - bind(DefaultMathLinePicker).toSelf().inSingletonScope(); - bind(MathLinePicker).toService(DefaultMathLinePicker); + bind(MathLinePicker).to(DefaultMathLinePicker).inSingletonScope(); bind(MathPickerContribution).toService(MathLinePicker); // path picker - bind(DefaultMathPathPicker).toSelf().inSingletonScope(); - bind(MathPathPicker).toService(DefaultMathPathPicker); + bind(MathPathPicker).to(DefaultMathPathPicker).inSingletonScope(); bind(MathPickerContribution).toService(MathPathPicker); // symbol picker - bind(DefaultMathSymbolPicker).toSelf().inSingletonScope(); - bind(MathSymbolPicker).toService(DefaultMathSymbolPicker); + bind(MathSymbolPicker).to(DefaultMathSymbolPicker).inSingletonScope(); bind(MathPickerContribution).toService(MathSymbolPicker); // text picker - bind(DefaultMathTextPicker).toSelf().inSingletonScope(); - bind(MathTextPicker).toService(DefaultMathTextPicker); + bind(MathTextPicker).to(DefaultMathTextPicker).inSingletonScope(); bind(MathPickerContribution).toService(MathTextPicker); // polygon picker - bind(DefaultMathPolygonPicker).toSelf().inSingletonScope(); - bind(MathPolygonPicker).toService(DefaultMathPolygonPicker); + bind(MathPolygonPicker).to(DefaultMathPolygonPicker).inSingletonScope(); bind(MathPickerContribution).toService(MathPolygonPicker); // glyph picker - bind(DefaultMathGlyphPicker).toSelf().inSingletonScope(); - bind(MathGlyphPicker).toService(DefaultMathGlyphPicker); + bind(MathGlyphPicker).to(DefaultMathGlyphPicker).inSingletonScope(); bind(DefaultMathGlyphPicker).toService(MathGlyphPicker); bindContributionProvider(bind, MathPickerContribution); diff --git a/packages/vrender-kits/src/picker/math-picker-service.ts b/packages/vrender-kits/src/picker/math-picker-service.ts index 67a7fd6c7..0d2599437 100644 --- a/packages/vrender-kits/src/picker/math-picker-service.ts +++ b/packages/vrender-kits/src/picker/math-picker-service.ts @@ -8,7 +8,6 @@ import { postConstruct, DefaultPickService, EmptyContext2d, - VGlobal, PickItemInterceptor } from '@visactor/vrender-core'; import type { @@ -40,13 +39,12 @@ export class DefaultMathPickerService extends DefaultPickService implements IPic @inject(ContributionProvider) @named(MathPickerContribution) protected readonly contributions: IContributionProvider, - @inject(VGlobal) public readonly global: IGlobal, // 拦截器 @inject(ContributionProvider) @named(PickItemInterceptor) protected readonly pickItemInterceptorContributions: IContributionProvider ) { - super(global, pickItemInterceptorContributions); + super(pickItemInterceptorContributions); this.global.hooks.onSetEnv.tap('math-picker-service', (lastEnv, env, global) => { this.configure(global, env); }); diff --git a/packages/vrender-kits/src/window/contributions/browser-contribution.ts b/packages/vrender-kits/src/window/contributions/browser-contribution.ts index 5ef666dc8..b6e6c97a0 100644 --- a/packages/vrender-kits/src/window/contributions/browser-contribution.ts +++ b/packages/vrender-kits/src/window/contributions/browser-contribution.ts @@ -3,9 +3,9 @@ import { injectable, Generator, BaseWindowHandlerContribution, - VGlobal, ContainerModule, - WindowHandlerContribution + WindowHandlerContribution, + application } from '@visactor/vrender-core'; import type { IContext2d, @@ -35,13 +35,16 @@ export class BrowserWindowHandlerContribution protected _canvasIsIntersecting: boolean; protected _onVisibleChangeCb: (currentVisible: boolean) => void; + private readonly global: IGlobal; + get container(): HTMLElement | null { return this.canvas.nativeCanvas.parentElement; } - constructor(@inject(VGlobal) private readonly global: IGlobal) { + constructor() { super(); this._canvasIsIntersecting = true; + this.global = application.global; } getTitle(): string { @@ -73,6 +76,9 @@ export class BrowserWindowHandlerContribution } protected postInit() { + if (!this.global.optimizeVisible) { + return; + } try { this.observerCanvas(); } catch (err) { diff --git a/packages/vrender/__tests__/browser/src/pages/circle.ts b/packages/vrender/__tests__/browser/src/pages/circle.ts index abae445b8..995512748 100644 --- a/packages/vrender/__tests__/browser/src/pages/circle.ts +++ b/packages/vrender/__tests__/browser/src/pages/circle.ts @@ -3,6 +3,13 @@ import { colorPools } from '../utils'; import { createGroup } from '@visactor/vrender'; export const page = () => { + const t = performance.now(); + const stage = createStage({ + canvas: 'main', + autoRender: true + }); + const delta = performance.now() - t; + window.delta = delta; const graphics: IGraphic[] = []; // graphics.push(createCircle({ // radius: 50, @@ -67,11 +74,6 @@ export const page = () => { graphics.push(group); - const stage = createStage({ - canvas: 'main', - autoRender: true - }); - stage.setTheme({ common: { lineWidth: 6 diff --git a/packages/vrender/src/index.ts b/packages/vrender/src/index.ts index 06171cdc5..6b6018ec5 100644 --- a/packages/vrender/src/index.ts +++ b/packages/vrender/src/index.ts @@ -1,10 +1,10 @@ import { container } from '@visactor/vrender-core'; -import { loadAllModule } from '@visactor/vrender-kits'; +import { loadBrowserEnv } from '@visactor/vrender-kits'; // 导出版本号 export const version = __VERSION__; -loadAllModule(container); +loadBrowserEnv(container); export * from '@visactor/vrender-core'; export * from '@visactor/vrender-kits'; From f118c8798a90918f76751c4768093a1178aade9a Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Tue, 7 Nov 2023 12:11:41 +0800 Subject: [PATCH 08/40] feat: optimize some code performance --- packages/vrender-components/src/axis/base.ts | 9 +- packages/vrender-components/src/axis/line.ts | 15 +- packages/vrender-components/src/core/base.ts | 20 +- .../src/allocator/graphic-allocate.ts | 447 ++++++++++-------- .../resolution/instantiation.ts | 16 - packages/vrender-core/src/core/global.ts | 2 +- packages/vrender-core/src/core/stage.ts | 3 +- packages/vrender-core/src/graphic/group.ts | 2 +- packages/vrender-core/src/index.ts | 1 + 9 files changed, 279 insertions(+), 236 deletions(-) diff --git a/packages/vrender-components/src/axis/base.ts b/packages/vrender-components/src/axis/base.ts index 153576608..cf4d08b79 100644 --- a/packages/vrender-components/src/axis/base.ts +++ b/packages/vrender-components/src/axis/base.ts @@ -13,11 +13,12 @@ import type { IGraphic, IText } from '@visactor/vrender-core'; +import { defaultGraphicMemoryManager, defaultTextAllocate } from '@visactor/vrender-core'; // eslint-disable-next-line no-duplicate-imports import { createLine, createText, createGroup } from '@visactor/vrender-core'; import type { Dict } from '@visactor/vutils'; // eslint-disable-next-line no-duplicate-imports -import { abs, cloneDeep, get, isEmpty, isFunction, isNumberClose, merge, pi } from '@visactor/vutils'; +import { AABBBounds, abs, cloneDeep, get, isEmpty, isFunction, isNumberClose, merge, pi } from '@visactor/vutils'; import { AbstractComponent } from '../core/base'; import type { Point } from '../core/type'; import type { TagAttributes } from '../tag'; @@ -111,11 +112,11 @@ export abstract class AxisBase extends AbstractCom x: this.attribute.x, y: this.attribute.y }); - this.add(offscreenGroup); + // this.add(offscreenGroup); this._renderInner(offscreenGroup); - this.removeChild(offscreenGroup); + // this.removeChild(offscreenGroup); this.attribute = currentAttribute; return offscreenGroup.AABBBounds; } @@ -324,7 +325,7 @@ export abstract class AxisBase extends AbstractCom let textBaseline = 'middle'; data.forEach((item: TransformedAxisItem, index: number) => { const labelStyle = this._getLabelAttribute(item, index, data, layer); - const text = createText(labelStyle); + const text = defaultTextAllocate.allocate(labelStyle); text.name = AXIS_ELEMENT_NAME.label; text.id = this._getNodeId(`layer${layer}-label-${item.id}`); if (isEmpty(this.attribute.label?.state)) { diff --git a/packages/vrender-components/src/axis/line.ts b/packages/vrender-components/src/axis/line.ts index 5b31213f8..a8d6b5d62 100644 --- a/packages/vrender-components/src/axis/line.ts +++ b/packages/vrender-components/src/axis/line.ts @@ -13,7 +13,9 @@ import { isValid, normalizePadding, mixin, - last as peek + last as peek, + AABBBounds, + cloneDeep } from '@visactor/vutils'; import type { TextAlignType } from '@visactor/vrender-core'; // eslint-disable-next-line no-duplicate-imports @@ -40,14 +42,25 @@ export interface LineAxis export class LineAxis extends AxisBase { static defaultAttributes = DEFAULT_AXIS_THEME; + // 判定是否是第一次run,第一次不用渲染 + // skipRenderOnce: boolean; constructor(attributes: LineAxisAttributes, mode?: '2d' | '3d') { super(merge({}, LineAxis.defaultAttributes, attributes), mode); if (mode === '3d') { this.setMode(mode); } + // this.skipRenderOnce = true; } + // protected render(): void { + // if (this.skipRenderOnce) { + // this.skipRenderOnce = false; + // return; + // } + // super.render(); + // } + protected _renderInner(container: IGroup) { super._renderInner(container); const { panel } = this.attribute; diff --git a/packages/vrender-components/src/core/base.ts b/packages/vrender-components/src/core/base.ts index b4bab96d6..9bc635f0a 100644 --- a/packages/vrender-components/src/core/base.ts +++ b/packages/vrender-components/src/core/base.ts @@ -40,11 +40,22 @@ export abstract class AbstractComponent { - this.render(); + this.renderOnSetStage() && this.render(); this.bindEvents(); }); } + renderOnSetStage() { + return true; + } + + shouldAttributesUpdate(params: Partial, forceUpdateTag?: boolean | undefined) { + return true; + } + shouldAttributeUpdate(key: keyof T, value: any, forceUpdateTag?: boolean | undefined) { + return true; + } + /** * @override * 更新单个属性值 @@ -62,7 +73,7 @@ export abstract class AbstractComponent GROUP_ATTRIBUTES.includes(key as string))) { + if ( + this.shouldAttributesUpdate(params, forceUpdateTag) && + !keys.every(key => GROUP_ATTRIBUTES.includes(key as string)) + ) { this.render(); } diff --git a/packages/vrender-core/src/allocator/graphic-allocate.ts b/packages/vrender-core/src/allocator/graphic-allocate.ts index 35c6d2b86..8f4338d64 100644 --- a/packages/vrender-core/src/allocator/graphic-allocate.ts +++ b/packages/vrender-core/src/allocator/graphic-allocate.ts @@ -1,209 +1,238 @@ -// // import { IMatrix, IMatrixLike, Matrix } from '@visactor/vutils'; -// import { IAllocate } from './interface'; -// import { -// IArc, -// IArcGraphicAttribute, -// IArea, -// IAreaGraphicAttribute, -// ICircle, -// ICircleGraphicAttribute, -// IGraphic, -// ILine, -// ILineGraphicAttribute, -// IPath, -// IPathGraphicAttribute, -// IRect, -// IRectGraphicAttribute, -// ISymbol, -// ISymbolGraphicAttribute, -// IText, -// ITextGraphicAttribute, -// Releaseable -// } from '../interface'; -// import { application } from '../application'; - -// @injectable() -// export abstract class DefaultGraphicAllocate -// implements IAllocate, Releaseable -// { -// protected pools: T[] = []; -// abstract allocate(attribute: IGraphicAttribute): T; -// abstract allocateByObj(g: T): T; -// free(d: T) { -// this.pools.push(d); -// } -// get length(): number { -// return this.pools.length; -// } -// release(...params: any): void { -// this.pools = []; -// } -// } - -// @injectable() -// export class DefaultRectAllocate extends DefaultGraphicAllocate { -// allocate(attribute: IRectGraphicAttribute): IRect { -// if (!this.pools.length) { -// return application.graphicService.creator.rect(attribute); -// } -// const g = this.pools.pop(); -// g.initAttributes(attribute); -// return g; -// } - -// allocateByObj(rect: IRect): IRect { -// if (!this.pools.length) { -// return application.graphicService.creator.rect(rect.attribute); -// } -// const g = this.pools.pop(); -// g.initAttributes(rect.attribute); -// return g; -// } -// } - -// @injectable() -// export class DefaultArcAllocate extends DefaultGraphicAllocate { -// allocate(attribute: IArcGraphicAttribute): IArc { -// if (!this.pools.length) { -// return application.graphicService.creator.arc(attribute); -// } -// const g = this.pools.pop(); -// g.initAttributes(attribute); -// return g; -// } - -// allocateByObj(arc: IArc): IArc { -// if (!this.pools.length) { -// return application.graphicService.creator.arc(arc.attribute); -// } -// const g = this.pools.pop(); -// g.initAttributes(arc.attribute); -// return g; -// } -// } - -// @injectable() -// export class DefaultAreaAllocate extends DefaultGraphicAllocate { -// allocate(attribute: IAreaGraphicAttribute): IArea { -// if (!this.pools.length) { -// return application.graphicService.creator.area(attribute); -// } -// const g = this.pools.pop(); -// g.initAttributes(attribute); -// return g; -// } - -// allocateByObj(area: IArea): IArea { -// if (!this.pools.length) { -// return application.graphicService.creator.area(area.attribute); -// } -// const g = this.pools.pop(); -// g.initAttributes(area.attribute); -// return g; -// } -// } - -// @injectable() -// export class DefaultCircleAllocate extends DefaultGraphicAllocate { -// allocate(attribute: ICircleGraphicAttribute): ICircle { -// if (!this.pools.length) { -// return application.graphicService.creator.circle(attribute); -// } -// const g = this.pools.pop(); -// g.initAttributes(attribute); -// return g; -// } - -// allocateByObj(area: ICircle): ICircle { -// if (!this.pools.length) { -// return application.graphicService.creator.circle(area.attribute); -// } -// const g = this.pools.pop(); -// g.initAttributes(area.attribute); -// return g; -// } -// } - -// @injectable() -// export class DefaultLineAllocate extends DefaultGraphicAllocate { -// allocate(attribute: ILineGraphicAttribute): ILine { -// if (!this.pools.length) { -// return application.graphicService.creator.line(attribute); -// } -// const g = this.pools.pop(); -// g.initAttributes(attribute); -// return g; -// } - -// allocateByObj(line: ILine): ILine { -// if (!this.pools.length) { -// return application.graphicService.creator.line(line.attribute); -// } -// const g = this.pools.pop(); -// g.initAttributes(line.attribute); -// return g; -// } -// } - -// @injectable() -// export class DefaultPathAllocate extends DefaultGraphicAllocate { -// allocate(attribute: IPathGraphicAttribute): IPath { -// if (!this.pools.length) { -// return application.graphicService.creator.path(attribute); -// } -// const g = this.pools.pop(); -// g.initAttributes(attribute); -// return g; -// } - -// allocateByObj(path: IPath): IPath { -// if (!this.pools.length) { -// return application.graphicService.creator.path(path.attribute); -// } -// const g = this.pools.pop(); -// g.initAttributes(path.attribute); -// return g; -// } -// } - -// @injectable() -// export class DefaultSymbolAllocate extends DefaultGraphicAllocate { -// allocate(attribute: ISymbolGraphicAttribute): ISymbol { -// if (!this.pools.length) { -// return application.graphicService.creator.symbol(attribute); -// } -// const g = this.pools.pop(); -// g.initAttributes(attribute); -// return g; -// } - -// allocateByObj(symbol: ISymbol): ISymbol { -// if (!this.pools.length) { -// return application.graphicService.creator.symbol(symbol.attribute); -// } -// const g = this.pools.pop(); -// g.initAttributes(symbol.attribute); -// return g; -// } -// } - -// @injectable() -// export class DefaultTextAllocate extends DefaultGraphicAllocate { -// allocate(attribute: ITextGraphicAttribute): IText { -// if (!this.pools.length) { -// return application.graphicService.creator.text(attribute); -// } -// const g = this.pools.pop(); -// g.initAttributes(attribute); -// return g; -// } - -// allocateByObj(text: IText): IText { -// if (!this.pools.length) { -// return application.graphicService.creator.text(text.attribute); -// } -// const g = this.pools.pop(); -// g.initAttributes(text.attribute); -// return g; -// } -// } +// import { IMatrix, IMatrixLike, Matrix } from '@visactor/vutils'; +import type { IAllocate } from '../interface'; +import type { + IArc, + IArcGraphicAttribute, + IArea, + IAreaGraphicAttribute, + ICircle, + ICircleGraphicAttribute, + IGraphic, + ILine, + ILineGraphicAttribute, + IPath, + IPathGraphicAttribute, + IRect, + IRectGraphicAttribute, + ISymbol, + ISymbolGraphicAttribute, + IText, + ITextGraphicAttribute, + Releaseable +} from '../interface'; +import { application } from '../application'; + +export abstract class DefaultGraphicAllocate + implements IAllocate, Releaseable +{ + protected pools: T[] = []; + abstract allocate(attribute: IGraphicAttribute): T; + abstract allocateByObj(g: T): T; + free(d: T) { + this.pools.push(d); + } + get length(): number { + return this.pools.length; + } + release(...params: any): void { + this.pools = []; + } +} + +export class DefaultRectAllocate extends DefaultGraphicAllocate { + allocate(attribute: IRectGraphicAttribute): IRect { + if (!this.pools.length) { + return application.graphicService.creator.rect(attribute); + } + const g = this.pools.pop(); + g.initAttributes(attribute); + return g; + } + + allocateByObj(rect: IRect): IRect { + if (!this.pools.length) { + return application.graphicService.creator.rect(rect.attribute); + } + const g = this.pools.pop(); + g.initAttributes(rect.attribute); + return g; + } +} +export const defaultRectAllocate = new DefaultRectAllocate(); + +export class DefaultArcAllocate extends DefaultGraphicAllocate { + allocate(attribute: IArcGraphicAttribute): IArc { + if (!this.pools.length) { + return application.graphicService.creator.arc(attribute); + } + const g = this.pools.pop(); + g.initAttributes(attribute); + return g; + } + + allocateByObj(arc: IArc): IArc { + if (!this.pools.length) { + return application.graphicService.creator.arc(arc.attribute); + } + const g = this.pools.pop(); + g.initAttributes(arc.attribute); + return g; + } +} + +export const defaultArcAllocate = new DefaultArcAllocate(); + +export class DefaultAreaAllocate extends DefaultGraphicAllocate { + allocate(attribute: IAreaGraphicAttribute): IArea { + if (!this.pools.length) { + return application.graphicService.creator.area(attribute); + } + const g = this.pools.pop(); + g.initAttributes(attribute); + return g; + } + + allocateByObj(area: IArea): IArea { + if (!this.pools.length) { + return application.graphicService.creator.area(area.attribute); + } + const g = this.pools.pop(); + g.initAttributes(area.attribute); + return g; + } +} + +export const defaultAreaAllocate = new DefaultAreaAllocate(); + +export class DefaultCircleAllocate extends DefaultGraphicAllocate { + allocate(attribute: ICircleGraphicAttribute): ICircle { + if (!this.pools.length) { + return application.graphicService.creator.circle(attribute); + } + const g = this.pools.pop(); + g.initAttributes(attribute); + return g; + } + + allocateByObj(area: ICircle): ICircle { + if (!this.pools.length) { + return application.graphicService.creator.circle(area.attribute); + } + const g = this.pools.pop(); + g.initAttributes(area.attribute); + return g; + } +} + +export const defaultCircleAllocate = new DefaultCircleAllocate(); + +export class DefaultLineAllocate extends DefaultGraphicAllocate { + allocate(attribute: ILineGraphicAttribute): ILine { + if (!this.pools.length) { + return application.graphicService.creator.line(attribute); + } + const g = this.pools.pop(); + g.initAttributes(attribute); + return g; + } + + allocateByObj(line: ILine): ILine { + if (!this.pools.length) { + return application.graphicService.creator.line(line.attribute); + } + const g = this.pools.pop(); + g.initAttributes(line.attribute); + return g; + } +} + +export const defaultLineAllocate = new DefaultLineAllocate(); + +export class DefaultPathAllocate extends DefaultGraphicAllocate { + allocate(attribute: IPathGraphicAttribute): IPath { + if (!this.pools.length) { + return application.graphicService.creator.path(attribute); + } + const g = this.pools.pop(); + g.initAttributes(attribute); + return g; + } + + allocateByObj(path: IPath): IPath { + if (!this.pools.length) { + return application.graphicService.creator.path(path.attribute); + } + const g = this.pools.pop(); + g.initAttributes(path.attribute); + return g; + } +} + +export const defaultPathAllocate = new DefaultPathAllocate(); + +export class DefaultSymbolAllocate extends DefaultGraphicAllocate { + allocate(attribute: ISymbolGraphicAttribute): ISymbol { + if (!this.pools.length) { + return application.graphicService.creator.symbol(attribute); + } + const g = this.pools.pop(); + g.initAttributes(attribute); + return g; + } + + allocateByObj(symbol: ISymbol): ISymbol { + if (!this.pools.length) { + return application.graphicService.creator.symbol(symbol.attribute); + } + const g = this.pools.pop(); + g.initAttributes(symbol.attribute); + return g; + } +} + +export const defaultSymbolAllocate = new DefaultSymbolAllocate(); + +export class DefaultTextAllocate extends DefaultGraphicAllocate { + allocate(attribute: ITextGraphicAttribute): IText { + if (!this.pools.length) { + return application.graphicService.creator.text(attribute); + } + const g = this.pools.pop(); + g.initAttributes(attribute); + return g; + } + + allocateByObj(text: IText): IText { + if (!this.pools.length) { + return application.graphicService.creator.text(text.attribute); + } + const g = this.pools.pop(); + g.initAttributes(text.attribute); + return g; + } +} + +export const defaultTextAllocate = new DefaultTextAllocate(); + +export class DefaultGraphicMemoryManager { + map: Record> = { + text: defaultTextAllocate, + symbol: defaultSymbolAllocate + }; + gc(g: IGraphic) { + if (g.isContainer) { + g.forEachChildren(i => this.gc(i as any)); + } else { + this.gcItem(g); + } + } + + gcItem(g: IGraphic) { + const allocate = this.map[g.type]; + if (allocate) { + allocate.free(g); + } + } +} + +export const defaultGraphicMemoryManager = new DefaultGraphicMemoryManager(); diff --git a/packages/vrender-core/src/common/inversify-lite/resolution/instantiation.ts b/packages/vrender-core/src/common/inversify-lite/resolution/instantiation.ts index 54c217d9c..1d9375fc2 100644 --- a/packages/vrender-core/src/common/inversify-lite/resolution/instantiation.ts +++ b/packages/vrender-core/src/common/inversify-lite/resolution/instantiation.ts @@ -59,30 +59,14 @@ function _createInstance( result = createInstanceWithInjections(createInstanceWithInjectionsArg); } } else { - if (!(window as any).constr) { - (window as any).constr = 0; - (window as any).map = new Map(); - } - const t = performance.now(); result = new constr(); - const delta = performance.now() - t; - (window as any).map.set(result, delta); - (window as any).constr += delta; } return result; } function createInstanceWithInjections(args: CreateInstanceWithInjectionArg): T { - if (!(window as any).constr) { - (window as any).constr = 0; - (window as any).map = new Map(); - } - const t = performance.now(); const instance = new args.constr(...args.constructorInjections); - const delta = performance.now() - t; - (window as any).map.set(instance, delta); - (window as any).constr += delta; args.propertyRequests.forEach((r: interfaces.Request, index: number) => { const property = r.target.identifier; const injection = args.propertyInjections[index]; diff --git a/packages/vrender-core/src/core/global.ts b/packages/vrender-core/src/core/global.ts index d0cb960ec..ef004f96d 100644 --- a/packages/vrender-core/src/core/global.ts +++ b/packages/vrender-core/src/core/global.ts @@ -124,7 +124,7 @@ export class DefaultGlobal implements IGlobal { this.hooks = { onSetEnv: new SyncHook<[EnvType | undefined, EnvType, IGlobal]>(['lastEnv', 'env', 'global']) }; - this.measureTextMethod = 'native'; + this.measureTextMethod = 'quick'; this.optimizeVisible = false; } diff --git a/packages/vrender-core/src/core/stage.ts b/packages/vrender-core/src/core/stage.ts index c59dcb7a5..1c197c3b6 100644 --- a/packages/vrender-core/src/core/stage.ts +++ b/packages/vrender-core/src/core/stage.ts @@ -476,8 +476,9 @@ export class Stage extends Group implements IStage { if (!plugin) { plugin = new DirtyBoundsPlugin(); this.pluginService.register(plugin); + } else { + plugin.activate(this.pluginService); } - plugin.activate(this.pluginService); } disableDirtyBounds() { if (!this.dirtyBounds) { diff --git a/packages/vrender-core/src/graphic/group.ts b/packages/vrender-core/src/graphic/group.ts index 410a66734..8741b7d24 100644 --- a/packages/vrender-core/src/graphic/group.ts +++ b/packages/vrender-core/src/graphic/group.ts @@ -181,7 +181,7 @@ export class Group extends Graphic implements IGroup { this._AABBBounds.setValue(Infinity, Infinity, -Infinity, -Infinity); const bounds = application.graphicService.updateGroupAABBBounds( attribute, - getTheme(this).group, + groupTheme, this._AABBBounds, this ) as AABBBounds; diff --git a/packages/vrender-core/src/index.ts b/packages/vrender-core/src/index.ts index db078cefd..ad4075f2d 100644 --- a/packages/vrender-core/src/index.ts +++ b/packages/vrender-core/src/index.ts @@ -44,6 +44,7 @@ export * from './common/generator'; export * from './plugins/constants'; export * from './allocator/matrix-allocate'; export * from './allocator/canvas-allocate'; +export * from './allocator/graphic-allocate'; export * from './animate/default-ticker'; export { wrapCanvas, wrapContext } from './canvas/util'; From 0f0fe484a9456c51ee1f13cd71d5d7bdb02e2213 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Tue, 7 Nov 2023 14:42:08 +0800 Subject: [PATCH 09/40] fix: set default measureTextMethod to native --- packages/vrender-core/src/core/global.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vrender-core/src/core/global.ts b/packages/vrender-core/src/core/global.ts index ef004f96d..d0cb960ec 100644 --- a/packages/vrender-core/src/core/global.ts +++ b/packages/vrender-core/src/core/global.ts @@ -124,7 +124,7 @@ export class DefaultGlobal implements IGlobal { this.hooks = { onSetEnv: new SyncHook<[EnvType | undefined, EnvType, IGlobal]>(['lastEnv', 'env', 'global']) }; - this.measureTextMethod = 'quick'; + this.measureTextMethod = 'native'; this.optimizeVisible = false; } From 43a4842c426ed56b7fa20c26d30533de9fec7005 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Tue, 7 Nov 2023 14:56:23 +0800 Subject: [PATCH 10/40] fix: fix theme issue with Object.assign --- .../__tests__/browser/examples/checkbox.ts | 50 +++++++++++++++---- .../resolution/instantiation.ts | 16 ------ .../canvas/contributions/browser/context.ts | 24 ++++++--- 3 files changed, 59 insertions(+), 31 deletions(-) diff --git a/packages/vrender-components/__tests__/browser/examples/checkbox.ts b/packages/vrender-components/__tests__/browser/examples/checkbox.ts index 56810c0e4..97838785d 100644 --- a/packages/vrender-components/__tests__/browser/examples/checkbox.ts +++ b/packages/vrender-components/__tests__/browser/examples/checkbox.ts @@ -2,17 +2,49 @@ import '@visactor/vrender'; import { IPointLike } from '@visactor/vutils'; import render from '../../util/render'; import { CheckBox } from '../../../src'; +import { createLine } from '@visactor/vrender-core'; export function run() { - const checkbox = new CheckBox({ - x: 100, - y: 100, - text: { - text: 'checkbox' - }, - checked: false, - disabled: true + // const checkbox = new CheckBox({ + // x: 100, + // y: 100, + // text: { + // text: 'checkbox' + // }, + // checked: false, + // disabled: true + // }); + + const l = createLine({ + segments: [ + { + visible: true, + lineWidth: 1, + lineDash: [1, 0], + stroke: '#468DFF', + points: [ + { x: 5.776942533605235, y: 239.21, context: 0 }, + { x: 13.47953257841222, y: 377.70000000000005, context: 1 }, + { x: 21.182122623219207, y: 283.27500000000003, context: 2 }, + { x: 28.884712668026193, y: 270.68500000000006, context: 3 }, + { x: 36.58730271283318, y: 251.8, context: 4 }, + { x: 44.28989275764016, y: 207.73499999999999, context: 5 }, + { x: 51.99248280244715, y: 176.25999999999993, context: 6 }, + { x: 59.69507284725414, y: 107.01500000000003, context: 7 } + ] + }, + { + visible: true, + lineWidth: 1, + lineDash: [4, 4], + stroke: '#468DFF', + points: [{ x: 59.69507284725414, y: 107.01500000000003, context: 7 }] + } + ], + stroke: true, + points: null, + pickable: true }); - const stage = render([checkbox], 'main'); + const stage = render([l], 'main'); } diff --git a/packages/vrender-core/src/common/inversify-lite/resolution/instantiation.ts b/packages/vrender-core/src/common/inversify-lite/resolution/instantiation.ts index 54c217d9c..1d9375fc2 100644 --- a/packages/vrender-core/src/common/inversify-lite/resolution/instantiation.ts +++ b/packages/vrender-core/src/common/inversify-lite/resolution/instantiation.ts @@ -59,30 +59,14 @@ function _createInstance( result = createInstanceWithInjections(createInstanceWithInjectionsArg); } } else { - if (!(window as any).constr) { - (window as any).constr = 0; - (window as any).map = new Map(); - } - const t = performance.now(); result = new constr(); - const delta = performance.now() - t; - (window as any).map.set(result, delta); - (window as any).constr += delta; } return result; } function createInstanceWithInjections(args: CreateInstanceWithInjectionArg): T { - if (!(window as any).constr) { - (window as any).constr = 0; - (window as any).map = new Map(); - } - const t = performance.now(); const instance = new args.constr(...args.constructorInjections); - const delta = performance.now() - t; - (window as any).map.set(instance, delta); - (window as any).constr += delta; args.propertyRequests.forEach((r: interfaces.Request, index: number) => { const property = r.target.identifier; const injection = args.propertyInjections[index]; diff --git a/packages/vrender-kits/src/canvas/contributions/browser/context.ts b/packages/vrender-kits/src/canvas/contributions/browser/context.ts index 3d118d181..8c343c09e 100644 --- a/packages/vrender-kits/src/canvas/contributions/browser/context.ts +++ b/packages/vrender-kits/src/canvas/contributions/browser/context.ts @@ -962,8 +962,12 @@ export class BrowserContext2d implements IContext2d { return this._setCommonStyle(params, attribute, offsetX, offsetY, defaultParams[0]); } // TODO 是否存在性能问题? - const dp = {}; - defaultParams.forEach(p => { + // TODO 默认第一个是theme + const dp = Object.create(defaultParams[0]); + defaultParams.forEach((p, i) => { + if (i === 0) { + return; + } Object.assign(dp, p); }); return this._setCommonStyle(params, attribute, offsetX, offsetY, dp as Required); @@ -1007,8 +1011,12 @@ export class BrowserContext2d implements IContext2d { return this._setShadowBlendStyle(params, defaultParams[0]); } // TODO 是否存在性能问题? - const dp = {}; - defaultParams.forEach(p => { + // TODO 默认第一个是theme + const dp = Object.create(defaultParams[0]); + defaultParams.forEach((p, i) => { + if (i === 0) { + return; + } Object.assign(dp, p); }); return this._setShadowBlendStyle(params, attribute, dp as Required); @@ -1084,8 +1092,12 @@ export class BrowserContext2d implements IContext2d { return this._setStrokeStyle(params, attribute, offsetX, offsetY, defaultParams[0]); } // TODO 是否存在性能问题? - const dp = {}; - defaultParams.forEach(p => { + // TODO 默认第一个是theme + const dp = Object.create(defaultParams[0]); + defaultParams.forEach((p, i) => { + if (i === 0) { + return; + } Object.assign(dp, p); }); return this._setStrokeStyle(params, attribute, offsetX, offsetY, dp as IStrokeStyleParams); From ba6ecf6e35955f845cb765c54b8df6e0cf45b837 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Tue, 7 Nov 2023 17:20:51 +0800 Subject: [PATCH 11/40] fix: fix group update matrix issue --- packages/vrender-core/src/graphic/group.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/vrender-core/src/graphic/group.ts b/packages/vrender-core/src/graphic/group.ts index 410a66734..7179c095e 100644 --- a/packages/vrender-core/src/graphic/group.ts +++ b/packages/vrender-core/src/graphic/group.ts @@ -162,12 +162,14 @@ export class Group extends Graphic implements IGroup { const { x = DefaultTransform.x, y = DefaultTransform.y, + dx = DefaultTransform.dx, + dy = DefaultTransform.dy, scaleX = DefaultTransform.scaleX, scaleY = DefaultTransform.scaleY, angle = DefaultTransform.angle, postMatrix } = this.attribute; - if (x === 0 && y === 0 && scaleX === 1 && scaleY === 1 && angle === 0 && !postMatrix) { + if (x === 0 && y === 0 && dx === 0 && dy === 0 && scaleX === 1 && scaleY === 1 && angle === 0 && !postMatrix) { this._transMatrix.reset(); return; } From dc3b92cae9c333d31263b01ee1d9a054da26701c Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Tue, 7 Nov 2023 17:20:51 +0800 Subject: [PATCH 12/40] fix: remove create canvas --- packages/vrender-core/src/core/global.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/vrender-core/src/core/global.ts b/packages/vrender-core/src/core/global.ts index d0cb960ec..4c81bca64 100644 --- a/packages/vrender-core/src/core/global.ts +++ b/packages/vrender-core/src/core/global.ts @@ -15,10 +15,6 @@ import { SyncHook } from '../tapable'; import { EnvContribution } from '../constants'; import type { IAABBBoundsLike } from '@visactor/vutils'; -const canvas = document.createElement('canvas'); -canvas.width = 500; -canvas.height = 500; - const defaultEnv: EnvType = 'browser'; @injectable() export class DefaultGlobal implements IGlobal { From caa34b5d6733f7dcba07bbd0ec34bb765151ef2c Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Tue, 7 Nov 2023 20:39:17 +0800 Subject: [PATCH 13/40] chore: add vchart test --- .../__tests__/browser/src/pages/index.ts | 9 + .../__tests__/browser/src/pages/vchart.ts | 496 ++++++++++++++++++ 2 files changed, 505 insertions(+) create mode 100644 packages/vrender/__tests__/browser/src/pages/vchart.ts diff --git a/packages/vrender/__tests__/browser/src/pages/index.ts b/packages/vrender/__tests__/browser/src/pages/index.ts index b7c73ee3a..0c86147af 100644 --- a/packages/vrender/__tests__/browser/src/pages/index.ts +++ b/packages/vrender/__tests__/browser/src/pages/index.ts @@ -189,5 +189,14 @@ export const pages = [ path: 'text-fly-in' } ] + }, + { + menu: '上层', + children: [ + { + name: 'vchart', + path: 'vchart' + } + ] } ]; diff --git a/packages/vrender/__tests__/browser/src/pages/vchart.ts b/packages/vrender/__tests__/browser/src/pages/vchart.ts new file mode 100644 index 000000000..39b855596 --- /dev/null +++ b/packages/vrender/__tests__/browser/src/pages/vchart.ts @@ -0,0 +1,496 @@ +import * as VRender from '@visactor/vrender'; +import { addShapesToStage, colorPools } from '../utils'; +import { pi, pi2 } from '@visactor/vutils'; + +export const page = () => { + window.VRender = VRender; + import('https://tosv.byted.org/obj/dpvis/vchart-used-in-vrender-bugserver.js').then(async () => { + window.ChartSpace = window.VChart; + const spec = { + width: 500, + height: 500, + type: 'scatter', + xField: 'x', + yField: 'y', + label: { + visible: true, + style: { + fill: '#222' + } + }, + axes: [ + { + orient: 'bottom', + type: 'linear', + range: { + min: 140, + max: 220 + }, + visible: false + }, + { + orient: 'left', + visible: false + } + ], + markArea: [ + { + coordinates: [ + { + x: 140, + y: 0 + }, + { + x: 220, + y: 0 + }, + { + x: 220, + y: 80 + }, + { + x: 140, + y: 80 + } + ], + area: { + style: { + fill: '#5B8FF9', + fillOpacity: 0, + stroke: '#5B8FF9' + } + } + }, + { + coordinates: [ + { + x: 140, + y: 0 + }, + { + x: 180, + y: 0 + }, + { + x: 180, + y: 40 + }, + { + x: 140, + y: 40 + } + ], + area: { + style: { + fill: '#5B8FF9', + fillOpacity: 0.15 + } + } + }, + { + coordinates: [ + { + x: 180, + y: 40 + }, + { + x: 220, + y: 40 + }, + { + x: 220, + y: 80 + }, + { + x: 180, + y: 80 + } + ], + area: { + style: { + fill: '#5B8FF9', + fillOpacity: 0.15 + } + } + } + ], + data: { + id: 'data2', + values: [ + { + name: 'Denmark', + x: 201.53, + y: 26.84 + }, + { + name: 'Switzerland', + x: 196.44, + y: 21.73 + }, + { + name: 'Australia', + x: 196.4, + y: 24.09 + }, + { + name: 'New Zealand', + x: 196.09, + y: 19.43, + label: { + anchor: 'left' + } + }, + { + name: 'Germany', + x: 189.87, + y: 27.68 + }, + { + name: 'Austria', + x: 187, + y: 25.43 + }, + { + name: 'Netherlands', + x: 186.46, + y: 29.08, + label: { + anchor: 'left' + } + }, + { + name: 'Spain', + x: 184.69, + y: 40.37, + label: { + anchor: 'left' + } + }, + { + name: 'Finland', + x: 183.98, + y: 14.57 + }, + { + name: 'United States', + x: 181.91, + y: 32.73, + label: { + anchor: 'left' + } + }, + { + name: 'Portugal', + x: 180.66, + y: 29.87 + }, + { + name: 'Sweden', + x: 177.93, + y: 16.59 + }, + { + name: 'United Kingdom', + x: 177.73, + y: 34.24 + }, + { + name: 'Norway', + x: 176.23, + y: 19.28, + label: { + anchor: 'left' + } + }, + { + name: 'Canada', + x: 172.83, + y: 28.17, + label: { + anchor: 'left' + } + }, + { + name: 'Japan', + x: 172.72, + y: 40.9 + }, + { + name: 'France', + x: 172.3, + y: 42.04, + label: { + anchor: 'left' + } + }, + { + name: 'Estonia', + x: 171.71, + y: 19.19 + }, + { + name: 'Ireland', + x: 170.83, + y: 27.47 + }, + { + name: 'Czech Republic', + x: 167.77, + y: 42.17 + }, + { + name: 'South Korea', + x: 167.52, + y: 50.28, + label: { + anchor: 'left' + } + }, + { + name: 'Croatia', + x: 167.51, + y: 30.69 + }, + { + name: 'Belgium', + x: 162.57, + y: 50.46, + label: { + anchor: 'top', + offsetX: 0, + offsetY: 3 + } + }, + { + name: 'Israel', + x: 160.72, + y: 61.91 + }, + { + name: 'Italy', + x: 160.21, + y: 52.96 + }, + { + name: 'Saudi Arabia', + x: 156.98, + y: 72.12 + }, + { + name: 'Greece', + x: 156.8, + y: 49.1 + }, + { + name: 'Slovakia', + x: 154.13, + y: 44.28 + }, + { + name: 'Taiwan', + x: 150.62, + y: 64.3 + }, + { + name: 'Poland', + x: 150.13, + y: 50.79 + } + ] + } + }; + + const chartSpace = new window.ChartSpace.default(spec, { dom: 'container', animation: false }); + + chartSpace.renderSync(); + console.log(chartSpace); + + // window.BUGSERVER_SCREENSHOT(); + // window.BUGSERVER_RELEASE(() => { + // chartSpace.release(); + // }); + }); + return; + const graphics: IGraphic[] = []; + const startAngle = pi + pi / 20; + const endAngle = pi2 - pi / 20; + const delatAngle = endAngle - startAngle; + const outerRadius = 200; + const innerRadius = 80; + const x = 300; + const y = 300; + + const rectW = 5; + const _startAngle = startAngle + (rectW / (2 * pi * outerRadius)) * pi * 2; + const _endAngle = endAngle - (rectW / (2 * pi * outerRadius)) * pi * 2 * 2; + const _deltaAngle = _endAngle - startAngle; + const _x = x - rectW / 2; + const _y = y; + for (let i = 0; i <= 7; i++) { + const rect = createRect({ + x: _x, + y: _y, + width: rectW, + height: innerRadius, + angle: _startAngle + (_deltaAngle / 7) * i - pi / 2, + anchor: [_x + rectW / 2, _y], + fill: 'brown' + }); + graphics.push(rect); + } + const ba = createArc({ + startAngle: pi + pi / 20, + endAngle: pi2 - pi / 20, + x: 300, + y: 300, + outerRadius, + innerRadius, + // fill: 'green', + background: + 'data:image/png;base64,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' + // texture: 'vertical-line', + // texturePadding: 3, + // textureSize: 3, + // textureColor: 'red', + }); + graphics.push(ba); + + for (let i = 1; i < 8; i++) { + const da = delatAngle / 23; + const arc = createArc({ + startAngle: startAngle + (delatAngle / 8) * i - da / 2, + endAngle: startAngle + (delatAngle / 8) * i + da / 2, + x, + y, + outerRadius, + innerRadius, + fill: '#e9e9e977' + }); + graphics.push(arc); + } + + const zgj = createGlyph({ + x, + y + }); + const s1 = createSymbol({ + symbolType: + 'M -73.8954 505.6538 a 70.4 70.4 0 0 1 -49.9507 -20.6541 c -27.52 -27.5507 -27.52 -72.3405 0 -99.8605 l 24.9651 -24.9805 l -49.9302 -49.9354 l -24.9651 24.9651 c -27.5712 27.5712 -72.3456 27.5405 -99.881 0 c -27.52 -27.5456 -27.52 -72.3405 0 -99.8605 c 27.5354 -27.5354 72.3098 -27.5661 99.881 0 l 24.9651 24.9651 l 49.9302 -49.9302 l -24.9651 -24.9805 c -27.5354 -27.5354 -27.5354 -72.3251 0 -99.8605 c 27.5354 -27.5251 72.3149 -27.5405 99.881 0 L 1 110.4819 l 24.9651 -24.9651 c 27.5712 -27.5405 72.3456 -27.5251 99.881 0 c 27.5354 27.5354 27.5354 72.3251 0 99.8605 l -24.9651 24.9805 l 49.9302 49.9302 l 24.9702 -24.9651 c 27.5661 -27.5661 72.3405 -27.5354 99.881 0 c 27.5149 27.52 27.5149 72.3149 0 99.8656 c -27.52 27.5507 -72.3302 27.5507 -99.881 0 l -24.9702 -24.9651 l -49.9302 49.9302 l 24.9651 24.9805 c 27.52 27.52 27.52 72.3149 0 99.8656 c -27.5149 27.5507 -72.3251 27.5507 -99.881 0 L 1 460.0346 l -24.9651 24.9651 a 70.4 70.4 0 0 1 -49.9302 20.6541 z m 0 -120.5146 l -24.9805 24.9651 c -13.7574 13.7574 -13.7574 36.1574 0 49.9302 c 13.8086 13.7728 36.2035 13.7472 49.9456 0 l 24.9651 -24.9651 l -49.9302 -49.9302 z m 99.8605 49.9302 l 24.9651 24.9651 c 13.7626 13.7728 36.1882 13.7472 49.9507 0 c 13.7626 -13.7728 13.7626 -36.1728 0 -49.9302 l -24.9805 -24.9651 l -49.9354 49.9302 z m -74.8954 -74.9158 L 1 410.0992 l 49.9302 -49.9456 L 1 310.2234 l -49.9302 49.9302 z m 74.8954 -74.8954 l 49.9302 49.9302 l 49.9507 -49.9302 l -49.9507 -49.9302 l -49.9302 49.9302 z m -149.8112 0 l 49.9456 49.9302 l 49.9302 -49.9302 l -49.9302 -49.9302 l -49.9456 49.9302 z m 299.6224 0 l 24.9651 24.9651 c 13.7267 13.7472 36.1626 13.7626 49.9507 0 c 13.7626 -13.7728 13.7626 -36.1728 0 -49.9302 c -13.7728 -13.7779 -36.2035 -13.7421 -49.9507 0 l -24.9651 24.9651 z m -424.4685 24.9651 c 13.8086 13.7626 36.2086 13.7626 49.9456 0 l 24.9651 -24.9651 l -24.9651 -24.9651 c -13.7574 -13.7626 -36.1882 -13.7779 -49.9456 0 c -13.7574 13.7574 -13.7574 36.1523 0 49.9302 z m 199.7619 -99.8605 L 1 260.2931 l 49.9302 -49.9302 L 1 160.4173 l -49.9302 49.9456 z m 74.8954 -74.9158 l 49.9302 49.9302 l 24.9856 -24.9651 c 13.7574 -13.7626 13.7574 -36.1728 0 -49.9302 c -13.7626 -13.7779 -36.1882 -13.8035 -49.9507 0 l -24.9651 24.9651 z m -99.8605 -35.2922 a 35.1744 35.1744 0 0 0 -24.9805 10.3322 c -13.7574 13.7574 -13.7574 36.1728 0 49.9302 l 24.9805 24.9651 l 49.9302 -49.9354 l -24.9651 -24.9651 a 35.2 35.2 0 0 0 -24.9651 -10.327 z', + size: 60, + dy: -30, + fill: '#ff4c4c' + }); + const s2 = createSymbol({ + symbolType: 'circle', + size: 15, + dy: 25, + fill: 'red' + }); + const s3 = createSymbol({ + symbolType: + 'M 2.2406 156.12 h -2.3962 l 0.2509 -157.7626 H 2 z M 7.033 156.12 h -2.3962 l -0.0768 -157.7626 h 1.9098 z M 11.8253 156.12 h -2.3962 l 0.0461 -157.7626 h 1.9098 z M 16.6176 156.12 h -2.391 l -0.2266 -158.12 h 1.9098 z M -2.5568 156.12 h -2.391 l 0.1229 -157.7626 h 1.9098 z M -7.3491 156.12 h -2.3962 l -0.2547 -158.12 h 2 z M -12.1414 156.12 h -2.3962 l -0.4624 -158.12 h 2 z', + size: 30, + scaleY: 1.5, + dy: 30, + fill: '#ff4c4c' + }); + zgj.setSubGraphic([s1, s2, s3]); + graphics.push(zgj); + // graphics.push(createArc({ + // innerRadius: 60, + // outerRadius: 137.8, + // startAngle: -1.5707963267948966, + // endAngle: -0.3141592653589793, + // x: 100, + // y: 200, + // cornerRadius: 6, + // stroke: 'green', + // lineWidth: 2, + // 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 + // })); + + graphics.length = 0; + graphics.push( + createArc({ + innerRadius: 60, + outerRadius: 137.8, + startAngle: 0, + endAngle: Math.PI, + x: 200, + y: 500, + stroke: [false, 'green', false, 'green'], + outerBorder: { + stroke: ['red', false, false, false], + distance: 30, + lineWidth: 10 + }, + lineWidth: 5, + fill: { + x: 0.5, + y: 0.5, + startAngle: 0, + endAngle: 6.283185307179586, + stops: [ + { offset: 0, color: 'red' }, + { offset: 0.2, color: 'blue' }, + { offset: 0.4, color: 'orange' }, + { offset: 0.6, color: 'pink' }, + { offset: 0.8, color: 'green' }, + { offset: 1, color: 'purple' } + ], + gradient: 'conical' + }, + // cap: [true, true], + // cornerRadius: 26, + forceShowCap: true + }) + ); + + const stage = createStage({ + canvas: 'main', + autoRender: true, + poptip: true + }); + + const layer = stage.createLayer(null, 'virtual'); + const t = createText({ + text: '这是第二个图层', + x: 100, + y: 100, + fill: 'red' + }); + layer.add(t); + // t.animate().to({ y: 300 }, 1000, 'linear'); + graphics.forEach(g => { + stage.defaultLayer.add(g); + }); +}; From f44f0d0518c2cc81798d435e967d9eb42ad9d007 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Tue, 7 Nov 2023 20:40:03 +0800 Subject: [PATCH 14/40] feat: optmize bounds performance --- .../fix-performance-bounds_2023-11-07-12-39.json | 10 ++++++++++ .../fix-performance-bounds_2023-11-07-12-39.json | 10 ++++++++++ .../fix-performance-bounds_2023-11-07-12-39.json | 10 ++++++++++ .../fix-performance-bounds_2023-11-07-12-39.json | 10 ++++++++++ 4 files changed, 40 insertions(+) create mode 100644 common/changes/@visactor/vrender-components/fix-performance-bounds_2023-11-07-12-39.json create mode 100644 common/changes/@visactor/vrender-core/fix-performance-bounds_2023-11-07-12-39.json create mode 100644 common/changes/@visactor/vrender-kits/fix-performance-bounds_2023-11-07-12-39.json create mode 100644 common/changes/@visactor/vrender/fix-performance-bounds_2023-11-07-12-39.json diff --git a/common/changes/@visactor/vrender-components/fix-performance-bounds_2023-11-07-12-39.json b/common/changes/@visactor/vrender-components/fix-performance-bounds_2023-11-07-12-39.json new file mode 100644 index 000000000..d27aa4387 --- /dev/null +++ b/common/changes/@visactor/vrender-components/fix-performance-bounds_2023-11-07-12-39.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vrender-components", + "comment": "feat: optmize bounds performance", + "type": "none" + } + ], + "packageName": "@visactor/vrender-components" +} \ No newline at end of file diff --git a/common/changes/@visactor/vrender-core/fix-performance-bounds_2023-11-07-12-39.json b/common/changes/@visactor/vrender-core/fix-performance-bounds_2023-11-07-12-39.json new file mode 100644 index 000000000..1a878451e --- /dev/null +++ b/common/changes/@visactor/vrender-core/fix-performance-bounds_2023-11-07-12-39.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vrender-core", + "comment": "feat: optmize bounds performance", + "type": "none" + } + ], + "packageName": "@visactor/vrender-core" +} \ No newline at end of file diff --git a/common/changes/@visactor/vrender-kits/fix-performance-bounds_2023-11-07-12-39.json b/common/changes/@visactor/vrender-kits/fix-performance-bounds_2023-11-07-12-39.json new file mode 100644 index 000000000..9d459e856 --- /dev/null +++ b/common/changes/@visactor/vrender-kits/fix-performance-bounds_2023-11-07-12-39.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vrender-kits", + "comment": "feat: optmize bounds performance", + "type": "none" + } + ], + "packageName": "@visactor/vrender-kits" +} \ No newline at end of file diff --git a/common/changes/@visactor/vrender/fix-performance-bounds_2023-11-07-12-39.json b/common/changes/@visactor/vrender/fix-performance-bounds_2023-11-07-12-39.json new file mode 100644 index 000000000..45229036e --- /dev/null +++ b/common/changes/@visactor/vrender/fix-performance-bounds_2023-11-07-12-39.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vrender", + "comment": "feat: optmize bounds performance", + "type": "none" + } + ], + "packageName": "@visactor/vrender" +} \ No newline at end of file From d4232c0ba6e6dcf13a4edc7958f002162f10bcca Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Wed, 8 Nov 2023 10:45:45 +0800 Subject: [PATCH 15/40] fix: revert some component edit --- packages/vrender-components/src/axis/base.ts | 9 ++++----- packages/vrender-components/src/axis/line.ts | 15 +-------------- packages/vrender-components/src/core/base.ts | 20 +++----------------- 3 files changed, 8 insertions(+), 36 deletions(-) diff --git a/packages/vrender-components/src/axis/base.ts b/packages/vrender-components/src/axis/base.ts index cf4d08b79..153576608 100644 --- a/packages/vrender-components/src/axis/base.ts +++ b/packages/vrender-components/src/axis/base.ts @@ -13,12 +13,11 @@ import type { IGraphic, IText } from '@visactor/vrender-core'; -import { defaultGraphicMemoryManager, defaultTextAllocate } from '@visactor/vrender-core'; // eslint-disable-next-line no-duplicate-imports import { createLine, createText, createGroup } from '@visactor/vrender-core'; import type { Dict } from '@visactor/vutils'; // eslint-disable-next-line no-duplicate-imports -import { AABBBounds, abs, cloneDeep, get, isEmpty, isFunction, isNumberClose, merge, pi } from '@visactor/vutils'; +import { abs, cloneDeep, get, isEmpty, isFunction, isNumberClose, merge, pi } from '@visactor/vutils'; import { AbstractComponent } from '../core/base'; import type { Point } from '../core/type'; import type { TagAttributes } from '../tag'; @@ -112,11 +111,11 @@ export abstract class AxisBase extends AbstractCom x: this.attribute.x, y: this.attribute.y }); - // this.add(offscreenGroup); + this.add(offscreenGroup); this._renderInner(offscreenGroup); - // this.removeChild(offscreenGroup); + this.removeChild(offscreenGroup); this.attribute = currentAttribute; return offscreenGroup.AABBBounds; } @@ -325,7 +324,7 @@ export abstract class AxisBase extends AbstractCom let textBaseline = 'middle'; data.forEach((item: TransformedAxisItem, index: number) => { const labelStyle = this._getLabelAttribute(item, index, data, layer); - const text = defaultTextAllocate.allocate(labelStyle); + const text = createText(labelStyle); text.name = AXIS_ELEMENT_NAME.label; text.id = this._getNodeId(`layer${layer}-label-${item.id}`); if (isEmpty(this.attribute.label?.state)) { diff --git a/packages/vrender-components/src/axis/line.ts b/packages/vrender-components/src/axis/line.ts index a8d6b5d62..5b31213f8 100644 --- a/packages/vrender-components/src/axis/line.ts +++ b/packages/vrender-components/src/axis/line.ts @@ -13,9 +13,7 @@ import { isValid, normalizePadding, mixin, - last as peek, - AABBBounds, - cloneDeep + last as peek } from '@visactor/vutils'; import type { TextAlignType } from '@visactor/vrender-core'; // eslint-disable-next-line no-duplicate-imports @@ -42,25 +40,14 @@ export interface LineAxis export class LineAxis extends AxisBase { static defaultAttributes = DEFAULT_AXIS_THEME; - // 判定是否是第一次run,第一次不用渲染 - // skipRenderOnce: boolean; constructor(attributes: LineAxisAttributes, mode?: '2d' | '3d') { super(merge({}, LineAxis.defaultAttributes, attributes), mode); if (mode === '3d') { this.setMode(mode); } - // this.skipRenderOnce = true; } - // protected render(): void { - // if (this.skipRenderOnce) { - // this.skipRenderOnce = false; - // return; - // } - // super.render(); - // } - protected _renderInner(container: IGroup) { super._renderInner(container); const { panel } = this.attribute; diff --git a/packages/vrender-components/src/core/base.ts b/packages/vrender-components/src/core/base.ts index 9bc635f0a..b4bab96d6 100644 --- a/packages/vrender-components/src/core/base.ts +++ b/packages/vrender-components/src/core/base.ts @@ -40,22 +40,11 @@ export abstract class AbstractComponent { - this.renderOnSetStage() && this.render(); + this.render(); this.bindEvents(); }); } - renderOnSetStage() { - return true; - } - - shouldAttributesUpdate(params: Partial, forceUpdateTag?: boolean | undefined) { - return true; - } - shouldAttributeUpdate(key: keyof T, value: any, forceUpdateTag?: boolean | undefined) { - return true; - } - /** * @override * 更新单个属性值 @@ -73,7 +62,7 @@ export abstract class AbstractComponent GROUP_ATTRIBUTES.includes(key as string)) - ) { + if (!keys.every(key => GROUP_ATTRIBUTES.includes(key as string))) { this.render(); } From b6ff2e4bb4db812818d7affe904754432f090730 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Thu, 9 Nov 2023 14:37:22 +0800 Subject: [PATCH 16/40] feat: temp store --- .../inversify-lite/annotation/post_construct.ts | 7 ------- .../inversify-lite/container/container_module.ts | 10 ---------- .../vrender-core/src/common/inversify-lite/index.ts | 2 +- .../common/inversify-lite/interfaces/interfaces.ts | 6 ------ packages/vrender-core/src/core/stage.ts | 13 ++----------- packages/vrender-core/src/core/window.ts | 4 ++-- .../contributions/render/draw-contribution.ts | 4 ++-- .../src/picker/canvas-picker-service.ts | 3 +-- .../vrender-kits/src/picker/math-picker-service.ts | 3 +-- 9 files changed, 9 insertions(+), 43 deletions(-) delete mode 100644 packages/vrender-core/src/common/inversify-lite/annotation/post_construct.ts diff --git a/packages/vrender-core/src/common/inversify-lite/annotation/post_construct.ts b/packages/vrender-core/src/common/inversify-lite/annotation/post_construct.ts deleted file mode 100644 index 88b92c1e4..000000000 --- a/packages/vrender-core/src/common/inversify-lite/annotation/post_construct.ts +++ /dev/null @@ -1,7 +0,0 @@ -import * as ERRORS_MSGS from '../constants/error_msgs'; -import * as METADATA_KEY from '../constants/metadata_keys'; -import { propertyEventDecorator } from './property_event_decorator'; - -const postConstruct = propertyEventDecorator(METADATA_KEY.POST_CONSTRUCT, ERRORS_MSGS.MULTIPLE_POST_CONSTRUCT_METHODS); - -export { postConstruct }; diff --git a/packages/vrender-core/src/common/inversify-lite/container/container_module.ts b/packages/vrender-core/src/common/inversify-lite/container/container_module.ts index 2d926c966..c92dc93e2 100644 --- a/packages/vrender-core/src/common/inversify-lite/container/container_module.ts +++ b/packages/vrender-core/src/common/inversify-lite/container/container_module.ts @@ -10,13 +10,3 @@ export class ContainerModule implements interfaces.ContainerModule { this.registry = registry; } } - -export class AsyncContainerModule implements interfaces.AsyncContainerModule { - id: number; - registry: interfaces.AsyncContainerModuleCallBack; - - constructor(registry: interfaces.AsyncContainerModuleCallBack) { - this.id = id(); - this.registry = registry; - } -} diff --git a/packages/vrender-core/src/common/inversify-lite/index.ts b/packages/vrender-core/src/common/inversify-lite/index.ts index 57f5fe688..8dcc137eb 100644 --- a/packages/vrender-core/src/common/inversify-lite/index.ts +++ b/packages/vrender-core/src/common/inversify-lite/index.ts @@ -30,5 +30,5 @@ export { multiInject } from './annotation/multi_inject'; export { injectable } from './annotation/injectable'; export { named } from './annotation/named'; export { Container } from './container/container'; -export { postConstruct } from './annotation/post_construct'; +// export { postConstruct } from './annotation/post_construct'; export * from './interfaces/interfaces'; diff --git a/packages/vrender-core/src/common/inversify-lite/interfaces/interfaces.ts b/packages/vrender-core/src/common/inversify-lite/interfaces/interfaces.ts index 2fdf0b866..3f3070565 100644 --- a/packages/vrender-core/src/common/inversify-lite/interfaces/interfaces.ts +++ b/packages/vrender-core/src/common/inversify-lite/interfaces/interfaces.ts @@ -268,10 +268,6 @@ export namespace interfaces { registry: ContainerModuleCallBack; } - export interface AsyncContainerModule extends ContainerModuleBase { - registry: AsyncContainerModuleCallBack; - } - export interface ModuleActivationHandlers { onActivations: Lookup>; onDeactivations: Lookup>; @@ -301,8 +297,6 @@ export namespace interfaces { // onDeactivation: interfaces.Container['onDeactivation'] ) => void; - export type AsyncContainerModuleCallBack = AsyncCallback; - // export interface ContainerSnapshot { // bindings: Lookup>; // activations: Lookup>; diff --git a/packages/vrender-core/src/core/stage.ts b/packages/vrender-core/src/core/stage.ts index 10af90ea6..c59dcb7a5 100644 --- a/packages/vrender-core/src/core/stage.ts +++ b/packages/vrender-core/src/core/stage.ts @@ -1,5 +1,5 @@ import type { IAABBBounds, IBounds, IBoundsLike, IMatrix } from '@visactor/vutils'; -import { AABBBounds, Bounds, Point, isString } from '@visactor/vutils'; +import { AABBBounds, Bounds, Point } from '@visactor/vutils'; import type { IGraphic, IGroup, @@ -235,13 +235,7 @@ export class Stage extends Group implements IStage { // 创建一个默认layer图层 // this.appendChild(new Layer(this, this.global, this.window, { main: true })); - this.appendChild( - this.layerService.createLayer( - this, - // 如果传入的canvas是string的id,就传入,避免被判定要使用离屏canvas - params.canvas && isString(params.canvas) ? { main: true, canvasId: params.canvas } : { main: true } - ) - ); + this.appendChild(this.layerService.createLayer(this, { main: true })); this.nextFrameRenderLayerSet = new Set(); this.willNextFrameRender = false; @@ -296,9 +290,6 @@ export class Stage extends Group implements IStage { this.ticker.addTimeline(this.timeline); this.timeline.pause(); this.optmize(params.optimize); - if (this._background && isString(this._background)) { - this.setAttributes({ background: this._background }); - } } // 优化策略 diff --git a/packages/vrender-core/src/core/window.ts b/packages/vrender-core/src/core/window.ts index 00f461745..9dc0d41ca 100644 --- a/packages/vrender-core/src/core/window.ts +++ b/packages/vrender-core/src/core/window.ts @@ -1,4 +1,4 @@ -import { inject, injectable, postConstruct } from '../common/inversify-lite'; +import { inject, injectable } from '../common/inversify-lite'; import type { IBoundsLike } from '@visactor/vutils'; import { Generator } from '../common/generator'; import type { @@ -77,9 +77,9 @@ export class DefaultWindow implements IWindow { constructor() { this._uid = Generator.GenAutoIncrementId(); this.global = application.global; + this.postInit(); } - @postConstruct() protected postInit() { this.global.hooks.onSetEnv.tap('window', () => { this.active(); diff --git a/packages/vrender-core/src/render/contributions/render/draw-contribution.ts b/packages/vrender-core/src/render/contributions/render/draw-contribution.ts index 9cd3e1739..79031dc23 100644 --- a/packages/vrender-core/src/render/contributions/render/draw-contribution.ts +++ b/packages/vrender-core/src/render/contributions/render/draw-contribution.ts @@ -1,4 +1,4 @@ -import { injectable, inject, postConstruct, named, multiInject } from '../../../common/inversify-lite'; +import { injectable, inject, named, multiInject } from '../../../common/inversify-lite'; import type { IContext2d, MaybePromise, @@ -63,9 +63,9 @@ export class DefaultDrawContribution implements IDrawContribution { this.backupDirtyBounds = new Bounds(); this.global = application.global; this.layerService = application.layerService; + this.init(); } - @postConstruct() init() { this.contributions.forEach(item => { if (item.style) { diff --git a/packages/vrender-kits/src/picker/canvas-picker-service.ts b/packages/vrender-kits/src/picker/canvas-picker-service.ts index 2df868043..6a340da7b 100644 --- a/packages/vrender-kits/src/picker/canvas-picker-service.ts +++ b/packages/vrender-kits/src/picker/canvas-picker-service.ts @@ -5,7 +5,6 @@ import { inject, injectable, named, - postConstruct, DefaultPickService, DrawContribution, PickItemInterceptor, @@ -69,9 +68,9 @@ export class DefaultCanvasPickerService extends DefaultPickService implements IP }); this.configure(this.global, this.global.env); this.pickerMap = new Map(); + this.init(); } - @postConstruct() init() { this.contributions.getContributions().forEach(item => { this.pickerMap.set(item.numberType, item); diff --git a/packages/vrender-kits/src/picker/math-picker-service.ts b/packages/vrender-kits/src/picker/math-picker-service.ts index 0d2599437..1793e3e9c 100644 --- a/packages/vrender-kits/src/picker/math-picker-service.ts +++ b/packages/vrender-kits/src/picker/math-picker-service.ts @@ -5,7 +5,6 @@ import { inject, injectable, named, - postConstruct, DefaultPickService, EmptyContext2d, PickItemInterceptor @@ -50,9 +49,9 @@ export class DefaultMathPickerService extends DefaultPickService implements IPic }); this.configure(this.global, this.global.env); this.pickerMap = new Map(); + this.init(); } - @postConstruct() init() { this.contributions.getContributions().forEach(item => { this.pickerMap.set(item.numberType, item); From d2636c011ef8a32dbcf0357397cdc39e53f38fe8 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Thu, 9 Nov 2023 14:40:38 +0800 Subject: [PATCH 17/40] chore: change type to minor --- .../vrender-core/fix-performance-bounds_2023-11-07-12-39.json | 2 +- .../vrender-kits/fix-performance-bounds_2023-11-07-12-39.json | 2 +- .../vrender/fix-performance-bounds_2023-11-07-12-39.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/common/changes/@visactor/vrender-core/fix-performance-bounds_2023-11-07-12-39.json b/common/changes/@visactor/vrender-core/fix-performance-bounds_2023-11-07-12-39.json index 1a878451e..da3578e5b 100644 --- a/common/changes/@visactor/vrender-core/fix-performance-bounds_2023-11-07-12-39.json +++ b/common/changes/@visactor/vrender-core/fix-performance-bounds_2023-11-07-12-39.json @@ -3,7 +3,7 @@ { "packageName": "@visactor/vrender-core", "comment": "feat: optmize bounds performance", - "type": "none" + "type": "minor" } ], "packageName": "@visactor/vrender-core" diff --git a/common/changes/@visactor/vrender-kits/fix-performance-bounds_2023-11-07-12-39.json b/common/changes/@visactor/vrender-kits/fix-performance-bounds_2023-11-07-12-39.json index 9d459e856..ef01ed3bc 100644 --- a/common/changes/@visactor/vrender-kits/fix-performance-bounds_2023-11-07-12-39.json +++ b/common/changes/@visactor/vrender-kits/fix-performance-bounds_2023-11-07-12-39.json @@ -3,7 +3,7 @@ { "packageName": "@visactor/vrender-kits", "comment": "feat: optmize bounds performance", - "type": "none" + "type": "minor" } ], "packageName": "@visactor/vrender-kits" diff --git a/common/changes/@visactor/vrender/fix-performance-bounds_2023-11-07-12-39.json b/common/changes/@visactor/vrender/fix-performance-bounds_2023-11-07-12-39.json index 45229036e..f9023d14f 100644 --- a/common/changes/@visactor/vrender/fix-performance-bounds_2023-11-07-12-39.json +++ b/common/changes/@visactor/vrender/fix-performance-bounds_2023-11-07-12-39.json @@ -3,7 +3,7 @@ { "packageName": "@visactor/vrender", "comment": "feat: optmize bounds performance", - "type": "none" + "type": "minor" } ], "packageName": "@visactor/vrender" From 1cdbecfd4fdcef6f1b1a3387724c9f7e9711aed4 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Thu, 9 Nov 2023 15:14:35 +0800 Subject: [PATCH 18/40] feat: skip update bounds while render small node-tree --- ...t-render-skip-bounds_2023-11-09-07-14.json | 10 +++++ packages/vrender-core/src/core/stage.ts | 6 +-- .../contributions/render/draw-contribution.ts | 43 +++++++++++++------ 3 files changed, 44 insertions(+), 15 deletions(-) create mode 100644 common/changes/@visactor/vrender/feat-render-skip-bounds_2023-11-09-07-14.json diff --git a/common/changes/@visactor/vrender/feat-render-skip-bounds_2023-11-09-07-14.json b/common/changes/@visactor/vrender/feat-render-skip-bounds_2023-11-09-07-14.json new file mode 100644 index 000000000..a32295c56 --- /dev/null +++ b/common/changes/@visactor/vrender/feat-render-skip-bounds_2023-11-09-07-14.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vrender", + "comment": "feat: skip update bounds while render small node-tree", + "type": "none" + } + ], + "packageName": "@visactor/vrender" +} \ No newline at end of file diff --git a/packages/vrender-core/src/core/stage.ts b/packages/vrender-core/src/core/stage.ts index 78c4da3b9..2b322562c 100644 --- a/packages/vrender-core/src/core/stage.ts +++ b/packages/vrender-core/src/core/stage.ts @@ -693,7 +693,7 @@ export class Stage extends Group implements IStage { { renderService: this.renderService, background: layer === this.defaultLayer ? this.background : undefined, - updateBounds: !!this.dirtyBounds + updateBounds: !!(this.dirtyBounds && !this.dirtyBounds.empty()) }, { renderStyle: this.renderStyle, ...params } ); @@ -704,7 +704,7 @@ export class Stage extends Group implements IStage { this.interactiveLayer.render( { renderService: this.renderService, - updateBounds: !!this.dirtyBounds + updateBounds: !!(this.dirtyBounds && !this.dirtyBounds.empty()) }, { renderStyle: this.renderStyle, ...params } ); @@ -850,7 +850,7 @@ export class Stage extends Group implements IStage { renderService: this.renderService, background: layer === this.defaultLayer ? this.background : undefined, clear: i === 0, // 第一个layer需要clear - updateBounds: !!this.dirtyBounds + updateBounds: !!(this.dirtyBounds && !this.dirtyBounds.empty()) }); }); } diff --git a/packages/vrender-core/src/render/contributions/render/draw-contribution.ts b/packages/vrender-core/src/render/contributions/render/draw-contribution.ts index 9cd3e1739..5d830f7df 100644 --- a/packages/vrender-core/src/render/contributions/render/draw-contribution.ts +++ b/packages/vrender-core/src/render/contributions/render/draw-contribution.ts @@ -18,7 +18,7 @@ import { findNextGraphic, foreach } from '../../../common/sort'; // eslint-disable-next-line @typescript-eslint/consistent-type-imports import { ContributionProvider } from '../../../common/contribution-provider'; import { DefaultAttribute } from '../../../graphic'; -import type { IAABBBounds, IBounds, IMatrixLike } from '@visactor/vutils'; +import type { IAABBBounds, IBounds, IBoundsLike, IMatrix, IMatrixLike } from '@visactor/vutils'; import { Bounds, getRectIntersect, isRectIntersect, last } from '@visactor/vutils'; import { container } from '../../../container'; import { GraphicRender, IncrementalDrawContribution, RenderSelector } from './symbol'; @@ -39,6 +39,8 @@ export class DefaultDrawContribution implements IDrawContribution { declare styleRenderMap: Map>; declare dirtyBounds: IBounds; declare backupDirtyBounds: IBounds; + // 是否使用dirtyBounds + declare useDirtyBounds: boolean; declare currentRenderService: IRenderService; declare InterceptorContributions: IDrawItemInterceptorContribution[]; @@ -81,7 +83,18 @@ export class DefaultDrawContribution implements IDrawContribution { .sort((a, b) => a.order - b.order); } + prepareForDraw(renderService: IRenderService, drawContext: IDrawContext) { + const count = renderService.renderTreeRoots.reduce((a, b) => a + b.count, 0); + // 小于500个元素就不用计算dirtyBounds了 + if (count < 500) { + this.useDirtyBounds = false; + } else { + this.useDirtyBounds = true; + } + } + draw(renderService: IRenderService, drawContext: IDrawContext): MaybePromise { + this.prepareForDraw(renderService, drawContext); drawContext.drawContribution = this; this.currentRenderMap = this.styleRenderMap.get(drawContext.renderStyle) || this.defaultRenderMap; // this.startAtId = drawParams.startAtId; @@ -181,17 +194,21 @@ export class DefaultDrawContribution implements IDrawContribution { return; } - if (!isRectIntersect(group.AABBBounds, this.dirtyBounds, false)) { + if (this.useDirtyBounds && !isRectIntersect(group.AABBBounds, this.dirtyBounds, false)) { return; } - const tempBounds = boundsAllocate.allocateByObj(this.dirtyBounds); + let nextM: IMatrix; + let tempBounds: IBounds; - // 变换dirtyBounds - const gm = group.transMatrix; - const nextM = matrixAllocate.allocateByObj(parentMatrix).multiply(gm.a, gm.b, gm.c, gm.d, gm.e, gm.f); - // const m = group.globalTransMatrix.getInverse(); - this.dirtyBounds.copy(this.backupDirtyBounds).transformWithMatrix(nextM.getInverse()); + if (this.useDirtyBounds) { + tempBounds = boundsAllocate.allocateByObj(this.dirtyBounds); + // 变换dirtyBounds + const gm = group.transMatrix; + nextM = matrixAllocate.allocateByObj(parentMatrix).multiply(gm.a, gm.b, gm.c, gm.d, gm.e, gm.f); + // const m = group.globalTransMatrix.getInverse(); + this.dirtyBounds.copy(this.backupDirtyBounds).transformWithMatrix(nextM.getInverse()); + } this.renderItem(group, drawContext, { drawingCb: () => { @@ -225,9 +242,11 @@ export class DefaultDrawContribution implements IDrawContribution { } }); - this.dirtyBounds.copy(tempBounds); - boundsAllocate.free(tempBounds); - matrixAllocate.free(nextM); + if (this.useDirtyBounds) { + this.dirtyBounds.copy(tempBounds); + boundsAllocate.free(tempBounds); + matrixAllocate.free(nextM); + } } protected _increaseRender(group: IGroup, drawContext: IDrawContext) { @@ -334,7 +353,7 @@ export class DefaultDrawContribution implements IDrawContribution { } } - if (!(graphic.isContainer || isRectIntersect(graphic.AABBBounds, this.dirtyBounds, false))) { + if (this.useDirtyBounds && !(graphic.isContainer || isRectIntersect(graphic.AABBBounds, this.dirtyBounds, false))) { retrans && this.dirtyBounds.copy(tempBounds); return; } From 34f637f0ed4cd031cd38e6cd308a6f44c212bb7b Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Thu, 9 Nov 2023 15:33:04 +0800 Subject: [PATCH 19/40] fix: fix issue with render text without update cache, closed #660 --- ...t-render-skip-bounds_2023-11-09-07-14.json | 2 +- .../contributions/render/text-render.ts | 57 +++++++++---------- .../__tests__/browser/src/pages/text.ts | 27 ++++----- 3 files changed, 38 insertions(+), 48 deletions(-) diff --git a/common/changes/@visactor/vrender/feat-render-skip-bounds_2023-11-09-07-14.json b/common/changes/@visactor/vrender/feat-render-skip-bounds_2023-11-09-07-14.json index a32295c56..f50ec0144 100644 --- a/common/changes/@visactor/vrender/feat-render-skip-bounds_2023-11-09-07-14.json +++ b/common/changes/@visactor/vrender/feat-render-skip-bounds_2023-11-09-07-14.json @@ -2,7 +2,7 @@ "changes": [ { "packageName": "@visactor/vrender", - "comment": "feat: skip update bounds while render small node-tree", + "comment": "feat: skip update bounds while render small node-tree, closed #660", "type": "none" } ], diff --git a/packages/vrender-core/src/render/contributions/render/text-render.ts b/packages/vrender-core/src/render/contributions/render/text-render.ts index 1cdb25af6..2bf5971e7 100644 --- a/packages/vrender-core/src/render/contributions/render/text-render.ts +++ b/packages/vrender-core/src/render/contributions/render/text-render.ts @@ -58,13 +58,6 @@ export class DefaultCanvasTextRender extends BaseRender implements IGraph const textAttribute = getTheme(text, params?.theme).text; const { text: str, - fill = textAttribute.fill, - stroke = textAttribute.stroke, - fillOpacity = textAttribute.fillOpacity, - strokeOpacity = textAttribute.strokeOpacity, - opacity = textAttribute.opacity, - lineWidth = textAttribute.lineWidth, - visible = textAttribute.visible, underline = textAttribute.underline, lineThrough = textAttribute.lineThrough, keepDirIn3d = textAttribute.keepDirIn3d, @@ -199,6 +192,7 @@ export class DefaultCanvasTextRender extends BaseRender implements IGraph } } } else { + text.tryUpdateAABBBounds(); // 更新cache const cache = text.cache; const { verticalList } = cache; context.textAlign = 'left'; @@ -238,7 +232,6 @@ export class DefaultCanvasTextRender extends BaseRender implements IGraph }); } } else { - const cache = text.cache; if (direction === 'horizontal') { context.setTextStyle(text.attribute, textAttribute, z); const t = text.clipedText as string; @@ -256,29 +249,33 @@ export class DefaultCanvasTextRender extends BaseRender implements IGraph } } drawText(t, 0, dy, 0); - } else if (cache) { - context.setTextStyleWithoutAlignBaseline(text.attribute, textAttribute, z); - const { verticalList } = cache; - let offsetY = 0; - const totalW = verticalList[0].reduce((a, b) => a + (b.width || 0), 0); - let offsetX = 0; - if (textBaseline === 'bottom') { - offsetX = -lineHeight; - } else if (textBaseline === 'middle') { - offsetX = -lineHeight / 2; - } - if (textAlign === 'center') { - offsetY -= totalW / 2; - } else if (textAlign === 'right') { - offsetY -= totalW; + } else { + text.tryUpdateAABBBounds(); // 更新cache + const cache = text.cache; + if (cache) { + context.setTextStyleWithoutAlignBaseline(text.attribute, textAttribute, z); + const { verticalList } = cache; + let offsetY = 0; + const totalW = verticalList[0].reduce((a, b) => a + (b.width || 0), 0); + let offsetX = 0; + if (textBaseline === 'bottom') { + offsetX = -lineHeight; + } else if (textBaseline === 'middle') { + offsetX = -lineHeight / 2; + } + if (textAlign === 'center') { + offsetY -= totalW / 2; + } else if (textAlign === 'right') { + offsetY -= totalW; + } + context.textAlign = 'left'; + context.textBaseline = 'top'; + verticalList[0].forEach(item => { + const { text, width, direction } = item; + drawText(text, offsetX, offsetY, direction); + offsetY += width; + }); } - context.textAlign = 'left'; - context.textBaseline = 'top'; - verticalList[0].forEach(item => { - const { text, width, direction } = item; - drawText(text, offsetX, offsetY, direction); - offsetY += width; - }); } } transform3dMatrixToContextMatrix && this.restoreTransformUseContext2d(text, textAttribute, z, context); diff --git a/packages/vrender/__tests__/browser/src/pages/text.ts b/packages/vrender/__tests__/browser/src/pages/text.ts index acb24b209..c70303f35 100644 --- a/packages/vrender/__tests__/browser/src/pages/text.ts +++ b/packages/vrender/__tests__/browser/src/pages/text.ts @@ -49,23 +49,16 @@ function performance(stage: any) { export const page = () => { const graphics: IGraphic[] = []; const t = createText({ - fontFamily: 'Arial', - fontSize: 14, - fontWeight: null, - fill: '#000', - textAlign: 'left', - textBaseline: 'top', - lineHeight: 14, - ellipsis: '...', - text: 'US-2019-1357144', - maxLineWidth: 119, - autoWrapText: true, - wordBreak: 'break-word', - heightLimit: 20, - pickable: false, - dx: 0, - x: 16, - y: 12 + x: 100, + y: 100, + fill: 'red', + text: ['这是垂aaa直布局的文字(abc】', '这是垂ccc直布局的文字(abc】'], + maxLineWidth: 200, + direction: 'vertical', + fontSize: 20, + stroke: 'green', + textBaseline: 'middle', + textAlign: 'center' }); console.log(t.AABBBounds); graphics.push(t); From 637f548a80da95963323b87112467868b404a8a1 Mon Sep 17 00:00:00 2001 From: xile611 Date: Mon, 13 Nov 2023 16:21:41 +0800 Subject: [PATCH 20/40] perf: add option `skipDefault` to vrender-components --- packages/vrender-components/src/axis/circle.ts | 5 +++-- .../vrender-components/src/axis/grid/base.ts | 8 ++++++-- .../vrender-components/src/axis/grid/circle.ts | 5 +++-- .../vrender-components/src/axis/grid/line.ts | 8 +++----- packages/vrender-components/src/axis/line.ts | 8 +++----- packages/vrender-components/src/brush/brush.ts | 5 +++-- .../src/checkbox/checkbox.ts | 5 +++-- packages/vrender-components/src/core/base.ts | 18 +++++++++++++++--- .../vrender-components/src/crosshair/circle.ts | 5 +++-- .../vrender-components/src/crosshair/line.ts | 5 +++-- .../src/crosshair/polygon.ts | 5 +++-- .../vrender-components/src/crosshair/rect.ts | 5 +++-- .../vrender-components/src/crosshair/sector.ts | 5 +++-- .../src/data-zoom/data-zoom.ts | 5 +++-- packages/vrender-components/src/interface.ts | 7 +++++++ packages/vrender-components/src/label/arc.ts | 5 +++-- packages/vrender-components/src/label/base.ts | 5 +++-- .../vrender-components/src/label/dataLabel.ts | 5 +++-- .../vrender-components/src/label/line-data.ts | 5 +++-- packages/vrender-components/src/label/line.ts | 5 +++-- .../vrender-components/src/label/polygon.ts | 5 +++-- packages/vrender-components/src/label/rect.ts | 5 +++-- .../vrender-components/src/label/symbol.ts | 5 +++-- .../src/legend/color/color.ts | 5 +++-- .../src/legend/discrete/discrete.ts | 5 +++-- .../vrender-components/src/legend/size/size.ts | 6 +++--- .../src/link-path/link-path.ts | 5 +++-- packages/vrender-components/src/marker/area.ts | 5 +++-- packages/vrender-components/src/marker/line.ts | 5 +++-- .../vrender-components/src/marker/point.ts | 5 +++-- packages/vrender-components/src/pager/pager.ts | 5 +++-- .../src/player/base-player.ts | 6 +++--- .../src/player/controller/controller.ts | 5 +++-- .../src/player/discrete-player.ts | 5 +++-- .../vrender-components/src/poptip/poptip.ts | 6 +++--- .../src/scrollbar/scrollbar.ts | 5 +++-- .../vrender-components/src/segment/segment.ts | 5 +++-- .../vrender-components/src/slider/slider.ts | 5 +++-- packages/vrender-components/src/tag/tag.ts | 6 +++--- packages/vrender-components/src/title/title.ts | 5 +++-- .../vrender-components/src/tooltip/tooltip.ts | 5 +++-- 41 files changed, 142 insertions(+), 91 deletions(-) diff --git a/packages/vrender-components/src/axis/circle.ts b/packages/vrender-components/src/axis/circle.ts index ee1dee88c..9a0820a6f 100644 --- a/packages/vrender-components/src/axis/circle.ts +++ b/packages/vrender-components/src/axis/circle.ts @@ -15,6 +15,7 @@ import { DEFAULT_AXIS_THEME } from './config'; import { AXIS_ELEMENT_NAME, DEFAULT_STATES } from './constant'; import { CircleAxisMixin } from './mixin/circle'; import { getLabelPosition } from './util'; +import type { ComponentOptions } from '../interface'; export interface CircleAxis extends Pick, @@ -23,8 +24,8 @@ export interface CircleAxis export class CircleAxis extends AxisBase { static defaultAttributes = DEFAULT_AXIS_THEME; - constructor(attributes: CircleAxisAttributes) { - super(merge({}, CircleAxis.defaultAttributes, attributes)); + constructor(attributes: CircleAxisAttributes, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, CircleAxis.defaultAttributes, attributes)); } protected renderLine(container: IGroup): void { diff --git a/packages/vrender-components/src/axis/grid/base.ts b/packages/vrender-components/src/axis/grid/base.ts index c9c5c960c..33f449908 100644 --- a/packages/vrender-components/src/axis/grid/base.ts +++ b/packages/vrender-components/src/axis/grid/base.ts @@ -196,7 +196,9 @@ export abstract class BaseGrid extends AbstractCom const shape = createPath({ path, z: depth, - ...(isFunction(style) ? merge({}, BaseGrid.defaultAttributes.style, style(item, index)) : style) + ...(isFunction(style) + ? merge({}, this.skipDefault ? null : BaseGrid.defaultAttributes.style, style(item, index)) + : style) }) as Path; shape.name = `${name}-line`; shape.id = this._getNodeId(`${name}-path-${id}`); @@ -223,7 +225,9 @@ export abstract class BaseGrid extends AbstractCom alpha: deltaX > deltaY ? ((points[1].x - points[0].x > 0 ? -1 : 1) * pi) / 2 : 0, beta: deltaX < deltaY ? -pi / 2 : 0, anchor3d: deltaX > deltaY ? [nextPoints[0].x, 0] : [0, nextPoints[0].y], - ...(isFunction(style) ? merge({}, BaseGrid.defaultAttributes.style, style(item, index)) : style) + ...(isFunction(style) + ? merge({}, this.skipDefault ? null : BaseGrid.defaultAttributes.style, style(item, index)) + : style) }) as Path; shape.name = `${name}-line`; shape.id = this._getNodeId(`${name}-path-${id}`); diff --git a/packages/vrender-components/src/axis/grid/circle.ts b/packages/vrender-components/src/axis/grid/circle.ts index 6e84c8f46..f6e9093be 100644 --- a/packages/vrender-components/src/axis/grid/circle.ts +++ b/packages/vrender-components/src/axis/grid/circle.ts @@ -8,14 +8,15 @@ import type { CircleAxisGridAttributes, GridItem } from './type'; import { POLAR_END_ANGLE, POLAR_START_ANGLE } from '../../constant'; import type { TransformedAxisItem } from '../type'; import { CircleAxisMixin } from '../mixin/circle'; +import type { ComponentOptions } from '../../interface'; export interface CircleAxisGrid extends Pick, BaseGrid {} export class CircleAxisGrid extends BaseGrid { - constructor(attributes: CircleAxisGridAttributes) { - super(merge({}, BaseGrid.defaultAttributes, attributes)); + constructor(attributes: CircleAxisGridAttributes, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, BaseGrid.defaultAttributes, attributes), options); } protected getGridAttribute(isSubGrid: boolean) { diff --git a/packages/vrender-components/src/axis/grid/line.ts b/packages/vrender-components/src/axis/grid/line.ts index 9f32f793f..6a1d1ab26 100644 --- a/packages/vrender-components/src/axis/grid/line.ts +++ b/packages/vrender-components/src/axis/grid/line.ts @@ -16,6 +16,7 @@ import type { Point } from '../../core/type'; import { POLAR_START_ANGLE, POLAR_END_ANGLE } from '../../constant'; import type { TransformedAxisItem } from '../type'; import { LineAxisMixin } from '../mixin/line'; +import type { ComponentOptions } from '../../interface'; function getCirclePoints(center: Point, count: number, radius: number, startAngle: number, endAngle: number) { const points: Point[] = []; @@ -32,11 +33,8 @@ export interface LineAxisGrid BaseGrid {} export class LineAxisGrid extends BaseGrid { - constructor(attributes: LineAxisGridAttributes, mode?: '2d' | '3d') { - super(merge({}, BaseGrid.defaultAttributes, attributes), mode); - if (mode === '3d') { - this.setMode(mode); - } + constructor(attributes: LineAxisGridAttributes, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, BaseGrid.defaultAttributes, attributes), options); } private _getGridPoint(gridType: string, point: IPointLike): Point[] { diff --git a/packages/vrender-components/src/axis/line.ts b/packages/vrender-components/src/axis/line.ts index af6c3e4bb..3f36f8f76 100644 --- a/packages/vrender-components/src/axis/line.ts +++ b/packages/vrender-components/src/axis/line.ts @@ -33,6 +33,7 @@ import { autoRotate as autoRotateFunc, getXAxisLabelAlign, getYAxisLabelAlign } import { autoLimit as autoLimitFunc } from './overlap/auto-limit'; import { alignAxisLabels } from '../util/align'; import { LineAxisMixin } from './mixin/line'; +import type { ComponentOptions } from '../interface'; export interface LineAxis extends Pick, @@ -41,11 +42,8 @@ export interface LineAxis export class LineAxis extends AxisBase { static defaultAttributes = DEFAULT_AXIS_THEME; - constructor(attributes: LineAxisAttributes, mode?: '2d' | '3d') { - super(merge({}, LineAxis.defaultAttributes, attributes), mode); - if (mode === '3d') { - this.setMode(mode); - } + constructor(attributes: LineAxisAttributes, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, LineAxis.defaultAttributes, attributes), options); } protected _renderInner(container: IGroup) { diff --git a/packages/vrender-components/src/brush/brush.ts b/packages/vrender-components/src/brush/brush.ts index 33fa24afc..cd0d124ca 100644 --- a/packages/vrender-components/src/brush/brush.ts +++ b/packages/vrender-components/src/brush/brush.ts @@ -9,6 +9,7 @@ import { AbstractComponent } from '../core/base'; import type { BrushAttributes } from './type'; import { IOperateType } from './type'; import { DEFAULT_BRUSH_ATTRIBUTES, DEFAULT_SIZE_THRESHOLD } from './config'; +import type { ComponentOptions } from '../interface'; const delayMap = { debounce: debounce, @@ -43,8 +44,8 @@ export class Brush extends AbstractComponent> { operatedMaskAABBBounds: { [name: string]: IBounds }; }) => void; - constructor(attributes: BrushAttributes) { - super(merge({}, Brush.defaultAttributes, attributes)); + constructor(attributes: BrushAttributes, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, Brush.defaultAttributes, attributes)); } protected bindBrushEvents(): void { diff --git a/packages/vrender-components/src/checkbox/checkbox.ts b/packages/vrender-components/src/checkbox/checkbox.ts index c738d71eb..fe8074510 100644 --- a/packages/vrender-components/src/checkbox/checkbox.ts +++ b/packages/vrender-components/src/checkbox/checkbox.ts @@ -2,6 +2,7 @@ import { merge } from '@visactor/vutils'; import { AbstractComponent } from '../core/base'; import type { CheckboxAttributes } from './type'; import { CustomEvent, Image, Rect, WrapText } from '@visactor/vrender-core'; +import type { ComponentOptions } from '../interface'; const checkSvg = ''; @@ -52,8 +53,8 @@ export class CheckBox extends AbstractComponent> { _indeterminateIcon: Image; _text: WrapText; - constructor(attributes: CheckboxAttributes) { - super(merge({}, CheckBox.defaultAttributes, attributes)); + constructor(attributes: CheckboxAttributes, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, CheckBox.defaultAttributes, attributes)); this.renderGroup(); this.onBeforeAttributeUpdate = (val: any, attributes: any, key: null | string | string[]) => { diff --git a/packages/vrender-components/src/core/base.ts b/packages/vrender-components/src/core/base.ts index 7089ca67c..86cc62f25 100644 --- a/packages/vrender-components/src/core/base.ts +++ b/packages/vrender-components/src/core/base.ts @@ -4,6 +4,7 @@ import type { IGroupGraphicAttribute } from '@visactor/vrender-core'; import { Group } from '@visactor/vrender-core'; import { merge, isFunction, isPlainObject, isNil } from '@visactor/vutils'; +import type { ComponentOptions } from '../interface'; const GROUP_ATTRIBUTES = [ 'x', @@ -26,11 +27,22 @@ const GROUP_ATTRIBUTES = [ export abstract class AbstractComponent extends Group { declare attribute: Partial; - protected mode: '2d' | '3d'; + protected mode?: '2d' | '3d'; - constructor(attributes: T, mode: '2d' | '3d' = '2d') { + protected skipDefault?: boolean; + + constructor(attributes: T, options?: ComponentOptions) { super(attributes); - this.mode = mode; + + if (options?.mode) { + this.mode = options.mode; + + this.setMode(options.mode); + } + + if (options?.skipDefault) { + this.skipDefault = true; + } // 组件需要精准 bounds,所以将这个 strokeBoundsBuffer 设置为 0,否则会影响包围盒的获取 this.setTheme({ common: { diff --git a/packages/vrender-components/src/crosshair/circle.ts b/packages/vrender-components/src/crosshair/circle.ts index bdd19a20e..c02d5c8e9 100644 --- a/packages/vrender-components/src/crosshair/circle.ts +++ b/packages/vrender-components/src/crosshair/circle.ts @@ -6,6 +6,7 @@ import { merge, PointService } from '@visactor/vutils'; import type { PointLocationCfg } from '../core/type'; import { CrosshairBase } from './base'; import type { CircleCrosshairAttrs } from './type'; +import type { ComponentOptions } from '../interface'; export class CircleCrosshair extends CrosshairBase { static defaultAttributes = { @@ -16,8 +17,8 @@ export class CircleCrosshair extends CrosshairBase { } }; - constructor(attributes: CircleCrosshairAttrs) { - super(merge({}, CircleCrosshair.defaultAttributes, attributes)); + constructor(attributes: CircleCrosshairAttrs, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, CircleCrosshair.defaultAttributes, attributes)); } protected renderCrosshair(container: IGroup) { diff --git a/packages/vrender-components/src/crosshair/line.ts b/packages/vrender-components/src/crosshair/line.ts index 0565cdb08..99d320d68 100644 --- a/packages/vrender-components/src/crosshair/line.ts +++ b/packages/vrender-components/src/crosshair/line.ts @@ -6,6 +6,7 @@ import { merge } from '@visactor/vutils'; import type { RegionLocationCfg } from '../core/type'; import { CrosshairBase } from './base'; import type { LineCrosshairAttrs } from './type'; +import type { ComponentOptions } from '../interface'; export class LineCrosshair extends CrosshairBase { static defaultAttributes = { @@ -16,8 +17,8 @@ export class LineCrosshair extends CrosshairBase { } }; - constructor(attributes: LineCrosshairAttrs) { - super(merge({}, LineCrosshair.defaultAttributes, attributes)); + constructor(attributes: LineCrosshairAttrs, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, LineCrosshair.defaultAttributes, attributes)); } protected renderCrosshair(container: IGroup) { diff --git a/packages/vrender-components/src/crosshair/polygon.ts b/packages/vrender-components/src/crosshair/polygon.ts index 418f76c31..c9bad4905 100644 --- a/packages/vrender-components/src/crosshair/polygon.ts +++ b/packages/vrender-components/src/crosshair/polygon.ts @@ -6,6 +6,7 @@ import { merge, polarToCartesian, PointService } from '@visactor/vutils'; import type { PointLocationCfg } from '../core/type'; import { CrosshairBase } from './base'; import type { PolygonCrosshairAttrs } from './type'; +import type { ComponentOptions } from '../interface'; export class PolygonCrosshair extends CrosshairBase { static defaultAttributes = { @@ -16,8 +17,8 @@ export class PolygonCrosshair extends CrosshairBase { } }; - constructor(attributes: PolygonCrosshairAttrs) { - super(merge({}, PolygonCrosshair.defaultAttributes, attributes)); + constructor(attributes: PolygonCrosshairAttrs, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, PolygonCrosshair.defaultAttributes, attributes)); } protected renderCrosshair(container: IGroup) { diff --git a/packages/vrender-components/src/crosshair/rect.ts b/packages/vrender-components/src/crosshair/rect.ts index 4819e67e1..70d1ee7f7 100644 --- a/packages/vrender-components/src/crosshair/rect.ts +++ b/packages/vrender-components/src/crosshair/rect.ts @@ -7,6 +7,7 @@ import type { RegionLocationCfg } from '../core/type'; import type { Tag } from '../tag'; import { CrosshairBase } from './base'; import type { RectCrosshairAttrs } from './type'; +import type { ComponentOptions } from '../interface'; export class RectCrosshair extends CrosshairBase { static defaultAttributes = { @@ -21,8 +22,8 @@ export class RectCrosshair extends CrosshairBase { protected leftLabelShape?: Tag; protected rightLabelShape?: Tag; - constructor(attributes: RectCrosshairAttrs) { - super(merge({}, RectCrosshair.defaultAttributes, attributes)); + constructor(attributes: RectCrosshairAttrs, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, RectCrosshair.defaultAttributes, attributes)); } protected renderCrosshair(container: IGroup) { diff --git a/packages/vrender-components/src/crosshair/sector.ts b/packages/vrender-components/src/crosshair/sector.ts index 9091c823c..4c98f5034 100644 --- a/packages/vrender-components/src/crosshair/sector.ts +++ b/packages/vrender-components/src/crosshair/sector.ts @@ -7,6 +7,7 @@ import type { PointLocationCfg } from '../core/type'; import { POLAR_END_ANGLE, POLAR_START_ANGLE } from '../constant'; import { CrosshairBase } from './base'; import type { SectorCrosshairAttrs } from './type'; +import type { ComponentOptions } from '../interface'; export class SectorCrosshair extends CrosshairBase { static defaultAttributes = { @@ -16,8 +17,8 @@ export class SectorCrosshair extends CrosshairBase { } }; - constructor(attributes: SectorCrosshairAttrs) { - super(merge({}, SectorCrosshair.defaultAttributes, attributes)); + constructor(attributes: SectorCrosshairAttrs, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, SectorCrosshair.defaultAttributes, attributes)); } protected renderCrosshair(container: IGroup) { diff --git a/packages/vrender-components/src/data-zoom/data-zoom.ts b/packages/vrender-components/src/data-zoom/data-zoom.ts index a9052a395..812e65946 100644 --- a/packages/vrender-components/src/data-zoom/data-zoom.ts +++ b/packages/vrender-components/src/data-zoom/data-zoom.ts @@ -9,6 +9,7 @@ import type { TagAttributes } from '../tag'; import { Tag } from '../tag'; import { DataZoomActiveTag, DEFAULT_DATA_ZOOM_ATTRIBUTES } from './config'; import type { DataZoomAttributes } from './type'; +import type { ComponentOptions } from '../interface'; const delayMap = { debounce: debounce, @@ -84,8 +85,8 @@ export class DataZoom extends AbstractComponent> { private _statePointToData: (state: number) => any = state => state; private _layoutAttrFromConfig: any; // 用于缓存 - constructor(attributes: DataZoomAttributes) { - super(merge({}, DataZoom.defaultAttributes, attributes)); + constructor(attributes: DataZoomAttributes, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, DataZoom.defaultAttributes, attributes)); const { start, end, diff --git a/packages/vrender-components/src/interface.ts b/packages/vrender-components/src/interface.ts index 560c60219..e15f44d3e 100644 --- a/packages/vrender-components/src/interface.ts +++ b/packages/vrender-components/src/interface.ts @@ -12,3 +12,10 @@ export type BackgroundAttributes = { } & Partial; export type IDelayType = 'debounce' | 'throttle'; + +export interface ComponentOptions { + /** skip default attributes of component */ + skipDefault?: boolean; + /** the mode of component, only axis support 3d mode now */ + mode?: '2d' | '3d'; +} diff --git a/packages/vrender-components/src/label/arc.ts b/packages/vrender-components/src/label/arc.ts index 730e41003..e0a56c08d 100644 --- a/packages/vrender-components/src/label/arc.ts +++ b/packages/vrender-components/src/label/arc.ts @@ -12,6 +12,7 @@ import { checkBoundsOverlap, computeQuadrant } from './util'; +import type { ComponentOptions } from '../interface'; export class ArcInfo { key!: string; @@ -129,8 +130,8 @@ export class ArcLabel extends LabelBase { private _arcLeft: Map = new Map(); private _arcRight: Map = new Map(); - constructor(attributes: ArcLabelAttrs) { - super(merge({}, ArcLabel.defaultAttributes, attributes)); + constructor(attributes: ArcLabelAttrs, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, ArcLabel.defaultAttributes, attributes)); } protected _overlapping(labels: IText[]) { diff --git a/packages/vrender-components/src/label/base.ts b/packages/vrender-components/src/label/base.ts index 6dbfbb388..0e8d6b44c 100644 --- a/packages/vrender-components/src/label/base.ts +++ b/packages/vrender-components/src/label/base.ts @@ -34,6 +34,7 @@ import { bitmapTool, boundToRange, canPlace, clampText, place } from './overlap' import type { BaseLabelAttrs, OverlapAttrs, ILabelAnimation, ArcLabelAttrs, LabelItem, SmartInvertAttrs } from './type'; import { DefaultLabelAnimation, getAnimationAttributes } from './animate/animate'; import { getPointsOfLineArea } from './util'; +import type { ComponentOptions } from '../interface'; export class LabelBase extends AbstractComponent { name = 'label'; @@ -80,8 +81,8 @@ export class LabelBase extends AbstractComponent { private _enableAnimation: boolean; - constructor(attributes: BaseLabelAttrs) { - super(merge({}, LabelBase.defaultAttributes, attributes)); + constructor(attributes: BaseLabelAttrs, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, LabelBase.defaultAttributes, attributes)); } /** diff --git a/packages/vrender-components/src/label/dataLabel.ts b/packages/vrender-components/src/label/dataLabel.ts index 27918de47..665b1447f 100644 --- a/packages/vrender-components/src/label/dataLabel.ts +++ b/packages/vrender-components/src/label/dataLabel.ts @@ -10,6 +10,7 @@ import type { DataLabelAttrs } from './type'; import type { LabelBase } from './base'; import { LabelBase as PointLabel } from './base'; import { LineDataLabel } from './line-data'; +import type { ComponentOptions } from '../interface'; const labelComponentMap = { rect: RectLabel, @@ -27,8 +28,8 @@ export class DataLabel extends AbstractComponent { pickable: false }; - constructor(attributes: DataLabelAttrs) { - super(merge({}, DataLabel.defaultAttributes, attributes)); + constructor(attributes: DataLabelAttrs, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, DataLabel.defaultAttributes, attributes)); } protected render(): void { diff --git a/packages/vrender-components/src/label/line-data.ts b/packages/vrender-components/src/label/line-data.ts index ea4dcd2bf..71e21382f 100644 --- a/packages/vrender-components/src/label/line-data.ts +++ b/packages/vrender-components/src/label/line-data.ts @@ -3,6 +3,7 @@ import { merge } from '@visactor/vutils'; import type { LineDataLabelAttrs } from './type'; import { LabelBase } from './base'; import { labelingPoint } from './util'; +import type { ComponentOptions } from '../interface'; export class LineDataLabel extends LabelBase { name = 'line-data-label'; @@ -20,8 +21,8 @@ export class LineDataLabel extends LabelBase { pickable: false }; - constructor(attributes: LineDataLabelAttrs) { - super(merge({}, LineDataLabel.defaultAttributes, attributes)); + constructor(attributes: LineDataLabelAttrs, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, LineDataLabel.defaultAttributes, attributes)); } protected labeling(textBounds: IBoundsLike, graphicBounds: IBoundsLike, position = 'top', offset = 0) { diff --git a/packages/vrender-components/src/label/line.ts b/packages/vrender-components/src/label/line.ts index 26b00bf16..5a7472309 100644 --- a/packages/vrender-components/src/label/line.ts +++ b/packages/vrender-components/src/label/line.ts @@ -4,6 +4,7 @@ import type { ILine } from '@visactor/vrender-core'; import type { PointLocationCfg } from '../core/type'; import type { LineLabelAttrs } from './type'; import { LabelBase } from './base'; +import type { ComponentOptions } from '../interface'; export class LineLabel extends LabelBase { name = 'line-label'; @@ -21,8 +22,8 @@ export class LineLabel extends LabelBase { pickable: false }; - constructor(attributes: LineLabelAttrs) { - super(merge({}, LineLabel.defaultAttributes, attributes)); + constructor(attributes: LineLabelAttrs, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, LineLabel.defaultAttributes, attributes)); } protected getGraphicBounds(graphic: ILine, point: Partial = {}) { diff --git a/packages/vrender-components/src/label/polygon.ts b/packages/vrender-components/src/label/polygon.ts index d6464171d..0f24a74df 100644 --- a/packages/vrender-components/src/label/polygon.ts +++ b/packages/vrender-components/src/label/polygon.ts @@ -2,6 +2,7 @@ import type { IBoundsLike } from '@visactor/vutils'; import { merge } from '@visactor/vutils'; import type { PolygonLabelAttrs } from './type'; import { LabelBase } from './base'; +import type { ComponentOptions } from '../interface'; export class PolygonLabel extends LabelBase { name = 'polygon-label'; @@ -19,8 +20,8 @@ export class PolygonLabel extends LabelBase { pickable: false }; - constructor(attributes: PolygonLabelAttrs) { - super(merge({}, PolygonLabel.defaultAttributes, attributes)); + constructor(attributes: PolygonLabelAttrs, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, PolygonLabel.defaultAttributes, attributes)); } protected labeling( diff --git a/packages/vrender-components/src/label/rect.ts b/packages/vrender-components/src/label/rect.ts index 8838a2292..e498327dc 100644 --- a/packages/vrender-components/src/label/rect.ts +++ b/packages/vrender-components/src/label/rect.ts @@ -2,6 +2,7 @@ import type { IBoundsLike } from '@visactor/vutils'; import { merge } from '@visactor/vutils'; import type { RectLabelAttrs } from './type'; import { LabelBase } from './base'; +import type { ComponentOptions } from '../interface'; export class RectLabel extends LabelBase { static tag = 'rect-label'; @@ -19,8 +20,8 @@ export class RectLabel extends LabelBase { pickable: false }; - constructor(attributes: RectLabelAttrs) { - super(merge({}, RectLabel.defaultAttributes, attributes)); + constructor(attributes: RectLabelAttrs, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, RectLabel.defaultAttributes, attributes)); } protected labeling(textBounds: IBoundsLike, graphicBounds: IBoundsLike, position = 'top', offset = 0) { diff --git a/packages/vrender-components/src/label/symbol.ts b/packages/vrender-components/src/label/symbol.ts index 35a1c59dc..81f7e2dc4 100644 --- a/packages/vrender-components/src/label/symbol.ts +++ b/packages/vrender-components/src/label/symbol.ts @@ -3,6 +3,7 @@ import { merge } from '@visactor/vutils'; import type { SymbolLabelAttrs } from './type'; import { LabelBase } from './base'; import { labelingPoint } from './util'; +import type { ComponentOptions } from '../interface'; export class SymbolLabel extends LabelBase { name = 'symbol-label'; @@ -20,8 +21,8 @@ export class SymbolLabel extends LabelBase { pickable: false }; - constructor(attributes: SymbolLabelAttrs) { - super(merge({}, SymbolLabel.defaultAttributes, attributes)); + constructor(attributes: SymbolLabelAttrs, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, SymbolLabel.defaultAttributes, attributes)); } protected labeling(textBounds: IBoundsLike, graphicBounds: IBoundsLike, position = 'top', offset = 0) { diff --git a/packages/vrender-components/src/legend/color/color.ts b/packages/vrender-components/src/legend/color/color.ts index 81a91c0bf..6511f158d 100644 --- a/packages/vrender-components/src/legend/color/color.ts +++ b/packages/vrender-components/src/legend/color/color.ts @@ -11,6 +11,7 @@ import { LegendBase } from '../base'; import { Slider } from '../../slider'; import { DEFAULT_TITLE_SPACE } from '../constant'; import type { ColorLegendAttributes } from './type'; +import type { ComponentOptions } from '../../interface'; export class ColorContinuousLegend extends LegendBase { name = 'colorLegend'; @@ -43,8 +44,8 @@ export class ColorContinuousLegend extends LegendBase { private _colorScale!: ILinearScale; private _color: IColor | undefined; - constructor(attributes: ColorLegendAttributes) { - super(merge({}, ColorContinuousLegend.defaultAttributes, attributes)); + constructor(attributes: ColorLegendAttributes, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, ColorContinuousLegend.defaultAttributes, attributes)); } /** diff --git a/packages/vrender-components/src/legend/discrete/discrete.ts b/packages/vrender-components/src/legend/discrete/discrete.ts index e5c672220..30fa9f6bd 100644 --- a/packages/vrender-components/src/legend/discrete/discrete.ts +++ b/packages/vrender-components/src/legend/discrete/discrete.ts @@ -30,6 +30,7 @@ import { LEGEND_ELEMENT_NAME } from '../constant'; import type { DiscreteLegendAttrs, LegendItem, LegendItemDatum } from './type'; +import type { ComponentOptions } from '../../interface'; const DEFAULT_STATES = { [LegendStateValue.focus]: {}, @@ -138,8 +139,8 @@ export class DiscreteLegend extends LegendBase { allowAllCanceled: true }; - constructor(attributes: DiscreteLegendAttrs) { - super(merge({}, DiscreteLegend.defaultAttributes, attributes)); + constructor(attributes: DiscreteLegendAttrs, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, DiscreteLegend.defaultAttributes, attributes)); } /** diff --git a/packages/vrender-components/src/legend/size/size.ts b/packages/vrender-components/src/legend/size/size.ts index 29a2c9ada..d0bc02e8b 100644 --- a/packages/vrender-components/src/legend/size/size.ts +++ b/packages/vrender-components/src/legend/size/size.ts @@ -7,7 +7,7 @@ import { merge, get } from '@visactor/vutils'; import { LegendBase } from '../base'; import { Slider } from '../../slider'; import { DEFAULT_TITLE_SPACE } from '../constant'; -import type { OrientType } from '../../interface'; +import type { ComponentOptions, OrientType } from '../../interface'; import type { SizeLegendAttributes } from './type'; export function getSizeHandlerPath(align: OrientType = 'bottom') { @@ -86,8 +86,8 @@ export class SizeContinuousLegend extends LegendBase { private _slider!: Slider; - constructor(attributes: SizeLegendAttributes) { - super(merge({}, SizeContinuousLegend.defaultAttributes, attributes)); + constructor(attributes: SizeLegendAttributes, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, SizeContinuousLegend.defaultAttributes, attributes)); } setSelected(value: number[]) { diff --git a/packages/vrender-components/src/link-path/link-path.ts b/packages/vrender-components/src/link-path/link-path.ts index 333a7165d..a81b2c9e4 100644 --- a/packages/vrender-components/src/link-path/link-path.ts +++ b/packages/vrender-components/src/link-path/link-path.ts @@ -6,6 +6,7 @@ import type { IGroup, IPath } from '@visactor/vrender-core'; import { merge } from '@visactor/vutils'; import { AbstractComponent } from '../core/base'; import type { LinkPathAttributes } from './type'; +import type { ComponentOptions } from '../interface'; export const getHorizontalPath = (options: LinkPathAttributes, ratio?: number) => { let x0 = options.x0; @@ -121,8 +122,8 @@ export class LinkPath extends AbstractComponent> { private _backPath?: IPath; private _frontPath?: IPath; - constructor(attributes: LinkPathAttributes) { - super(merge({}, LinkPath.defaultAttributes, attributes)); + constructor(attributes: LinkPathAttributes, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, LinkPath.defaultAttributes, attributes)); } protected render() { diff --git a/packages/vrender-components/src/marker/area.ts b/packages/vrender-components/src/marker/area.ts index 269af8e35..7386818fc 100644 --- a/packages/vrender-components/src/marker/area.ts +++ b/packages/vrender-components/src/marker/area.ts @@ -6,6 +6,7 @@ import { Marker } from './base'; import { DEFAULT_MARK_AREA_TEXT_STYLE_MAP, DEFAULT_MARK_AREA_THEME } from './config'; import type { MarkAreaAttrs } from './type'; import { limitShapeInBounds } from '../util/limit-shape'; +import type { ComponentOptions } from '../interface'; export class MarkArea extends Marker { name = 'markArea'; @@ -19,8 +20,8 @@ export class MarkArea extends Marker { return this._label; } - constructor(attributes: MarkAreaAttrs) { - super(merge({}, MarkArea.defaultAttributes, attributes)); + constructor(attributes: MarkAreaAttrs, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, MarkArea.defaultAttributes, attributes)); } private _getPositionByDirection(area: IPolygon, direction: string) { diff --git a/packages/vrender-components/src/marker/line.ts b/packages/vrender-components/src/marker/line.ts index 996ebb7ee..445bd2b05 100644 --- a/packages/vrender-components/src/marker/line.ts +++ b/packages/vrender-components/src/marker/line.ts @@ -7,6 +7,7 @@ import { DEFAULT_MARK_LINE_THEME, DEFAULT_MARK_LINE_TEXT_STYLE_MAP } from './con import type { MarkLineAttrs } from './type'; import { limitShapeInBounds } from '../util/limit-shape'; import type { Point } from '../core/type'; +import type { ComponentOptions } from '../interface'; export class MarkLine extends Marker { name = 'markLine'; @@ -20,8 +21,8 @@ export class MarkLine extends Marker { return this._label; } - constructor(attributes: MarkLineAttrs) { - super(merge({}, MarkLine.defaultAttributes, attributes)); + constructor(attributes: MarkLineAttrs, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, MarkLine.defaultAttributes, attributes)); } protected setLabelPos() { diff --git a/packages/vrender-components/src/marker/point.ts b/packages/vrender-components/src/marker/point.ts index 58f9a15a0..cf7d513b5 100644 --- a/packages/vrender-components/src/marker/point.ts +++ b/packages/vrender-components/src/marker/point.ts @@ -22,6 +22,7 @@ import type { IItemContent, IItemLine, MarkPointAttrs } from './type'; // eslint-disable-next-line no-duplicate-imports import { IMarkPointItemPosition } from './type'; import type { Point } from '../core/type'; +import type { ComponentOptions } from '../interface'; export class MarkPoint extends Marker { name = 'markPoint'; @@ -33,8 +34,8 @@ export class MarkPoint extends Marker { private _decorativeLine!: ILine; - constructor(attributes: MarkPointAttrs) { - super(merge({}, MarkPoint.defaultAttributes, attributes)); + constructor(attributes: MarkPointAttrs, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, MarkPoint.defaultAttributes, attributes)); } protected setLabelPos() { diff --git a/packages/vrender-components/src/pager/pager.ts b/packages/vrender-components/src/pager/pager.ts index b00f7b6e9..cc7e1f62c 100644 --- a/packages/vrender-components/src/pager/pager.ts +++ b/packages/vrender-components/src/pager/pager.ts @@ -8,6 +8,7 @@ import { merge, normalizePadding, isNumber } from '@visactor/vutils'; import { AbstractComponent } from '../core/base'; import { measureTextSize } from '../util'; import type { PagerAttributes } from './type'; +import type { ComponentOptions } from '../interface'; const DEFAULT_HANDLER_STYLE: PagerAttributes['handler'] = { space: 8, @@ -46,8 +47,8 @@ export class Pager extends AbstractComponent> { } }; - constructor(attributes: PagerAttributes) { - super(merge({}, Pager.defaultAttributes, attributes)); + constructor(attributes: PagerAttributes, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, Pager.defaultAttributes, attributes)); } protected render() { diff --git a/packages/vrender-components/src/player/base-player.ts b/packages/vrender-components/src/player/base-player.ts index 58bb165a9..0a9e6a5c9 100644 --- a/packages/vrender-components/src/player/base-player.ts +++ b/packages/vrender-components/src/player/base-player.ts @@ -2,7 +2,7 @@ import type { INode } from '@visactor/vrender-core'; import { CustomEvent } from '@visactor/vrender-core'; import { isNumber, isValidNumber, max, merge } from '@visactor/vutils'; import { AbstractComponent } from '../core/base'; -import type { OrientType } from '../interface'; +import type { ComponentOptions, OrientType } from '../interface'; import type { SliderAttributes } from '../slider'; import { Slider } from '../slider'; import type { ControllerAttributes } from './controller'; @@ -91,8 +91,8 @@ export class BasePlayer extends AbstractComponent> forward?: { x: number; y: number; size: number }; } = {}; - constructor(attributes: T) { - super(merge({}, BasePlayer.defaultAttributes, attributes)); + constructor(attributes: T, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, BasePlayer.defaultAttributes, attributes)); // 先初始化属性, 再初始化Slider、Controller, 最后初始化事件. this._initAttributes(); this._initLayoutInfo(); diff --git a/packages/vrender-components/src/player/controller/controller.ts b/packages/vrender-components/src/player/controller/controller.ts index 909f10d4b..6e1037593 100644 --- a/packages/vrender-components/src/player/controller/controller.ts +++ b/packages/vrender-components/src/player/controller/controller.ts @@ -7,6 +7,7 @@ import type { ControllerAttributes, LayoutType } from './type'; import { iconRight, iconPause, iconPlay, iconLeft, iconUp, iconDown } from './assets'; import { PlayerIcon } from './icon'; import { ControllerEventEnum, ControllerTypeEnum } from './constant'; +import type { ComponentOptions } from '../../interface'; export class Controller extends AbstractComponent> { static defaultControllerAttr: ISymbolGraphicAttribute = { @@ -36,8 +37,8 @@ export class Controller extends AbstractComponent private _forwardAttr: BaseGraphicAttributes; private _backwardAttr: BaseGraphicAttributes; - constructor(attributes: ControllerAttributes) { - super(merge({}, Controller.defaultAttributes, attributes)); + constructor(attributes: ControllerAttributes, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, Controller.defaultAttributes, attributes)); this.updateAttributes(); this._initPlay(); this._initBackward(); diff --git a/packages/vrender-components/src/player/discrete-player.ts b/packages/vrender-components/src/player/discrete-player.ts index b13eaff99..e6e557fab 100644 --- a/packages/vrender-components/src/player/discrete-player.ts +++ b/packages/vrender-components/src/player/discrete-player.ts @@ -6,6 +6,7 @@ import type { DirectionType, DiscretePlayerAttributes, PlayerAttributes } from ' import { DirectionEnum, PlayerEventEnum } from './type'; import { forwardStep, isReachEnd, isReachStart } from './utils'; import { ControllerEventEnum } from './controller/constant'; +import type { ComponentOptions } from '../interface'; export interface IDiscretePlayer { play: () => void; @@ -28,8 +29,8 @@ export class DiscretePlayer extends BasePlayer impleme private _rafId: number; private _isReachEnd = false; - constructor(attributes: DiscretePlayerAttributes) { - super(merge({}, attributes)); + constructor(attributes: DiscretePlayerAttributes, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, attributes)); this._initAttributes(); this._initEvents(); diff --git a/packages/vrender-components/src/poptip/poptip.ts b/packages/vrender-components/src/poptip/poptip.ts index b8382860a..91fb8bea3 100644 --- a/packages/vrender-components/src/poptip/poptip.ts +++ b/packages/vrender-components/src/poptip/poptip.ts @@ -26,7 +26,7 @@ import { rectInsideAnotherRect } from '@visactor/vutils'; import { AbstractComponent } from '../core/base'; -import type { BackgroundAttributes } from '../interface'; +import type { BackgroundAttributes, ComponentOptions } from '../interface'; import type { PopTipAttributes } from './type'; const _tBounds = new AABBBounds(); @@ -56,8 +56,8 @@ export class PopTip extends AbstractComponent> { padding: 10 }; - constructor(attributes: PopTipAttributes) { - super(merge({}, PopTip.defaultAttributes, attributes)); + constructor(attributes: PopTipAttributes, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, PopTip.defaultAttributes, attributes)); } protected render() { diff --git a/packages/vrender-components/src/scrollbar/scrollbar.ts b/packages/vrender-components/src/scrollbar/scrollbar.ts index fa6c14ae8..0d72f33e6 100644 --- a/packages/vrender-components/src/scrollbar/scrollbar.ts +++ b/packages/vrender-components/src/scrollbar/scrollbar.ts @@ -7,6 +7,7 @@ import { merge, normalizePadding, clamp, clampRange, debounce, throttle } from ' import { AbstractComponent } from '../core/base'; import type { ScrollBarAttributes } from './type'; +import type { ComponentOptions } from '../interface'; type ComponentBounds = { x1: number; @@ -57,8 +58,8 @@ export class ScrollBar extends AbstractComponent> private _viewPosition!: { x: number; y: number }; private _sliderSize!: number; - constructor(attributes: ScrollBarAttributes) { - super(merge({}, ScrollBar.defaultAttributes, attributes)); + constructor(attributes: ScrollBarAttributes, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, ScrollBar.defaultAttributes, attributes)); } setScrollRange(range: [number, number], render = true) { diff --git a/packages/vrender-components/src/segment/segment.ts b/packages/vrender-components/src/segment/segment.ts index cfc731c15..96e63f16f 100644 --- a/packages/vrender-components/src/segment/segment.ts +++ b/packages/vrender-components/src/segment/segment.ts @@ -7,6 +7,7 @@ import { createSymbol, createLine, createPolygon } from '@visactor/vrender-core' import { AbstractComponent } from '../core/base'; import type { SegmentAttributes, SymbolAttributes } from './type'; import type { Point } from '../core/type'; +import type { ComponentOptions } from '../interface'; export class Segment extends AbstractComponent> { name = 'segment'; @@ -69,8 +70,8 @@ export class Segment extends AbstractComponent> { } }; - constructor(attributes: SegmentAttributes) { - super(merge({}, Segment.defaultAttributes, attributes)); + constructor(attributes: SegmentAttributes, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, Segment.defaultAttributes, attributes)); } protected render() { diff --git a/packages/vrender-components/src/slider/slider.ts b/packages/vrender-components/src/slider/slider.ts index bbdef3fe8..7bb20dc33 100644 --- a/packages/vrender-components/src/slider/slider.ts +++ b/packages/vrender-components/src/slider/slider.ts @@ -20,6 +20,7 @@ import { AbstractComponent } from '../core/base'; import { SLIDER_ELEMENT_NAME } from './constant'; import type { SliderAttributes } from './type'; +import type { ComponentOptions } from '../interface'; function convertValueToRange(value: number | [number, number]) { if (isArray(value)) { @@ -113,8 +114,8 @@ export class Slider extends AbstractComponent> { return this._endHandler; } - constructor(attributes: SliderAttributes) { - super(merge({}, Slider.defaultAttributes, attributes)); + constructor(attributes: SliderAttributes, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, Slider.defaultAttributes, attributes)); } /** diff --git a/packages/vrender-components/src/tag/tag.ts b/packages/vrender-components/src/tag/tag.ts index eed4a8c82..bacb2e261 100644 --- a/packages/vrender-components/src/tag/tag.ts +++ b/packages/vrender-components/src/tag/tag.ts @@ -5,7 +5,7 @@ import type { IGroup, IRect, ISymbol, IText, ITextAttribute, ITextGraphicAttribu import { isBoolean, isEmpty, isNil, isNumber, isValid, merge, normalizePadding } from '@visactor/vutils'; import { AbstractComponent } from '../core/base'; import { measureTextSize } from '../util'; -import type { BackgroundAttributes } from '../interface'; +import type { BackgroundAttributes, ComponentOptions } from '../interface'; import type { TagAttributes, TagShapeAttributes } from './type'; export class Tag extends AbstractComponent> { @@ -27,8 +27,8 @@ export class Tag extends AbstractComponent> { } }; - constructor(attributes: TagAttributes) { - super(merge({}, Tag.defaultAttributes, attributes)); + constructor(attributes: TagAttributes, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, Tag.defaultAttributes, attributes)); } protected render() { diff --git a/packages/vrender-components/src/title/title.ts b/packages/vrender-components/src/title/title.ts index c83f1b96d..42746a4c4 100644 --- a/packages/vrender-components/src/title/title.ts +++ b/packages/vrender-components/src/title/title.ts @@ -5,6 +5,7 @@ import type { IGroup, IText, IRichText } from '@visactor/vrender-core'; import { merge, isValid, normalizePadding } from '@visactor/vutils'; import { AbstractComponent } from '../core/base'; import type { TitleAttrs } from './type'; +import type { ComponentOptions } from '../interface'; export class Title extends AbstractComponent> { name = 'title'; @@ -31,8 +32,8 @@ export class Title extends AbstractComponent> { } }; - constructor(attributes: TitleAttrs) { - super(merge({}, Title.defaultAttributes, attributes)); + constructor(attributes: TitleAttrs, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, Title.defaultAttributes, attributes)); } protected render() { diff --git a/packages/vrender-components/src/tooltip/tooltip.ts b/packages/vrender-components/src/tooltip/tooltip.ts index 6bd390e34..120a6cd82 100644 --- a/packages/vrender-components/src/tooltip/tooltip.ts +++ b/packages/vrender-components/src/tooltip/tooltip.ts @@ -10,6 +10,7 @@ import { isVisible } from '../util'; import type { TooltipAttributes, TooltipRowAttrs, TooltipRowStyleAttrs } from './type'; import { getRichTextAttribute, mergeRowAttrs } from './util'; import { defaultAttributes, TOOLTIP_POSITION_ATTRIBUTES } from './config'; +import type { ComponentOptions } from '../interface'; const TOOLTIP_BACKGROUND_NAME = 'tooltip-background'; const TOOLTIP_TITLE_NAME = 'tooltip-title'; @@ -35,8 +36,8 @@ export class Tooltip extends AbstractComponent> { static defaultAttributes: Partial = defaultAttributes; - constructor(attributes: TooltipAttributes) { - super(merge({}, Tooltip.defaultAttributes, attributes)); + constructor(attributes: TooltipAttributes, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, Tooltip.defaultAttributes, attributes), options); } protected render() { From 80a930cc1474ac1c249da2f6591a70ea67b93fa2 Mon Sep 17 00:00:00 2001 From: xile611 Date: Mon, 13 Nov 2023 16:22:50 +0800 Subject: [PATCH 21/40] docs: update changelog of vrender-components --- .../perf-skip-default-attributes_2023-11-13-08-22.json | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 common/changes/@visactor/vrender-components/perf-skip-default-attributes_2023-11-13-08-22.json diff --git a/common/changes/@visactor/vrender-components/perf-skip-default-attributes_2023-11-13-08-22.json b/common/changes/@visactor/vrender-components/perf-skip-default-attributes_2023-11-13-08-22.json new file mode 100644 index 000000000..5c6374c6c --- /dev/null +++ b/common/changes/@visactor/vrender-components/perf-skip-default-attributes_2023-11-13-08-22.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vrender-components", + "comment": "perf: add option `skipDefault` to vrender-components", + "type": "none" + } + ], + "packageName": "@visactor/vrender-components" +} \ No newline at end of file From 165b9f3a9476314a09278ce7ef91c309c03e5fe3 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Mon, 13 Nov 2023 20:29:16 +0800 Subject: [PATCH 22/40] refactor: refact inversify completely, closed #657 --- .../refactor-inversify_2023-11-13-12-30.json | 10 + .../refactor-inversify_2023-11-13-12-30.json | 10 + .../refactor-inversify_2023-11-13-12-30.json | 10 + .../src/allocator/canvas-allocate.ts | 16 +- .../src/common/inversify-lite/index.ts | 60 +-- .../src/common/inversify/annotation/inject.ts | 4 + .../inversify/annotation/inject_base.ts | 66 ++++ .../common/inversify/annotation/injectable.ts | 10 + .../inversify/annotation/multi_inject.ts | 4 + .../src/common/inversify/annotation/named.ts | 7 + .../src/common/inversify/binding.ts | 80 ++++ .../src/common/inversify/container.ts | 274 +++++++++++++ .../src/common/inversify/cotainer-module.ts | 12 + .../src/common/inversify/index.ts | 34 ++ .../src/common/inversify/interfaces.ts | 360 ++++++++++++++++++ .../src/common/inversify/literal_types.ts | 25 ++ .../src/common/inversify/meta-data.ts | 18 + .../src/common/inversify/metadata_keys.ts | 38 ++ .../src/common/inversify/metadata_reader.ts | 27 ++ .../src/common/inversify/reflect-metadata.ts | 0 .../inversify/syntax/binding_in_syntax.ts | 34 ++ .../inversify/syntax/binding_to_syntax.ts | 55 +++ .../inversify/syntax/constraint_helpers.ts | 25 ++ .../vrender-core/src/core/graphic-utils.ts | 12 +- .../src/picker/canvas-picker-service.ts | 2 +- packages/vrender/package.json | 2 +- 26 files changed, 1159 insertions(+), 36 deletions(-) create mode 100644 common/changes/@visactor/vrender-core/refactor-inversify_2023-11-13-12-30.json create mode 100644 common/changes/@visactor/vrender-kits/refactor-inversify_2023-11-13-12-30.json create mode 100644 common/changes/@visactor/vrender/refactor-inversify_2023-11-13-12-30.json create mode 100644 packages/vrender-core/src/common/inversify/annotation/inject.ts create mode 100644 packages/vrender-core/src/common/inversify/annotation/inject_base.ts create mode 100644 packages/vrender-core/src/common/inversify/annotation/injectable.ts create mode 100644 packages/vrender-core/src/common/inversify/annotation/multi_inject.ts create mode 100644 packages/vrender-core/src/common/inversify/annotation/named.ts create mode 100644 packages/vrender-core/src/common/inversify/binding.ts create mode 100644 packages/vrender-core/src/common/inversify/container.ts create mode 100644 packages/vrender-core/src/common/inversify/cotainer-module.ts create mode 100644 packages/vrender-core/src/common/inversify/index.ts create mode 100644 packages/vrender-core/src/common/inversify/interfaces.ts create mode 100644 packages/vrender-core/src/common/inversify/literal_types.ts create mode 100644 packages/vrender-core/src/common/inversify/meta-data.ts create mode 100644 packages/vrender-core/src/common/inversify/metadata_keys.ts create mode 100644 packages/vrender-core/src/common/inversify/metadata_reader.ts create mode 100644 packages/vrender-core/src/common/inversify/reflect-metadata.ts create mode 100644 packages/vrender-core/src/common/inversify/syntax/binding_in_syntax.ts create mode 100644 packages/vrender-core/src/common/inversify/syntax/binding_to_syntax.ts create mode 100644 packages/vrender-core/src/common/inversify/syntax/constraint_helpers.ts diff --git a/common/changes/@visactor/vrender-core/refactor-inversify_2023-11-13-12-30.json b/common/changes/@visactor/vrender-core/refactor-inversify_2023-11-13-12-30.json new file mode 100644 index 000000000..3453dd969 --- /dev/null +++ b/common/changes/@visactor/vrender-core/refactor-inversify_2023-11-13-12-30.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vrender-core", + "comment": "refactor: refact inversify completely, closed #657", + "type": "none" + } + ], + "packageName": "@visactor/vrender-core" +} \ No newline at end of file diff --git a/common/changes/@visactor/vrender-kits/refactor-inversify_2023-11-13-12-30.json b/common/changes/@visactor/vrender-kits/refactor-inversify_2023-11-13-12-30.json new file mode 100644 index 000000000..15bdc752c --- /dev/null +++ b/common/changes/@visactor/vrender-kits/refactor-inversify_2023-11-13-12-30.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vrender-kits", + "comment": "refactor: refact inversify completely, closed #657", + "type": "none" + } + ], + "packageName": "@visactor/vrender-kits" +} \ No newline at end of file diff --git a/common/changes/@visactor/vrender/refactor-inversify_2023-11-13-12-30.json b/common/changes/@visactor/vrender/refactor-inversify_2023-11-13-12-30.json new file mode 100644 index 000000000..5824c1412 --- /dev/null +++ b/common/changes/@visactor/vrender/refactor-inversify_2023-11-13-12-30.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vrender", + "comment": "refactor: refact inversify completely, closed #657", + "type": "none" + } + ], + "packageName": "@visactor/vrender" +} \ No newline at end of file diff --git a/packages/vrender-core/src/allocator/canvas-allocate.ts b/packages/vrender-core/src/allocator/canvas-allocate.ts index 8d3883c9e..e6b0d236d 100644 --- a/packages/vrender-core/src/allocator/canvas-allocate.ts +++ b/packages/vrender-core/src/allocator/canvas-allocate.ts @@ -5,6 +5,14 @@ import { wrapCanvas } from '../canvas/util'; export class DefaultCanvasAllocate implements IAllocate, Releaseable { protected pools: ICanvas[] = []; protected _commonCanvas: any; + // 已经被分配出去的canvas + protected allocatedCanvas: ICanvas[] = []; + shareCanvas(): ICanvas { + if (this.allocatedCanvas.length) { + return this.allocatedCanvas[0]; + } + return this.getCommonCanvas(); + } getCommonCanvas(): ICanvas { if (!this._commonCanvas) { this._commonCanvas = this.allocate({ width: 100, height: 100, dpr: 2 }); @@ -13,10 +21,12 @@ export class DefaultCanvasAllocate implements IAllocate, Releaseable { } allocate(data: { width: number; height: number; dpr: number }): ICanvas { if (!this.pools.length) { - return wrapCanvas({ + const c = wrapCanvas({ nativeCanvas: application.global.createCanvas(data), ...data }); + this.allocatedCanvas.push(c); + return c; } const m = this.pools.pop(); m.resize(data.width, data.height); @@ -30,10 +40,12 @@ export class DefaultCanvasAllocate implements IAllocate, Releaseable { height: canvas.height / canvas.dpr, dpr: canvas.dpr }; - return wrapCanvas({ + const c = wrapCanvas({ nativeCanvas: application.global.createCanvas(data), ...data }); + this.allocatedCanvas.push(c); + return c; } const m = this.pools.pop(); m.width = canvas.width; diff --git a/packages/vrender-core/src/common/inversify-lite/index.ts b/packages/vrender-core/src/common/inversify-lite/index.ts index 8dcc137eb..238b0b0d1 100644 --- a/packages/vrender-core/src/common/inversify-lite/index.ts +++ b/packages/vrender-core/src/common/inversify-lite/index.ts @@ -1,34 +1,36 @@ -/** - * 该文件夹下所有文件来源于inversify - * https://github.com/inversify/InversifyJS - * The MIT License (MIT) +// /** +// * 该文件夹下所有文件来源于inversify +// * https://github.com/inversify/InversifyJS +// * The MIT License (MIT) -Copyright (c) 2015-2017 Remo H. Jansen +// Copyright (c) 2015-2017 Remo H. Jansen -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - */ +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// */ -export { ContainerModule } from './container/container_module'; -export { inject } from './annotation/inject'; -export { multiInject } from './annotation/multi_inject'; -export { injectable } from './annotation/injectable'; -export { named } from './annotation/named'; -export { Container } from './container/container'; -// export { postConstruct } from './annotation/post_construct'; -export * from './interfaces/interfaces'; +// export { ContainerModule } from './container/container_module'; +// export { inject } from './annotation/inject'; +// export { multiInject } from './annotation/multi_inject'; +// export { injectable } from './annotation/injectable'; +// export { named } from './annotation/named'; +// export { Container } from './container/container'; +// // export { postConstruct } from './annotation/post_construct'; +// export * from './interfaces/interfaces'; + +export * from '../inversify'; diff --git a/packages/vrender-core/src/common/inversify/annotation/inject.ts b/packages/vrender-core/src/common/inversify/annotation/inject.ts new file mode 100644 index 000000000..aedac40a1 --- /dev/null +++ b/packages/vrender-core/src/common/inversify/annotation/inject.ts @@ -0,0 +1,4 @@ +import { INJECT_TAG } from '../metadata_keys'; +import { injectBase } from './inject_base'; + +export const inject = injectBase(INJECT_TAG); diff --git a/packages/vrender-core/src/common/inversify/annotation/inject_base.ts b/packages/vrender-core/src/common/inversify/annotation/inject_base.ts new file mode 100644 index 000000000..94ef42405 --- /dev/null +++ b/packages/vrender-core/src/common/inversify/annotation/inject_base.ts @@ -0,0 +1,66 @@ +import { Metadata } from '../meta-data'; +import { TAGGED } from '../metadata_keys'; + +function _tagParameterOrProperty( + metadataKey: string, + annotationTarget: NewableFunction, + key: string | symbol, + metadata: Metadata +) { + const metadatas: Metadata[] = [metadata]; + + let paramsOrPropertiesMetadata: Record = {}; + // read metadata if available + if ((Reflect as any).hasOwnMetadata(metadataKey, annotationTarget)) { + paramsOrPropertiesMetadata = (Reflect as any).getMetadata(metadataKey, annotationTarget); + } + + let paramOrPropertyMetadata: Metadata[] | undefined = paramsOrPropertiesMetadata[key as string]; + + if (paramOrPropertyMetadata === undefined) { + paramOrPropertyMetadata = []; + } + + // set metadata + paramOrPropertyMetadata.push(...metadatas); + paramsOrPropertiesMetadata[key] = paramOrPropertyMetadata; + (Reflect as any).defineMetadata(metadataKey, paramsOrPropertiesMetadata, annotationTarget); +} + +function tagParameter( + annotationTarget: DecoratorTarget, + parameterName: string | symbol | undefined, + parameterIndex: number, + metadata: Metadata +) { + _tagParameterOrProperty(TAGGED, annotationTarget as ConstructorFunction, parameterIndex.toString(), metadata); +} + +export function createTaggedDecorator(metadata: Metadata) { + return (target: DecoratorTarget, targetKey?: string | symbol, indexOrPropertyDescriptor?: number) => { + tagParameter(target, targetKey, indexOrPropertyDescriptor, metadata); + }; +} + +type Prototype = { + [Property in keyof T]: T[Property] extends NewableFunction ? T[Property] : T[Property] | undefined; +} & { constructor: NewableFunction }; + +interface ConstructorFunction> { + new (...args: unknown[]): T; + prototype: Prototype; +} + +export type DecoratorTarget = ConstructorFunction | Prototype; + +export function injectBase(metadataKey: string) { + return (serviceIdentifier: any) => { + return (target: DecoratorTarget, targetKey?: string | symbol, indexOrPropertyDescriptor?: number) => { + return createTaggedDecorator(new Metadata(metadataKey, serviceIdentifier))( + target, + targetKey, + indexOrPropertyDescriptor + ); + }; + }; +} diff --git a/packages/vrender-core/src/common/inversify/annotation/injectable.ts b/packages/vrender-core/src/common/inversify/annotation/injectable.ts new file mode 100644 index 000000000..852a23a7c --- /dev/null +++ b/packages/vrender-core/src/common/inversify/annotation/injectable.ts @@ -0,0 +1,10 @@ +import * as METADATA_KEY from '../metadata_keys'; +import Reflect from '../../Reflect-metadata'; + +export function injectable() { + return function unknown>(target: T) { + (Reflect as any).defineMetadata(METADATA_KEY.PARAM_TYPES, null, target); + + return target; + }; +} diff --git a/packages/vrender-core/src/common/inversify/annotation/multi_inject.ts b/packages/vrender-core/src/common/inversify/annotation/multi_inject.ts new file mode 100644 index 000000000..ffdf022e5 --- /dev/null +++ b/packages/vrender-core/src/common/inversify/annotation/multi_inject.ts @@ -0,0 +1,4 @@ +import { MULTI_INJECT_TAG } from '../metadata_keys'; +import { injectBase } from './inject_base'; + +export const multiInject = injectBase(MULTI_INJECT_TAG); diff --git a/packages/vrender-core/src/common/inversify/annotation/named.ts b/packages/vrender-core/src/common/inversify/annotation/named.ts new file mode 100644 index 000000000..59fdba734 --- /dev/null +++ b/packages/vrender-core/src/common/inversify/annotation/named.ts @@ -0,0 +1,7 @@ +import { Metadata } from '../meta-data'; +import { NAMED_TAG } from '../metadata_keys'; +import { createTaggedDecorator } from './inject_base'; + +export function named(name: string | number | symbol) { + return createTaggedDecorator(new Metadata(NAMED_TAG, name)); +} diff --git a/packages/vrender-core/src/common/inversify/binding.ts b/packages/vrender-core/src/common/inversify/binding.ts new file mode 100644 index 000000000..bc0c9a4d0 --- /dev/null +++ b/packages/vrender-core/src/common/inversify/binding.ts @@ -0,0 +1,80 @@ +import { Generator } from '../generator'; +import type { interfaces } from './interfaces'; +import { BindingScopeEnum, BindingTypeEnum } from './literal_types'; + +class Binding implements interfaces.Binding { + id: number; + moduleId!: interfaces.ContainerModuleBase['id']; + + // Determines weather the bindings has been already activated + // The activation action takes place when an instance is resolved + // If the scope is singleton it only happens once + activated: boolean; + + // A runtime identifier because at runtime we don't have interfaces + serviceIdentifier: interfaces.ServiceIdentifier; + + // constructor from binding to or toConstructor + implementationType: interfaces.Newable | TActivated | null; + + // Cache used to allow singleton scope and BindingType.ConstantValue bindings + cache: TActivated | null; + + // Cache used to allow BindingType.DynamicValue bindings + dynamicValue: interfaces.DynamicValue | null; + + // The scope mode to be used + scope: interfaces.BindingScope; + + // The kind of binding + type: interfaces.BindingType; + + // A factory method used in BindingType.Factory bindings + factory: interfaces.FactoryCreator | null; + + // An async factory method used in BindingType.Provider bindings + provider: interfaces.ProviderCreator | null; + + // A constraint used to limit the contexts in which this binding is applicable + constraint: interfaces.ConstraintFunction; + + // // On activation handler (invoked just before an instance is added to cache and injected) + // onActivation: interfaces.BindingActivation | null; + + // // On deactivation handler (invoked just before an instance is unbinded and removed from container) + // onDeactivation: interfaces.BindingDeactivation | null; + + constructor(serviceIdentifier: interfaces.ServiceIdentifier, scope: interfaces.BindingScope) { + this.id = Generator.GenAutoIncrementId(); + this.activated = false; + this.serviceIdentifier = serviceIdentifier; + this.scope = scope; + this.type = BindingTypeEnum.Invalid; + this.constraint = (request: interfaces.Request | null) => true; + this.implementationType = null; + this.cache = null; + this.factory = null; + this.provider = null; + // this.onActivation = null; + // this.onDeactivation = null; + this.dynamicValue = null; + } + + clone(): interfaces.Binding { + const clone = new Binding(this.serviceIdentifier, this.scope); + clone.activated = clone.scope === BindingScopeEnum.Singleton ? this.activated : false; + clone.implementationType = this.implementationType; + clone.dynamicValue = this.dynamicValue; + clone.scope = this.scope; + clone.type = this.type; + // clone.factory = this.factory; + clone.provider = this.provider; + clone.constraint = this.constraint; + // clone.onActivation = this.onActivation; + // clone.onDeactivation = this.onDeactivation; + clone.cache = this.cache; + return clone; + } +} + +export { Binding }; diff --git a/packages/vrender-core/src/common/inversify/container.ts b/packages/vrender-core/src/common/inversify/container.ts new file mode 100644 index 000000000..239780f84 --- /dev/null +++ b/packages/vrender-core/src/common/inversify/container.ts @@ -0,0 +1,274 @@ +import { Generator } from '../generator'; +import { Binding } from './binding'; +import type { interfaces } from './interfaces'; +import { BindingScopeEnum, BindingTypeEnum } from './literal_types'; +import { Metadata } from './meta-data'; +import { INJECT_TAG, MULTI_INJECT_TAG, NAMED_TAG } from './metadata_keys'; +import { MetadataReader } from './metadata_reader'; +import { BindingToSyntax } from './syntax/binding_to_syntax'; + +interface IChildRequest { + injectIdentifier: any; + metadata: interfaces.Metadata[]; + bindings: Binding[]; +} + +interface GetArgs { + avoidConstraints: boolean; + isMultiInject: boolean; + serviceIdentifier: interfaces.ServiceIdentifier; + key: string | symbol; + value: any; +} + +export class Container { + id: number; + readonly options: interfaces.ContainerOptions; + private _bindingDictionary: Map[]>; + private _metadataReader: interfaces.MetadataReader; + + constructor(containerOptions?: interfaces.ContainerOptions) { + const options = containerOptions || {}; + options.defaultScope = options.defaultScope || BindingScopeEnum.Transient; + // console.log(this); + this.options = options; + this.id = Generator.GenAutoIncrementId(); + this._bindingDictionary = new Map(); + this._metadataReader = new MetadataReader(); + } + + load(module: interfaces.ContainerModule) { + const getHelpers = this._getContainerModuleHelpersFactory(); + + const containerModuleHelpers = getHelpers(module.id); + + module.registry( + containerModuleHelpers.bindFunction as interfaces.Bind, + containerModuleHelpers.unbindFunction, + containerModuleHelpers.isboundFunction, + containerModuleHelpers.rebindFunction as interfaces.Rebind + ); + } + + get(serviceIdentifier: interfaces.ServiceIdentifier): T { + const getArgs = this._getNotAllArgs(serviceIdentifier, false); + + return this._get(getArgs) as T; + } + + getAll(serviceIdentifier: interfaces.ServiceIdentifier): T[] { + const getArgs = this._getAllArgs(serviceIdentifier); + + return this._get(getArgs) as T[]; + } + + getTagged(serviceIdentifier: interfaces.ServiceIdentifier, key: string | number | symbol, value: unknown): T { + const getArgs = this._getNotAllArgs(serviceIdentifier, false, key, value); + + return this._get(getArgs) as T; + } + + getNamed(serviceIdentifier: interfaces.ServiceIdentifier, named: string | number | symbol): T { + return this.getTagged(serviceIdentifier, NAMED_TAG, named); + } + + isBound(serviceIdentifier: interfaces.ServiceIdentifier): boolean { + return this._bindingDictionary.has(serviceIdentifier); + } + + // Registers a type binding + bind(serviceIdentifier: interfaces.ServiceIdentifier): interfaces.BindingToSyntax { + const scope = this.options.defaultScope; + const binding = new Binding(serviceIdentifier, scope); + const list = this._bindingDictionary.get(serviceIdentifier) || []; + list.push(binding); + this._bindingDictionary.set(serviceIdentifier, list); + return new BindingToSyntax(binding); + } + + unbind(serviceIdentifier: interfaces.ServiceIdentifier): void { + this._bindingDictionary.delete(serviceIdentifier); + } + + rebind(serviceIdentifier: interfaces.ServiceIdentifier): interfaces.BindingToSyntax { + this.unbind(serviceIdentifier); + return this.bind(serviceIdentifier); + } + + private _getContainerModuleHelpersFactory() { + const setModuleId = ( + bindingToSyntax: interfaces.BindingToSyntax, + moduleId: interfaces.ContainerModuleBase['id'] + ) => { + // TODO: Implement an internal type `_BindingToSyntax` wherein this member + // can be public. Let `BindingToSyntax` be the presentational type that + // depends on it, and does not expose this member as public. + ( + bindingToSyntax as unknown as { _binding: { moduleId: interfaces.ContainerModuleBase['id'] } } + )._binding.moduleId = moduleId; + }; + + const getBindFunction = + (moduleId: interfaces.ContainerModuleBase['id']) => + (serviceIdentifier: interfaces.ServiceIdentifier) => { + const bindingToSyntax = this.bind(serviceIdentifier); + setModuleId(bindingToSyntax, moduleId); + return bindingToSyntax as BindingToSyntax; + }; + + const getUnbindFunction = () => (serviceIdentifier: interfaces.ServiceIdentifier) => { + return this.unbind(serviceIdentifier); + }; + + const getUnbindAsyncFunction = () => (serviceIdentifier: interfaces.ServiceIdentifier) => { + return null as any; + // return this.unbindAsync(serviceIdentifier); + }; + + const getIsboundFunction = () => (serviceIdentifier: interfaces.ServiceIdentifier) => { + return this.isBound(serviceIdentifier); + }; + + const getRebindFunction = + (moduleId: interfaces.ContainerModuleBase['id']) => + (serviceIdentifier: interfaces.ServiceIdentifier) => { + const bindingToSyntax = this.rebind(serviceIdentifier); + setModuleId(bindingToSyntax, moduleId); + return bindingToSyntax as BindingToSyntax; + }; + return (mId: interfaces.ContainerModuleBase['id']) => ({ + bindFunction: getBindFunction(mId), + isboundFunction: getIsboundFunction(), + rebindFunction: getRebindFunction(mId), + unbindFunction: getUnbindFunction(), + unbindAsyncFunction: getUnbindAsyncFunction() + }); + } + + private _getNotAllArgs( + serviceIdentifier: interfaces.ServiceIdentifier, + isMultiInject: boolean, + key?: string | number | symbol | undefined, + value?: unknown + ): any { + return { + avoidConstraints: false, + isMultiInject, + serviceIdentifier, + key, + value + }; + } + + private _getAllArgs(serviceIdentifier: interfaces.ServiceIdentifier): any { + return { + avoidConstraints: true, + isMultiInject: true, + serviceIdentifier + }; + } + + private _get(getArgs: GetArgs): T | T[] { + const result: T[] = []; + const bindings = this._bindingDictionary.get(getArgs.serviceIdentifier) as Binding[]; + bindings.forEach(binding => { + result.push(this._resolveFromBinding(binding)); + }); + + return !getArgs.isMultiInject && result.length === 1 ? result[0] : result; + } + + private _getChildRequest(binding: Binding) { + const constr = binding.implementationType; + const { userGeneratedMetadata } = this._metadataReader.getConstructorMetadata(constr as any); + const keys = Object.keys(userGeneratedMetadata); + const arr = []; + for (let i = 0; i < keys.length; i++) { + const constructorArgsMetadata = userGeneratedMetadata[i]; + const targetMetadataMap = {}; + constructorArgsMetadata.forEach(md => { + targetMetadataMap[md.key] = md.value; + }); + const metadata = { + inject: targetMetadataMap[INJECT_TAG], + multiInject: targetMetadataMap[MULTI_INJECT_TAG] + }; + const injectIdentifier = metadata.inject || metadata.multiInject; + const target = { + serviceIdentifier: injectIdentifier, + constructorArgsMetadata + }; + const bindings = this._bindingDictionary.get(injectIdentifier).filter(b => { + return b.constraint(target as any); + }); + const request = { + injectIdentifier, + metadata: constructorArgsMetadata, + bindings + }; + + arr.push(request); + } + + return arr; + } + + private _resolveFromBinding(binding: Binding): T { + const result = this._getResolvedFromBinding(binding); + + this._saveToScope(binding, result); + + return result; + } + + private _getResolvedFromBinding(binding: Binding) { + let result: T; + switch (binding.type) { + case BindingTypeEnum.ConstantValue: + case BindingTypeEnum.Function: + result = binding.cache as T; + break; + case BindingTypeEnum.Instance: + result = this._resolveInstance(binding, binding.implementationType as interfaces.Newable); + break; + default: + result = binding.dynamicValue({ container: this } as any); + } + + return result; + } + + private _resolveInstance(binding: Binding, constr: interfaces.Newable): T { + if (binding.activated) { + return binding.cache; + } + + const childRequests = this._getChildRequest(binding); + return this._createInstance(constr, childRequests); + } + + private _createInstance(constr: interfaces.Newable, childRequests: IChildRequest[]) { + if (childRequests.length) { + const resolved = this._resolveRequests(childRequests); + const obj = new constr(...resolved); + return obj; + } + const obj = new constr(); + return obj; + } + + private _resolveRequests(childRequests: IChildRequest[]): any[] { + return childRequests.map(request => { + return request.bindings.length > 1 + ? request.bindings.map(binding => this._resolveFromBinding(binding)) + : this._resolveFromBinding(request.bindings[0]); + }); + } + + private _saveToScope(binding: Binding, result: any) { + if (binding.scope === BindingScopeEnum.Singleton) { + binding.cache = result; + binding.activated = true; + } + } +} diff --git a/packages/vrender-core/src/common/inversify/cotainer-module.ts b/packages/vrender-core/src/common/inversify/cotainer-module.ts new file mode 100644 index 000000000..bfb05bfb7 --- /dev/null +++ b/packages/vrender-core/src/common/inversify/cotainer-module.ts @@ -0,0 +1,12 @@ +import { Generator } from '../generator'; +import type { interfaces } from '../inversify-lite'; + +export class ContainerModule { + id: number; + registry: interfaces.ContainerModuleCallBack; + + constructor(registry: interfaces.ContainerModuleCallBack) { + this.id = Generator.GenAutoIncrementId(); + this.registry = registry; + } +} diff --git a/packages/vrender-core/src/common/inversify/index.ts b/packages/vrender-core/src/common/inversify/index.ts new file mode 100644 index 000000000..f1081a318 --- /dev/null +++ b/packages/vrender-core/src/common/inversify/index.ts @@ -0,0 +1,34 @@ +/** + * 该文件夹下所有文件来源于inversify + * https://github.com/inversify/InversifyJS + * The MIT License (MIT) + +Copyright (c) 2015-2017 Remo H. Jansen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + */ + +export { ContainerModule } from './cotainer-module'; +export { inject } from './annotation/inject'; +export { multiInject } from './annotation/multi_inject'; +export { injectable } from './annotation/injectable'; +export { named } from './annotation/named'; +export { Container } from './container'; +// export { postConstruct } from './annotation/post_construct'; +export * from './interfaces'; diff --git a/packages/vrender-core/src/common/inversify/interfaces.ts b/packages/vrender-core/src/common/inversify/interfaces.ts new file mode 100644 index 000000000..213d68b84 --- /dev/null +++ b/packages/vrender-core/src/common/inversify/interfaces.ts @@ -0,0 +1,360 @@ +// @ts-nocheck +/* eslint-disable */ +import { FactoryType } from '../utils/factory_type'; + +export namespace interfaces { + export type DynamicValue = (context: interfaces.Context) => T; + export type ContainerResolution = T | Promise | (T | Promise)[]; + + export type BindingScope = 'Singleton' | 'Transient' | 'Request'; + + export type BindingType = + | 'ConstantValue' + | 'Constructor' + | 'DynamicValue' + | 'Factory' + | 'Function' + | 'Instance' + | 'Invalid' + | 'Provider'; + + export type TargetType = 'ConstructorArgument' | 'ClassProperty' | 'Variable'; + + export interface BindingScopeEnum { + Singleton: interfaces.BindingScope; + Transient: interfaces.BindingScope; + } + + export interface BindingTypeEnum { + ConstantValue: interfaces.BindingType; + Constructor: interfaces.BindingType; + DynamicValue: interfaces.BindingType; + Factory: interfaces.BindingType; + Function: interfaces.BindingType; + Instance: interfaces.BindingType; + Invalid: interfaces.BindingType; + Provider: interfaces.BindingType; + } + + export interface TargetTypeEnum { + ConstructorArgument: interfaces.TargetType; + ClassProperty: interfaces.TargetType; + Variable: interfaces.TargetType; + } + + export type Newable = new (...args: any[]) => T; + + export type Instance = T & Record void>; + + export interface Abstract { + prototype: T; + } + + export type ServiceIdentifier = string | symbol | Newable | Abstract; + + export interface Clonable { + clone(): T; + } + + export type BindingActivation = (context: interfaces.Context, injectable: T) => T | Promise; + + export type BindingDeactivation = (injectable: T) => void | Promise; + + export interface Binding extends Clonable> { + id: number; + moduleId: ContainerModuleBase['id']; + activated: boolean; + serviceIdentifier: ServiceIdentifier; + constraint: ConstraintFunction; + dynamicValue: DynamicValue | null; + scope: BindingScope; + type: BindingType; + implementationType: Newable | TActivated | null; + factory: FactoryCreator | null; + provider: ProviderCreator | null; + // onActivation: BindingActivation | null; + // onDeactivation: BindingDeactivation | null; + cache: null | TActivated | Promise; + } + + export type SimpleFactory = (...args: U) => T; + + export type MultiFactory = ( + ...args: U + ) => SimpleFactory; + + export type Factory = + | SimpleFactory + | MultiFactory; + + export type FactoryCreator = ( + context: Context + ) => Factory; + + export type AutoNamedFactory = SimpleFactory; + + export type AutoFactory = SimpleFactory; + + export type FactoryTypeFunction = (context: interfaces.Context) => T | Promise; + + export interface FactoryDetails { + factoryType: FactoryType; + factory: FactoryTypeFunction | null; + } + + export type Provider = (...args: any[]) => ((...args: any[]) => Promise) | Promise; + + export type ProviderCreator = (context: Context) => Provider; + + export interface NextArgs { + avoidConstraints: boolean; + contextInterceptor: (contexts: Context) => Context; + isMultiInject: boolean; + targetType: TargetType; + serviceIdentifier: interfaces.ServiceIdentifier; + key?: string | number | symbol | undefined; + value?: unknown; + } + + export type Next = (args: NextArgs) => unknown | unknown[]; + + export type Middleware = (next: Next) => Next; + + export type ContextInterceptor = (context: interfaces.Context) => interfaces.Context; + + export interface Context { + id: number; + container: Container; + plan: Plan; + currentRequest: Request; + addPlan(plan: Plan): void; + setCurrentRequest(request: Request): void; + } + + export type MetadataOrMetadataArray = Metadata | Metadata[]; + + export interface Metadata { + key: string | number | symbol; + value: TValue; + } + + export interface Plan { + parentContext: Context; + rootRequest: Request; + } + + export interface QueryableString { + // startsWith(searchString: string): boolean; + // endsWith(searchString: string): boolean; + contains(searchString: string): boolean; + equals(compareString: string): boolean; + value(): string; + } + + export type ResolveRequestHandler = (request: interfaces.Request) => unknown; + + export type RequestScope = Map; + + export interface Request { + id: number; + serviceIdentifier: ServiceIdentifier; + parentContext: Context; + parentRequest: Request | null; + childRequests: Request[]; + target: Target; + bindings: Binding[]; + requestScope: RequestScope | null; + addChildRequest( + serviceIdentifier: ServiceIdentifier, + bindings: Binding | Binding[], + target: Target + ): Request; + } + + export interface Target { + id: number; + serviceIdentifier: ServiceIdentifier; + type: TargetType; + name: QueryableString; + identifier: string | symbol; + metadata: Metadata[]; + getNamedTag(): interfaces.Metadata | null; + getCustomTags(): interfaces.Metadata[] | null; + hasTag(key: string | number | symbol): boolean; + isArray(): boolean; + matchesArray(name: interfaces.ServiceIdentifier): boolean; + isNamed(): boolean; + isTagged(): boolean; + isOptional(): boolean; + matchesNamedTag(name: string): boolean; + matchesTag(key: string | number | symbol): (value: unknown) => boolean; + } + + export interface ContainerOptions { + autoBindInjectable?: boolean; + defaultScope?: BindingScope | undefined; + skipBaseClassChecks?: boolean; + } + + export interface Container { + id: number; + parent: Container | null; + options: ContainerOptions; + bind(serviceIdentifier: ServiceIdentifier): BindingToSyntax; + rebind(serviceIdentifier: interfaces.ServiceIdentifier): interfaces.BindingToSyntax; + // rebindAsync(serviceIdentifier: interfaces.ServiceIdentifier): Promise>; + unbind(serviceIdentifier: ServiceIdentifier): void; + // unbindAsync(serviceIdentifier: interfaces.ServiceIdentifier): Promise; + unbindAll(): void; + // unbindAllAsync(): Promise; + isBound(serviceIdentifier: ServiceIdentifier): boolean; + isCurrentBound(serviceIdentifier: ServiceIdentifier): boolean; + isBoundNamed(serviceIdentifier: ServiceIdentifier, named: string | number | symbol): boolean; + isBoundTagged(serviceIdentifier: ServiceIdentifier, key: string | number | symbol, value: unknown): boolean; + get(serviceIdentifier: ServiceIdentifier): T; + getNamed(serviceIdentifier: ServiceIdentifier, named: string | number | symbol): T; + getTagged(serviceIdentifier: ServiceIdentifier, key: string | number | symbol, value: unknown): T; + getAll(serviceIdentifier: ServiceIdentifier): T[]; + getAllTagged(serviceIdentifier: ServiceIdentifier, key: string | number | symbol, value: unknown): T[]; + getAllNamed(serviceIdentifier: ServiceIdentifier, named: string | number | symbol): T[]; + getAsync(serviceIdentifier: ServiceIdentifier): Promise; + // getNamedAsync(serviceIdentifier: ServiceIdentifier, named: string | number | symbol): Promise; + // getTaggedAsync( + // serviceIdentifier: ServiceIdentifier, + // key: string | number | symbol, + // value: unknown + // ): Promise; + // getAllAsync(serviceIdentifier: ServiceIdentifier): Promise; + // getAllTaggedAsync( + // serviceIdentifier: ServiceIdentifier, + // key: string | number | symbol, + // value: unknown + // ): Promise; + // getAllNamedAsync(serviceIdentifier: ServiceIdentifier, named: string | number | symbol): Promise; + // onActivation(serviceIdentifier: ServiceIdentifier, onActivation: BindingActivation): void; + // onDeactivation(serviceIdentifier: ServiceIdentifier, onDeactivation: BindingDeactivation): void; + resolve(constructorFunction: interfaces.Newable): T; + load(...modules: ContainerModule[]): void; + // loadAsync(...modules: AsyncContainerModule[]): Promise; + unload(...modules: ContainerModuleBase[]): void; + // unloadAsync(...modules: ContainerModuleBase[]): Promise; + applyCustomMetadataReader(metadataReader: MetadataReader): void; + // applyMiddleware(...middleware: Middleware[]): void; + // snapshot(): void; + // restore(): void; + // createChild(): Container; + } + + export type Bind = (serviceIdentifier: ServiceIdentifier) => BindingToSyntax; + + export type Rebind = (serviceIdentifier: ServiceIdentifier) => BindingToSyntax; + + export type Unbind = (serviceIdentifier: ServiceIdentifier) => void; + + export type UnbindAsync = (serviceIdentifier: ServiceIdentifier) => Promise; + + export type IsBound = (serviceIdentifier: ServiceIdentifier) => boolean; + + export interface ContainerModuleBase { + id: number; + } + + export interface ContainerModule extends ContainerModuleBase { + registry: ContainerModuleCallBack; + } + + export interface ModuleActivationHandlers { + onActivations: Lookup>; + onDeactivations: Lookup>; + } + + // export interface ModuleActivationStore extends Clonable { + // addDeactivation( + // moduleId: ContainerModuleBase['id'], + // serviceIdentifier: ServiceIdentifier, + // onDeactivation: interfaces.BindingDeactivation + // ): void; + // addActivation( + // moduleId: ContainerModuleBase['id'], + // serviceIdentifier: ServiceIdentifier, + // onActivation: interfaces.BindingActivation + // ): void; + // remove(moduleId: ContainerModuleBase['id']): ModuleActivationHandlers; + // } + + export type ContainerModuleCallBack = ( + bind: interfaces.Bind, + unbind: interfaces.Unbind, + isBound: interfaces.IsBound, + rebind: interfaces.Rebind + // unbindAsync: interfaces.UnbindAsync, + // onActivation: interfaces.Container['onActivation'], + // onDeactivation: interfaces.Container['onDeactivation'] + ) => void; + + // export interface ContainerSnapshot { + // bindings: Lookup>; + // activations: Lookup>; + // deactivations: Lookup>; + // middleware: Next | null; + // moduleActivationStore: interfaces.ModuleActivationStore; + // } + + export interface Lookup extends Clonable> { + add(serviceIdentifier: ServiceIdentifier, value: T): void; + getMap(): Map; + get(serviceIdentifier: ServiceIdentifier): T[]; + remove(serviceIdentifier: interfaces.ServiceIdentifier): void; + removeByCondition(condition: (item: T) => boolean): T[]; + removeIntersection(lookup: interfaces.Lookup): void; + hasKey(serviceIdentifier: ServiceIdentifier): boolean; + clone(): Lookup; + traverse(func: (key: interfaces.ServiceIdentifier, value: T[]) => void): void; + } + + export interface BindingOnSyntax { + // onActivation(fn: (context: Context, injectable: T) => T | Promise): BindingWhenSyntax; + // onDeactivation(fn: (injectable: T) => void | Promise): BindingWhenSyntax; + } + + // export interface BindingWhenOnSyntax extends BindingWhenSyntax, BindingOnSyntax {} + + export interface BindingInSyntax { + inSingletonScope(): BindingInSyntax; + inTransientScope(): BindingInSyntax; + whenTargetNamed(name: string | number | symbol): BindingOnSyntax; + // inRequestScope(): BindingInSyntax; + } + + export interface BindingInWhenOnSyntax extends BindingInSyntax, BindingInSyntax {} + + export interface BindingToSyntax { + to(constructor: Newable): BindingInWhenOnSyntax; + toSelf(): BindingInWhenOnSyntax; + toConstantValue(value: T): BindingInWhenOnSyntax; + toDynamicValue(func: DynamicValue): BindingInWhenOnSyntax; + toFactory( + factory: FactoryCreator + ): BindingInWhenOnSyntax; + toService(service: ServiceIdentifier): void; + } + + export interface ConstraintFunction { + metaData?: Metadata; + (request: Request | null): boolean; + } + + export interface MetadataReader { + getConstructorMetadata(constructorFunc: NewableFunction): ConstructorMetadata; + getPropertiesMetadata(constructorFunc: NewableFunction): MetadataMap; + } + + export interface MetadataMap { + [propertyNameOrArgumentIndex: string | symbol]: Metadata[]; + } + + export interface ConstructorMetadata { + compilerGeneratedMetadata: NewableFunction[] | undefined; + userGeneratedMetadata: MetadataMap; + } +} diff --git a/packages/vrender-core/src/common/inversify/literal_types.ts b/packages/vrender-core/src/common/inversify/literal_types.ts new file mode 100644 index 000000000..8247bbf17 --- /dev/null +++ b/packages/vrender-core/src/common/inversify/literal_types.ts @@ -0,0 +1,25 @@ +import type { interfaces } from './interfaces'; + +const BindingScopeEnum: interfaces.BindingScopeEnum = { + Singleton: 'Singleton', + Transient: 'Transient' +}; + +const BindingTypeEnum: interfaces.BindingTypeEnum = { + ConstantValue: 'ConstantValue', + Constructor: 'Constructor', + DynamicValue: 'DynamicValue', + Factory: 'Factory', + Function: 'Function', + Instance: 'Instance', + Invalid: 'Invalid', + Provider: 'Provider' +}; + +const TargetTypeEnum: interfaces.TargetTypeEnum = { + ClassProperty: 'ClassProperty', + ConstructorArgument: 'ConstructorArgument', + Variable: 'Variable' +}; + +export { BindingScopeEnum, BindingTypeEnum, TargetTypeEnum }; diff --git a/packages/vrender-core/src/common/inversify/meta-data.ts b/packages/vrender-core/src/common/inversify/meta-data.ts new file mode 100644 index 000000000..3d7d11683 --- /dev/null +++ b/packages/vrender-core/src/common/inversify/meta-data.ts @@ -0,0 +1,18 @@ +import { NAMED_TAG } from './metadata_keys'; + +export class Metadata { + key: string | number | symbol; + value: unknown; + + constructor(key: string | number | symbol, value: unknown) { + this.key = key; + this.value = value; + } + + toString() { + if (this.key === NAMED_TAG) { + return `named: ${String(this.value).toString()} `; + } + return `tagged: { key:${this.key.toString()}, value: ${String(this.value)} }`; + } +} diff --git a/packages/vrender-core/src/common/inversify/metadata_keys.ts b/packages/vrender-core/src/common/inversify/metadata_keys.ts new file mode 100644 index 000000000..678316c06 --- /dev/null +++ b/packages/vrender-core/src/common/inversify/metadata_keys.ts @@ -0,0 +1,38 @@ +// Used for named bindings +export const NAMED_TAG = 'named'; + +// The name of the target at design time +export const NAME_TAG = 'name'; + +// The for unmanaged injections (in base classes when using inheritance) +export const UNMANAGED_TAG = 'unmanaged'; + +// The for optional injections +export const OPTIONAL_TAG = 'optional'; + +// The type of the binding at design time +export const INJECT_TAG = 'inject'; + +// The type of the binding at design type for multi-injections +export const MULTI_INJECT_TAG = 'multi_inject'; + +// used to store constructor arguments tags +export const TAGGED = 'inversify:tagged'; + +// used to store class properties tags +export const TAGGED_PROP = 'inversify:tagged_props'; + +// used to store types to be injected +export const PARAM_TYPES = 'inversify:paramtypes'; + +// used to access design time types +export const DESIGN_PARAM_TYPES = 'design:paramtypes'; + +// used to identify preDestroy functions +export const PRE_DESTROY = 'pre_destroy'; + +function getNonCustomTagKeys(): string[] { + return [INJECT_TAG, MULTI_INJECT_TAG, NAME_TAG, UNMANAGED_TAG, NAMED_TAG, OPTIONAL_TAG]; +} + +export const NON_CUSTOM_TAG_KEYS: string[] = getNonCustomTagKeys(); diff --git a/packages/vrender-core/src/common/inversify/metadata_reader.ts b/packages/vrender-core/src/common/inversify/metadata_reader.ts new file mode 100644 index 000000000..e44d1e319 --- /dev/null +++ b/packages/vrender-core/src/common/inversify/metadata_reader.ts @@ -0,0 +1,27 @@ +import type { interfaces } from './interfaces'; +import Reflect from '../Reflect-metadata'; +import { PARAM_TYPES, TAGGED, TAGGED_PROP } from './metadata_keys'; + +class MetadataReader implements interfaces.MetadataReader { + getConstructorMetadata(constructorFunc: NewableFunction): interfaces.ConstructorMetadata { + // TypeScript compiler generated annotations + const compilerGeneratedMetadata = (Reflect as any).getMetadata(PARAM_TYPES, constructorFunc); + + // User generated constructor annotations + const userGeneratedMetadata = (Reflect as any).getMetadata(TAGGED, constructorFunc); + + return { + compilerGeneratedMetadata, + userGeneratedMetadata: userGeneratedMetadata || {} + }; + } + + getPropertiesMetadata(constructorFunc: NewableFunction): interfaces.MetadataMap { + // // User generated properties annotations + // const userGeneratedMetadata = (Reflect as any).getMetadata(TAGGED_PROP, constructorFunc) || []; + // return userGeneratedMetadata; + throw new Error('暂未实现'); + } +} + +export { MetadataReader }; diff --git a/packages/vrender-core/src/common/inversify/reflect-metadata.ts b/packages/vrender-core/src/common/inversify/reflect-metadata.ts new file mode 100644 index 000000000..e69de29bb diff --git a/packages/vrender-core/src/common/inversify/syntax/binding_in_syntax.ts b/packages/vrender-core/src/common/inversify/syntax/binding_in_syntax.ts new file mode 100644 index 000000000..5c177bc92 --- /dev/null +++ b/packages/vrender-core/src/common/inversify/syntax/binding_in_syntax.ts @@ -0,0 +1,34 @@ +import type { interfaces } from '../interfaces'; +import { BindingScopeEnum } from '../literal_types'; +import { namedConstraint } from './constraint_helpers'; + +class BindingInSyntax implements interfaces.BindingInSyntax { + private _binding: interfaces.Binding; + + constructor(binding: interfaces.Binding) { + this._binding = binding; + } + + inRequestScope(): interfaces.BindingInSyntax { + // this._binding.scope = BindingScopeEnum.Request; + // return new BindingWhenOnSyntax(this._binding); + throw new Error('暂未实现'); + } + + inSingletonScope(): interfaces.BindingInSyntax { + this._binding.scope = BindingScopeEnum.Singleton; + return this; + } + + inTransientScope(): interfaces.BindingInSyntax { + this._binding.scope = BindingScopeEnum.Transient; + return this; + } + + whenTargetNamed(name: string | number | symbol): interfaces.BindingOnSyntax { + this._binding.constraint = namedConstraint(name); + return this; + } +} + +export { BindingInSyntax }; diff --git a/packages/vrender-core/src/common/inversify/syntax/binding_to_syntax.ts b/packages/vrender-core/src/common/inversify/syntax/binding_to_syntax.ts new file mode 100644 index 000000000..55765ef01 --- /dev/null +++ b/packages/vrender-core/src/common/inversify/syntax/binding_to_syntax.ts @@ -0,0 +1,55 @@ +import type { interfaces } from '../interfaces'; +import { BindingScopeEnum, BindingTypeEnum } from '../literal_types'; +import { BindingInSyntax } from './binding_in_syntax'; + +class BindingToSyntax implements interfaces.BindingToSyntax { + // TODO: Implement an internal type `_BindingToSyntax` wherein this member + // can be public. Let `BindingToSyntax` be the presentational type that + // depends on it, and does not expose this member as public. + private _binding: interfaces.Binding; + + constructor(binding: interfaces.Binding) { + this._binding = binding; + } + + to(constructor: interfaces.Newable): interfaces.BindingInWhenOnSyntax { + this._binding.type = BindingTypeEnum.Instance; + this._binding.implementationType = constructor; + return new BindingInSyntax(this._binding); + } + + toSelf(): interfaces.BindingInWhenOnSyntax { + const self = this._binding.serviceIdentifier; + return this.to(self as any); + } + + toDynamicValue(func: interfaces.DynamicValue): interfaces.BindingInWhenOnSyntax { + this._binding.type = BindingTypeEnum.DynamicValue; + this._binding.cache = null; + this._binding.dynamicValue = func; + this._binding.implementationType = null; + return new BindingInSyntax(this._binding); + } + + toConstantValue(value: T): interfaces.BindingInSyntax { + this._binding.type = BindingTypeEnum.ConstantValue; + this._binding.cache = value; + this._binding.dynamicValue = null; + this._binding.implementationType = null; + this._binding.scope = BindingScopeEnum.Singleton; + return new BindingInSyntax(this._binding); + } + + toFactory(factory: interfaces.FactoryCreator): interfaces.BindingInWhenOnSyntax { + this._binding.type = BindingTypeEnum.Factory; + this._binding.factory = factory; + this._binding.scope = BindingScopeEnum.Singleton; + return new BindingInSyntax(this._binding); + } + + toService(service: string | symbol | interfaces.Newable | interfaces.Abstract): void { + this.toDynamicValue(context => context.container.get(service)); + } +} + +export { BindingToSyntax }; diff --git a/packages/vrender-core/src/common/inversify/syntax/constraint_helpers.ts b/packages/vrender-core/src/common/inversify/syntax/constraint_helpers.ts new file mode 100644 index 000000000..f55a83c58 --- /dev/null +++ b/packages/vrender-core/src/common/inversify/syntax/constraint_helpers.ts @@ -0,0 +1,25 @@ +import type { interfaces } from '../interfaces'; +import { Metadata } from '../meta-data'; +import { NAMED_TAG } from '../metadata_keys'; + +const taggedConstraint = (key: string | number | symbol) => (value: unknown) => { + const constraint: interfaces.ConstraintFunction = (request: any) => { + if (request == null || request.constructorArgsMetadata == null) { + return false; + } + const constructorArgsMetadata = request.constructorArgsMetadata; + for (let i = 0; i < constructorArgsMetadata.length; i++) { + if (constructorArgsMetadata[i].key === key && constructorArgsMetadata[i].value === value) { + return true; + } + } + return false; + }; + // request !== null && request.target !== null && request.target.matchesTag(key)(value); + + constraint.metaData = new Metadata(key, value); + + return constraint; +}; + +export const namedConstraint = taggedConstraint(NAMED_TAG); diff --git a/packages/vrender-core/src/core/graphic-utils.ts b/packages/vrender-core/src/core/graphic-utils.ts index 62caec2fb..1c4f27f6a 100644 --- a/packages/vrender-core/src/core/graphic-utils.ts +++ b/packages/vrender-core/src/core/graphic-utils.ts @@ -43,15 +43,20 @@ export class DefaultGraphicUtil implements IGraphicUtil { if (this.configured) { return; } - const canvas = canvasAllocate.getCommonCanvas(); - this.canvas = canvas; - this.context = canvas.getContext('2d'); this.contributions.getContributions().forEach(contribution => { contribution.configure(this, env); }); this.configured = true; } + tryInitCanvas() { + if (!this.canvas) { + const canvas = canvasAllocate.shareCanvas(); + this.canvas = canvas; + this.context = canvas.getContext('2d'); + } + } + bindTextMeasure(tm: ITextMeasure) { this._textMeasure = tm; } @@ -78,6 +83,7 @@ export class DefaultGraphicUtil implements IGraphicUtil { getCanvasForMeasure?: () => any ) { this.configure(this.global, this.global.env); + this.tryInitCanvas(); return new TextMeasure( { defaultFontParams: { diff --git a/packages/vrender-kits/src/picker/canvas-picker-service.ts b/packages/vrender-kits/src/picker/canvas-picker-service.ts index 6a340da7b..20e7f8765 100644 --- a/packages/vrender-kits/src/picker/canvas-picker-service.ts +++ b/packages/vrender-kits/src/picker/canvas-picker-service.ts @@ -85,7 +85,7 @@ export class DefaultCanvasPickerService extends DefaultPickService implements IP // }); // 创建pick canvas - this.pickCanvas = canvasAllocate.getCommonCanvas(); + this.pickCanvas = canvasAllocate.shareCanvas(); this.pickContext = this.pickCanvas.getContext('2d'); } diff --git a/packages/vrender/package.json b/packages/vrender/package.json index cfd50fb46..d598db5ec 100644 --- a/packages/vrender/package.json +++ b/packages/vrender/package.json @@ -17,7 +17,7 @@ "build": "bundle --clean", "build-umd": "bundle --clean -f umd", "dev": "bundle --clean -f es -w", - "start": "vite ./__tests__/browser", + "start": "vite ./__tests__/browser --host", "test": "jest", "test-cov": "jest -w 16 --coverage", "prepublishOnly": "npm run build" From 1261d5fb88061943d2a90ce9dae0fd36784079f0 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Mon, 13 Nov 2023 20:54:02 +0800 Subject: [PATCH 23/40] feat: create event-manager on demand --- packages/vrender-core/package.json | 2 + .../inversify/annotation/inject_base.ts | 1 + .../src/common/inversify/reflect-metadata.ts | 0 packages/vrender-core/src/core/global.ts | 4 ++ .../vrender-core/src/core/graphic-utils.ts | 19 ++++-- packages/vrender-core/src/core/stage.ts | 58 ++++++++++--------- .../__tests__/browser/src/pages/circle.ts | 2 +- .../__tests__/browser/src/pages/text.ts | 22 ++----- packages/vrender/package.json | 2 + 9 files changed, 60 insertions(+), 50 deletions(-) delete mode 100644 packages/vrender-core/src/common/inversify/reflect-metadata.ts diff --git a/packages/vrender-core/package.json b/packages/vrender-core/package.json index 88666c2ea..00fc7e8d4 100644 --- a/packages/vrender-core/package.json +++ b/packages/vrender-core/package.json @@ -19,6 +19,8 @@ "dev": "bundle --clean -f es -w", "start": "vite ./__tests__/browser", "test": "jest", + "test-live": "npm run test-watch __tests__/unit/theme/line.test.ts", + "test-watch": "DEBUG_MODE=1 jest --watch", "test-cov": "jest -w 16 --coverage", "prepublishOnly": "npm run build" }, diff --git a/packages/vrender-core/src/common/inversify/annotation/inject_base.ts b/packages/vrender-core/src/common/inversify/annotation/inject_base.ts index 94ef42405..05763ab96 100644 --- a/packages/vrender-core/src/common/inversify/annotation/inject_base.ts +++ b/packages/vrender-core/src/common/inversify/annotation/inject_base.ts @@ -1,5 +1,6 @@ import { Metadata } from '../meta-data'; import { TAGGED } from '../metadata_keys'; +import Reflect from '../../Reflect-metadata'; function _tagParameterOrProperty( metadataKey: string, diff --git a/packages/vrender-core/src/common/inversify/reflect-metadata.ts b/packages/vrender-core/src/common/inversify/reflect-metadata.ts deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/vrender-core/src/core/global.ts b/packages/vrender-core/src/core/global.ts index 4c81bca64..439e8e4db 100644 --- a/packages/vrender-core/src/core/global.ts +++ b/packages/vrender-core/src/core/global.ts @@ -14,10 +14,13 @@ import type { import { SyncHook } from '../tapable'; import { EnvContribution } from '../constants'; import type { IAABBBoundsLike } from '@visactor/vutils'; +import { container } from '../container'; +import { Generator } from '../common/generator'; const defaultEnv: EnvType = 'browser'; @injectable() export class DefaultGlobal implements IGlobal { + readonly id: number; private _env: EnvType; private _isSafari?: boolean; private _isChrome?: boolean; @@ -117,6 +120,7 @@ export class DefaultGlobal implements IGlobal { @named(EnvContribution) protected readonly contributions: IContributionProvider ) { + this.id = Generator.GenAutoIncrementId(); this.hooks = { onSetEnv: new SyncHook<[EnvType | undefined, EnvType, IGlobal]>(['lastEnv', 'env', 'global']) }; diff --git a/packages/vrender-core/src/core/graphic-utils.ts b/packages/vrender-core/src/core/graphic-utils.ts index 1c4f27f6a..3ee260c3e 100644 --- a/packages/vrender-core/src/core/graphic-utils.ts +++ b/packages/vrender-core/src/core/graphic-utils.ts @@ -13,8 +13,16 @@ import { application } from '../application'; @injectable() export class DefaultGraphicUtil implements IGraphicUtil { - canvas?: ICanvas; - context?: IContext2d | null; + get canvas(): ICanvas { + this.tryInitCanvas(); + return this._canvas; + } + get context(): IContext2d | null { + this.tryInitCanvas(); + return this._context; + } + _canvas?: ICanvas; + _context?: IContext2d | null; _textMeasure: ITextMeasure; configured: boolean; global: IGlobal; @@ -50,10 +58,10 @@ export class DefaultGraphicUtil implements IGraphicUtil { } tryInitCanvas() { - if (!this.canvas) { + if (!this._canvas) { const canvas = canvasAllocate.shareCanvas(); - this.canvas = canvas; - this.context = canvas.getContext('2d'); + this._canvas = canvas; + this._context = canvas.getContext('2d'); } } @@ -83,7 +91,6 @@ export class DefaultGraphicUtil implements IGraphicUtil { getCanvasForMeasure?: () => any ) { this.configure(this.global, this.global.env); - this.tryInitCanvas(); return new TextMeasure( { defaultFontParams: { diff --git a/packages/vrender-core/src/core/stage.ts b/packages/vrender-core/src/core/stage.ts index c59dcb7a5..809f90e3a 100644 --- a/packages/vrender-core/src/core/stage.ts +++ b/packages/vrender-core/src/core/stage.ts @@ -166,7 +166,11 @@ export class Stage extends Group implements IStage { pickerService?: IPickerService; readonly pluginService: IPluginService; readonly layerService: ILayerService; - private readonly eventSystem?: EventSystem; + private _eventSystem?: EventSystem; + private get eventSystem(): EventSystem { + this.tryInitEventSystem(); + return this._eventSystem; + } protected _beforeRender?: (stage: IStage) => void; protected _afterRender?: (stage: IStage) => void; @@ -242,30 +246,6 @@ export class Stage extends Group implements IStage { this.stage = this; this.renderStyle = params.renderStyle; - if (this.global.supportEvent) { - this.eventSystem = new EventSystem({ - targetElement: this.window, - resolution: this.window.dpr || this.global.devicePixelRatio, - rootNode: this as any, - global: this.global, - viewport: { - viewBox: this._viewBox, - get x(): number { - return this.viewBox.x1; - }, - get y(): number { - return this.viewBox.y1; - }, - get width(): number { - return this.viewBox.width(); - }, - get height(): number { - return this.viewBox.height(); - } - } - }); - } - // this.autoRender = params.autoRender; if (params.autoRender) { this.enableAutoRender(); @@ -292,13 +272,39 @@ export class Stage extends Group implements IStage { this.optmize(params.optimize); } + protected tryInitEventSystem() { + if (this.global.supportEvent && !this._eventSystem) { + this._eventSystem = new EventSystem({ + targetElement: this.window, + resolution: this.window.dpr || this.global.devicePixelRatio, + rootNode: this as any, + global: this.global, + viewport: { + viewBox: this._viewBox, + get x(): number { + return this.viewBox.x1; + }, + get y(): number { + return this.viewBox.y1; + }, + get width(): number { + return this.viewBox.width(); + }, + get height(): number { + return this.viewBox.height(); + } + } + }); + } + } + // 优化策略 optmize(params?: IOptimizeType) { this.optmizeRender(params?.skipRenderWithOutRange); } // 优化渲染 - protected optmizeRender(skipRenderWithOutRange: boolean = true) { + protected optmizeRender(skipRenderWithOutRange: boolean = false) { if (!skipRenderWithOutRange) { return; } diff --git a/packages/vrender/__tests__/browser/src/pages/circle.ts b/packages/vrender/__tests__/browser/src/pages/circle.ts index 995512748..e358cee52 100644 --- a/packages/vrender/__tests__/browser/src/pages/circle.ts +++ b/packages/vrender/__tests__/browser/src/pages/circle.ts @@ -1,4 +1,4 @@ -import { createStage, DragNDrop, createCircle, IGraphic } from '@visactor/vrender'; +import { createStage, DragNDrop, createCircle, IGraphic, vglobal } from '@visactor/vrender'; import { colorPools } from '../utils'; import { createGroup } from '@visactor/vrender'; diff --git a/packages/vrender/__tests__/browser/src/pages/text.ts b/packages/vrender/__tests__/browser/src/pages/text.ts index acb24b209..f5c8a9784 100644 --- a/packages/vrender/__tests__/browser/src/pages/text.ts +++ b/packages/vrender/__tests__/browser/src/pages/text.ts @@ -19,7 +19,7 @@ const textStr = '蛋糕吃起来像已经放了很多年似的。那天晚上达力神气活现地在起居室里走来走去,向家人展示他那套新校服。斯梅廷中学的男生制服是棕红色燕尾服,橙色短灯笼裤和一顶叫硬草帽2的扁平草帽。他们还配了一支多节的手杖,趁老师不注意时用来互相打斗,这也许是对未来生活的一种很好的训练吧。弗农姨父看着身穿崭新灯笼裤的达力,他的声音都沙哑了,他说这是他平生感到最自豪的一刻。佩妮姨妈突然哭起来,她说她的宝贝疙瘩已经长大了,长得这么帅,简直让她不能相信。哈利却不敢开口。为了强忍住不笑,他的两条肋骨都快折断了。第二天早上哈利来吃早饭时,发现厨房里有一股难闻的味儿。这气味似乎是从污水池里的一只大铁盆里散发出来的。他去看了一眼,发现一盆灰黑色的水里泡着像破抹布似的东西。「这是什么?」他问佩妮姨妈。她把嘴唇抿紧,每当哈利大胆问问题时,她总是这样。「你的新校服呀。」她说。哈利又朝盆里扫了一眼。「哦,」他说,「我不知道还得泡得这么湿。」「别冒傻气,」佩妮姨妈斥责说,「我把达力的旧衣服染好给你用。等我染好以后,穿起来就会跟别人的一模一样。」哈利对此非常怀疑,但他还是觉得最好不要跟她争论。他坐下来吃早饭时,竭力不去想第一天去石墙中学上学自己会是什么模样,八成像披着大象的旧象皮吧。达力和弗农姨父进来时,都因为哈利那套新校服散发的味道皱起了鼻子。弗农姨父像通常一样打开报纸,达力则把他从不离身的斯梅廷手杖啪的一声放到桌上。他们听到信箱咔哒响了一声,一些信落到大门口的擦脚垫上。「去拿信,达力。」弗农姨父从报纸后边说。「叫哈利去捡。」「哈利去捡。」「达力去捡。」「用你的斯梅廷手杖赶他去捡。」哈利躲闪着斯梅廷手杖,去捡信。擦脚垫上有三样邮件:一封是弗农姨父的姐姐玛姬姑妈寄来的明信片,她现在在怀特岛3度假;另一封是看来像账单的棕色信封;还有一封是寄给哈利的信。哈利把信捡起来,目不转睛地盯着看,心里像有一根很粗的橡皮筋嘣的一声弹了起来,嗡嗡直响。活到现在,从来没有人给他写过信。这封信可能是谁写的呢?他没有朋友,没有另外的亲戚,他没有借书证,因此不会收到图书馆催还图书的通知单。可现在确实有一封信,地址清清楚楚,不会有错:萨里郡小惠金区女贞路4号楼梯下的碗柜哈利波特先生收信封是用厚重的羊皮纸做的,地址是甩翡翠绿的墨水写的。没有贴邮票。哈利用颤抖的手把信封翻转过来,只见上边有一块蜡封、一个盾牌纹章,大写「H」字母的周围圈着一头狮子、一只鹰、一只獾和一条蛇。「小子,快拿过来!」弗农姨父在厨房里喊起来,「你在干什么,在检查邮包有没有炸弹吗?」他开了个玩笑,自己也咯咯地笑开了。哈利回到厨房里,目光一直盯着他的那封信。他把账单和明信片递给弗农姨父,然后坐下来,慢慢拆开他那个黄色的信封。弗农姨父拆开有账单的信封,厌恶地哼了一声,又把明信片轻轻翻转过来。「玛姬病倒了,」他对佩妮姨妈说,「吃了有问题的油螺……」「老爸!」达力突然说,「老爸,哈利收到什么东西了!」哈利刚要打开他那封写在厚重羊皮纸上的信,信却被弗农姨父一把从手中抢过去了。「那是写给我的!」哈利说,想把信夺回来。「谁会给你写信?」弗农姨父讥讽地说,用一只手把信纸抖开,朝它瞥了一眼。他的脸一下子由红变青,比红绿灯变得还快。事情到这里并没结束。几秒钟之内他的脸就变得像灰色的麦片粥一样灰白了。「佩——佩——佩妮!」他气喘吁吁地说。达力想把信抢过来看,可是弗农姨父把信举得老高,他够不着。佩妮姨妈好奇地把信拿过去,刚看第一行,她就好像要晕倒了。她抓住喉咙,噎了一下,像要背过气去。「德思礼!哎呀!我的天……德思礼!」他们俩你看我,我看你,都不说话,似乎忘了哈利和达力还在屋里。达力是不习惯被人冷落的,他用斯梅廷手杖朝他父亲的头上狠狠地敲了一下。「我要看那封信。」他大声说。「我要看。」哈利气呼呼地说,「因为那封信是写给我的。」「你们俩,统统给我出去。」弗农姨父用低沉而沙哑的声音说,把信重新塞到信封里。哈利没有动。「我要我的信!」他大叫说。「让我看!」达力命令说。「出去!」弗农姨父吼了起来,揪住哈利和达力的脖领,把他们俩扔到了走廊里,砰地一'; function performance(stage: any) { - vglobal.measureTextMethod = 'quick'; + // vglobal.measureTextMethod = 'quick'; const textList = new Array(3000).fill(0).map(item => { const start = Math.floor(textStr.length * Math.random()); // return createText({ @@ -49,23 +49,11 @@ function performance(stage: any) { export const page = () => { const graphics: IGraphic[] = []; const t = createText({ + x: 100, + y: 100, fontFamily: 'Arial', - fontSize: 14, - fontWeight: null, - fill: '#000', - textAlign: 'left', - textBaseline: 'top', - lineHeight: 14, - ellipsis: '...', - text: 'US-2019-1357144', - maxLineWidth: 119, - autoWrapText: true, - wordBreak: 'break-word', - heightLimit: 20, - pickable: false, - dx: 0, - x: 16, - y: 12 + text: 'aaa这是aaa', + fill: 'red' }); console.log(t.AABBBounds); graphics.push(t); diff --git a/packages/vrender/package.json b/packages/vrender/package.json index d598db5ec..5fc584b09 100644 --- a/packages/vrender/package.json +++ b/packages/vrender/package.json @@ -20,6 +20,8 @@ "start": "vite ./__tests__/browser --host", "test": "jest", "test-cov": "jest -w 16 --coverage", + "test-live": "npm run test-watch __tests__/unit/theme/line.test.ts", + "test-watch": "DEBUG_MODE=1 jest --watch", "prepublishOnly": "npm run build" }, "dependencies": { From b67c077caad22ba785f078b32a26313f8194ffc7 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Tue, 14 Nov 2023 14:14:04 +0800 Subject: [PATCH 24/40] feat: line support drawLinearLineHighPerformance --- .../contributions/render/line-render.ts | 99 +++++++++++++++++-- 1 file changed, 90 insertions(+), 9 deletions(-) diff --git a/packages/vrender-core/src/render/contributions/render/line-render.ts b/packages/vrender-core/src/render/contributions/render/line-render.ts index a818e30a0..9721d174d 100644 --- a/packages/vrender-core/src/render/contributions/render/line-render.ts +++ b/packages/vrender-core/src/render/contributions/render/line-render.ts @@ -181,6 +181,64 @@ export class DefaultCanvasLineRender extends BaseRender implements IGraph return !!ret; } + // 高性能绘制linear line,不用拆分 + drawLinearLineHighPerformance( + line: ILine, + context: IContext2d, + fill: boolean, + stroke: boolean, + fillOpacity: number, + strokeOpacity: number, + offsetX: number, + offsetY: number, + lineAttribute: Required, + drawContext: IDrawContext, + params?: IGraphicRenderDrawParams, + fillCb?: ( + ctx: IContext2d, + lineAttribute: Partial, + themeAttribute: IThemeAttribute + ) => boolean, + strokeCb?: ( + ctx: IContext2d, + lineAttribute: Partial, + themeAttribute: IThemeAttribute + ) => boolean + ) { + context.beginPath(); + + const z = this.z ?? 0; + const { points } = line.attribute; + const startP = points[0]; + + context.moveTo(startP.x, startP.y, z); + for (let i = 1; i < points.length; i++) { + const p = points[i]; + context.lineTo(p.x, p.y, z); + } + + // shadow + context.setShadowBlendStyle && context.setShadowBlendStyle(line, line.attribute, lineAttribute); + + const { x: originX = 0, x: originY = 0 } = line.attribute; + if (fill !== false) { + if (fillCb) { + fillCb(context, line.attribute, lineAttribute); + } else if (fillOpacity) { + context.setCommonStyle(line, line.attribute, originX - offsetX, originY - offsetY, lineAttribute); + context.fill(); + } + } + if (stroke !== false) { + if (strokeCb) { + strokeCb(context, line.attribute, lineAttribute); + } else if (strokeOpacity) { + context.setStrokeStyle(line, line.attribute, originX - offsetX, originY - offsetY, lineAttribute); + context.stroke(); + } + } + } + drawShape( line: ILine, context: IContext2d, @@ -206,22 +264,48 @@ export class DefaultCanvasLineRender extends BaseRender implements IGraph fill = lineAttribute.fill, stroke = lineAttribute.stroke, fillOpacity = lineAttribute.fillOpacity, - strokeOpacity = lineAttribute.strokeOpacity + strokeOpacity = lineAttribute.strokeOpacity, + segments, + points, + closePath } = line.attribute; const data = this.valid(line, lineAttribute, fillCb, strokeCb); if (!data) { return; } + + let { curveType = lineAttribute.curveType } = line.attribute; + if (closePath && curveType === 'linear') { + curveType = 'linearClosed'; + } + + const { clipRange = lineAttribute.clipRange, clipRangeByDimension = lineAttribute.clipRangeByDimension } = + line.attribute; + + if (clipRange === 1 && !segments && !points.some(p => p.defined === false) && curveType === 'linear') { + return this.drawLinearLineHighPerformance( + line, + context, + !!fill, + !!stroke, + fillOpacity, + strokeOpacity, + x, + y, + lineAttribute, + drawContext, + params, + fillCb, + strokeCb + ); + } // const { fVisible, sVisible, doFill, doStroke } = data; // 更新cache if (line.shouldUpdateShape()) { - const { points, segments, closePath } = line.attribute; - let { curveType = lineAttribute.curveType } = line.attribute; - if (closePath && curveType === 'linear') { - curveType = 'linearClosed'; - } + const { points, segments } = line.attribute; + const _points = points; if (segments && segments.length) { let startPoint: IPointLike; @@ -287,9 +371,6 @@ export class DefaultCanvasLineRender extends BaseRender implements IGraph line.clearUpdateShapeTag(); } - const { clipRange = lineAttribute.clipRange, clipRangeByDimension = lineAttribute.clipRangeByDimension } = - line.attribute; - if (Array.isArray(line.cache)) { const segments = line.attribute.segments.filter(item => item.points.length); // 如果第一个seg只有一个点,那么shift出去 From 75602643ca72f016afb5f69ca846ac3d7ff95a21 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Tue, 14 Nov 2023 14:33:08 +0800 Subject: [PATCH 25/40] feat: add optmizeSkipCheckBoundariesThreshold config --- packages/vrender-core/src/core/global.ts | 4 ++++ packages/vrender-core/src/interface/global.ts | 2 ++ .../src/render/contributions/render/draw-contribution.ts | 2 +- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/vrender-core/src/core/global.ts b/packages/vrender-core/src/core/global.ts index 4c81bca64..19669b40b 100644 --- a/packages/vrender-core/src/core/global.ts +++ b/packages/vrender-core/src/core/global.ts @@ -103,7 +103,10 @@ export class DefaultGlobal implements IGlobal { this.envContribution.applyStyles = support; } + // 是否在不显示canvas的时候停止绘图操作,默认false optimizeVisible: boolean; + // 在场景树小于某个数的情况下,不进行图元超出边界判断,默认300 + optmizeSkipCheckBoundariesThreshold: number; envParams?: any; declare measureTextMethod: 'native' | 'simple' | 'quick'; @@ -122,6 +125,7 @@ export class DefaultGlobal implements IGlobal { }; this.measureTextMethod = 'native'; this.optimizeVisible = false; + this.optmizeSkipCheckBoundariesThreshold = 300; } protected bindContribution(params?: any): void | Promise { diff --git a/packages/vrender-core/src/interface/global.ts b/packages/vrender-core/src/interface/global.ts index 2ec757e78..73b49ac26 100644 --- a/packages/vrender-core/src/interface/global.ts +++ b/packages/vrender-core/src/interface/global.ts @@ -182,6 +182,8 @@ export interface IGlobal extends Omit void; setActiveEnvContribution: (contribution: IEnvContribution) => void; diff --git a/packages/vrender-core/src/render/contributions/render/draw-contribution.ts b/packages/vrender-core/src/render/contributions/render/draw-contribution.ts index 5d830f7df..67a522f18 100644 --- a/packages/vrender-core/src/render/contributions/render/draw-contribution.ts +++ b/packages/vrender-core/src/render/contributions/render/draw-contribution.ts @@ -86,7 +86,7 @@ export class DefaultDrawContribution implements IDrawContribution { prepareForDraw(renderService: IRenderService, drawContext: IDrawContext) { const count = renderService.renderTreeRoots.reduce((a, b) => a + b.count, 0); // 小于500个元素就不用计算dirtyBounds了 - if (count < 500) { + if (count < this.global.optmizeSkipCheckBoundariesThreshold) { this.useDirtyBounds = false; } else { this.useDirtyBounds = true; From 632a2332dbd5e4d713e2dd640df64c2e9b0a93e8 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Tue, 14 Nov 2023 14:48:21 +0800 Subject: [PATCH 26/40] feat: change optmizeSkipCheckBoundariesThreshold default value to 0 --- packages/vrender-core/src/core/global.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/vrender-core/src/core/global.ts b/packages/vrender-core/src/core/global.ts index 1018a81e4..6bdef174c 100644 --- a/packages/vrender-core/src/core/global.ts +++ b/packages/vrender-core/src/core/global.ts @@ -108,7 +108,7 @@ export class DefaultGlobal implements IGlobal { // 是否在不显示canvas的时候停止绘图操作,默认false optimizeVisible: boolean; - // 在场景树小于某个数的情况下,不进行图元超出边界判断,默认300 + // 在场景树小于某个数的情况下,不进行图元超出边界判断,默认0 optmizeSkipCheckBoundariesThreshold: number; envParams?: any; @@ -129,7 +129,7 @@ export class DefaultGlobal implements IGlobal { }; this.measureTextMethod = 'native'; this.optimizeVisible = false; - this.optmizeSkipCheckBoundariesThreshold = 300; + this.optmizeSkipCheckBoundariesThreshold = 0; } protected bindContribution(params?: any): void | Promise { From a2a4f33b853c5774c2409a17a4d0d0a6a11a8da3 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Wed, 15 Nov 2023 20:20:29 +0800 Subject: [PATCH 27/40] perf: area support drawLinearAreaHighPerformance, closed #672 --- .../perf-optmize-area_2023-11-15-12-20.json | 10 ++ .../__tests__/browser/src/pages/area.ts | 6 +- packages/vrender-core/src/core/stage.ts | 5 + .../contributions/render/area-render.ts | 109 +++++++++++++- .../__tests__/browser/src/pages/area.ts | 138 +++++++++--------- 5 files changed, 191 insertions(+), 77 deletions(-) create mode 100644 common/changes/@visactor/vrender-core/perf-optmize-area_2023-11-15-12-20.json diff --git a/common/changes/@visactor/vrender-core/perf-optmize-area_2023-11-15-12-20.json b/common/changes/@visactor/vrender-core/perf-optmize-area_2023-11-15-12-20.json new file mode 100644 index 000000000..b0c623ce2 --- /dev/null +++ b/common/changes/@visactor/vrender-core/perf-optmize-area_2023-11-15-12-20.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vrender-core", + "comment": "perf: area support drawLinearAreaHighPerformance, closed #672", + "type": "none" + } + ], + "packageName": "@visactor/vrender-core" +} \ No newline at end of file diff --git a/packages/vrender-core/__tests__/browser/src/pages/area.ts b/packages/vrender-core/__tests__/browser/src/pages/area.ts index 028e40845..9cd39b708 100644 --- a/packages/vrender-core/__tests__/browser/src/pages/area.ts +++ b/packages/vrender-core/__tests__/browser/src/pages/area.ts @@ -1,5 +1,9 @@ -import { createStage, createArea, container, IGraphic, global, createLine } from '@visactor/vrender'; +import { createStage, createArea, container, IGraphic, createLine } from '@visactor/vrender-core'; import { addShapesToStage, colorPools } from '../utils'; +import { loadBrowserEnv, loadCanvasPicker } from '@visactor/vrender-kits'; + +loadCanvasPicker(container); +loadBrowserEnv(container); const subP1 = [ [0, 100], diff --git a/packages/vrender-core/src/core/stage.ts b/packages/vrender-core/src/core/stage.ts index c9ed5ecf3..1ad079a04 100644 --- a/packages/vrender-core/src/core/stage.ts +++ b/packages/vrender-core/src/core/stage.ts @@ -49,6 +49,7 @@ import { OrthoCamera } from './camera'; import { LayerService } from './constants'; import { DefaultTimeline } from '../animate'; import { application } from '../application'; +import { isBrowserEnv } from '../env-check'; const DefaultConfig = { WIDTH: 500, @@ -201,6 +202,10 @@ export class Stage extends Group implements IStage { afterRender: new SyncHook(['stage']) }; this.global = application.global; + if (!this.global.env && isBrowserEnv()) { + // 如果是浏览器环境,默认设置env + this.global.setEnv('browser'); + } this.window = container.get(VWindow); this.renderService = container.get(RenderService); this.pluginService = container.get(PluginService); diff --git a/packages/vrender-core/src/render/contributions/render/area-render.ts b/packages/vrender-core/src/render/contributions/render/area-render.ts index 9c3bdb3c6..7872d429d 100644 --- a/packages/vrender-core/src/render/contributions/render/area-render.ts +++ b/packages/vrender-core/src/render/contributions/render/area-render.ts @@ -17,7 +17,8 @@ import type { IRenderService, IGraphicRender, IGraphicRenderDrawParams, - IContributionProvider + IContributionProvider, + IStrokeType } from '../../../interface'; // eslint-disable-next-line @typescript-eslint/consistent-type-imports import { ContributionProvider } from '../../../common/contribution-provider'; @@ -42,6 +43,7 @@ import { defaultAreaBackgroundRenderContribution, defaultAreaTextureRenderContribution } from './contributions/area-contribution-render'; +import { segments } from '../../../common/shape/arc'; function calcLineCache( points: IPointLike[], @@ -85,6 +87,80 @@ export class DefaultCanvasAreaRender extends BaseRender implements IGraph this.init(areaRenderContribitions); } + drawLinearAreaHighPerformance( + area: IArea, + context: IContext2d, + fill: boolean, + stroke: IStrokeType | IStrokeType[], + fillOpacity: number, + strokeOpacity: number, + offsetX: number, + offsetY: number, + areaAttribute: Required, + drawContext: IDrawContext, + params?: IGraphicRenderDrawParams, + fillCb?: ( + ctx: IContext2d, + lineAttribute: Partial, + themeAttribute: IThemeAttribute + ) => boolean, + strokeCb?: ( + ctx: IContext2d, + lineAttribute: Partial, + themeAttribute: IThemeAttribute + ) => boolean + ) { + context.beginPath(); + + const z = this.z ?? 0; + const { points } = area.attribute; + const startP = points[0]; + + context.moveTo(startP.x, startP.y, z); + for (let i = 1; i < points.length; i++) { + const p = points[i]; + context.lineTo(p.x, p.y, z); + } + for (let i = points.length - 1; i >= 0; i--) { + const p = points[i]; + context.lineTo(p.x1 ?? p.x, p.y1 ?? p.y, z); + } + context.closePath(); + + // shadow + context.setShadowBlendStyle && context.setShadowBlendStyle(area, area.attribute, areaAttribute); + + const { x: originX = 0, x: originY = 0 } = area.attribute; + if (fill !== false) { + if (fillCb) { + fillCb(context, area.attribute, areaAttribute); + } else if (fillOpacity) { + context.setCommonStyle(area, area.attribute, originX - offsetX, originY - offsetY, areaAttribute); + context.fill(); + } + } + + if (isArray(stroke) && (stroke[0] || stroke[2]) && stroke[1] === false) { + context.beginPath(); + if (stroke[0]) { + context.moveTo(startP.x, startP.y, z); + for (let i = 1; i < points.length; i++) { + const p = points[i]; + context.lineTo(p.x, p.y, z); + } + } else if (stroke[2]) { + const endP = points[points.length - 1]; + context.moveTo(endP.x, endP.y, z); + for (let i = points.length - 2; i >= 0; i--) { + const p = points[i]; + context.lineTo(p.x1 ?? p.x, p.y1 ?? p.y, z); + } + } + } + context.setStrokeStyle(area, area.attribute, originX - offsetX, originY - offsetY, areaAttribute); + context.stroke(); + } + drawShape( area: IArea, context: IContext2d, @@ -105,6 +181,8 @@ export class DefaultCanvasAreaRender extends BaseRender implements IGraph ) { const areaAttribute = getTheme(area, params?.theme).area; const { + fill = areaAttribute.fill, + stroke = areaAttribute.stroke, fillOpacity = areaAttribute.fillOpacity, z = areaAttribute.z, strokeOpacity = areaAttribute.strokeOpacity @@ -116,15 +194,32 @@ export class DefaultCanvasAreaRender extends BaseRender implements IGraph } const { doFill, doStroke } = data; - const { clipRange = areaAttribute.clipRange } = area.attribute; + const { clipRange = areaAttribute.clipRange, closePath, points, segments } = area.attribute; + let { curveType = areaAttribute.curveType } = area.attribute; + if (closePath && curveType === 'linear') { + curveType = 'linearClosed'; + } + + if (clipRange === 1 && !segments && !points.some(p => p.defined === false) && curveType === 'linear') { + return this.drawLinearAreaHighPerformance( + area, + context, + !!fill, + stroke, + fillOpacity, + strokeOpacity, + x, + y, + areaAttribute, + drawContext, + params, + fillCb, + strokeCb + ); + } // 更新cache if (area.shouldUpdateShape()) { - const { points, segments, closePath } = area.attribute; - let { curveType = areaAttribute.curveType } = area.attribute; - if (closePath && curveType === 'linear') { - curveType = 'linearClosed'; - } if (segments && segments.length) { let startPoint: IPointLike; let lastTopSeg: { endX: number; endY: number }; diff --git a/packages/vrender/__tests__/browser/src/pages/area.ts b/packages/vrender/__tests__/browser/src/pages/area.ts index 028e40845..31df9f5d9 100644 --- a/packages/vrender/__tests__/browser/src/pages/area.ts +++ b/packages/vrender/__tests__/browser/src/pages/area.ts @@ -58,8 +58,8 @@ export const page = () => { y: 250, x1: 230.5, y1: 250, - context: 2, - defined: false + context: 2 + // defined: false }, { x: 230.5, @@ -88,7 +88,7 @@ export const page = () => { lineWidth: 6, lineCap: 'round', lineJoin: 'round', - curveType: 'linearClosed', + curveType: 'linear', lineDash: [4, 2], stroke: ['orange', false, false, false], connectedType: 'connect', @@ -98,71 +98,71 @@ export const page = () => { // "pickable": true }) ); - graphics.push( - createLine({ - defined: true, - enableSegments: true, - segments: null, - points: [ - { - x: 230.5, - y: 151.1037915390441, - x1: 230.5, - y1: 250, - context: 0 - }, - { - x: 308.6643884293173, - y: 204.8717692992912, - x1: 230.5, - y1: 250, - context: 1 - }, - { - x: 230.5, - y: 250, - x1: 230.5, - y1: 250, - context: 2, - defined: false - }, - { - x: 230.5, - y: 280.05866037183256, - x1: 230.5, - y1: 250, - context: 3 - }, - { - x: 188.87948429636262, - y: 274.0296159453061, - x1: 230.5, - y1: 250, - context: 4 - }, - { - x: 98.35502938981602, - y: 173.70606564615522, - x1: 230.5, - y1: 250, - context: 5 - } - ], - // fill: 'red', - visible: true, - lineWidth: 1, - lineCap: 'round', - lineJoin: 'round', - curveType: 'linearClosed', - lineDash: [4, 2], - stroke: '#2E62F1', - connectedType: 'connect', - closePath: true, - x: 0, - y: 0 - // "pickable": true - }) - ); + // graphics.push( + // createLine({ + // defined: true, + // enableSegments: true, + // segments: null, + // points: [ + // { + // x: 230.5, + // y: 151.1037915390441, + // x1: 230.5, + // y1: 250, + // context: 0 + // }, + // { + // x: 308.6643884293173, + // y: 204.8717692992912, + // x1: 230.5, + // y1: 250, + // context: 1 + // }, + // { + // x: 230.5, + // y: 250, + // x1: 230.5, + // y1: 250, + // context: 2, + // defined: false + // }, + // { + // x: 230.5, + // y: 280.05866037183256, + // x1: 230.5, + // y1: 250, + // context: 3 + // }, + // { + // x: 188.87948429636262, + // y: 274.0296159453061, + // x1: 230.5, + // y1: 250, + // context: 4 + // }, + // { + // x: 98.35502938981602, + // y: 173.70606564615522, + // x1: 230.5, + // y1: 250, + // context: 5 + // } + // ], + // // fill: 'red', + // visible: true, + // lineWidth: 1, + // lineCap: 'round', + // lineJoin: 'round', + // curveType: 'linearClosed', + // lineDash: [4, 2], + // stroke: '#2E62F1', + // connectedType: 'connect', + // closePath: true, + // x: 0, + // y: 0 + // // "pickable": true + // }) + // ); }); // ['linear', 'step', 'stepBefore', 'stepAfter', 'basis', 'monotoneX', 'monotoneY'].forEach((type, i) => { @@ -210,7 +210,7 @@ export const page = () => { height: 500, renderStyle: 'default', // viewBox: viewOptions.viewBox, - dpr: 2, + // dpr: 2, // canvas: viewOptions.renderCanvas, canvasControled: false, // container: viewOptions.container, From fe7c093102583b24368a9ccaa82b08fcb7722aa3 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Fri, 17 Nov 2023 11:17:32 +0800 Subject: [PATCH 28/40] feat: don't rewrite global reflect --- .../feat-reflect-local_2023-11-17-03-17.json | 10 ++++++++ .../feat-reflect-local_2023-11-17-03-17.json | 10 ++++++++ .../src/common/Reflect-metadata.ts | 24 ++++--------------- 3 files changed, 25 insertions(+), 19 deletions(-) create mode 100644 common/changes/@visactor/vrender-core/feat-reflect-local_2023-11-17-03-17.json create mode 100644 common/changes/@visactor/vrender/feat-reflect-local_2023-11-17-03-17.json diff --git a/common/changes/@visactor/vrender-core/feat-reflect-local_2023-11-17-03-17.json b/common/changes/@visactor/vrender-core/feat-reflect-local_2023-11-17-03-17.json new file mode 100644 index 000000000..92b18504c --- /dev/null +++ b/common/changes/@visactor/vrender-core/feat-reflect-local_2023-11-17-03-17.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vrender-core", + "comment": "feat: don't rewrite global reflect", + "type": "none" + } + ], + "packageName": "@visactor/vrender-core" +} \ No newline at end of file diff --git a/common/changes/@visactor/vrender/feat-reflect-local_2023-11-17-03-17.json b/common/changes/@visactor/vrender/feat-reflect-local_2023-11-17-03-17.json new file mode 100644 index 000000000..7ffd1231a --- /dev/null +++ b/common/changes/@visactor/vrender/feat-reflect-local_2023-11-17-03-17.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vrender", + "comment": "feat: don't rewrite global reflect", + "type": "none" + } + ], + "packageName": "@visactor/vrender" +} \ No newline at end of file diff --git a/packages/vrender-core/src/common/Reflect-metadata.ts b/packages/vrender-core/src/common/Reflect-metadata.ts index c6e0bd7ea..5a194eb50 100644 --- a/packages/vrender-core/src/common/Reflect-metadata.ts +++ b/packages/vrender-core/src/common/Reflect-metadata.ts @@ -13,25 +13,11 @@ MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ -let Reflect; export default (function (Reflect) { // Metadata Proposal // https://rbuckton.github.io/reflect-metadata/ (function (factory) { - const root = - typeof global === 'object' - ? global - : typeof self === 'object' - ? self - : typeof this === 'object' - ? this - : Function('return this;')(); - let exporter = makeExporter(Reflect); - if (typeof root.Reflect === 'undefined') { - root.Reflect = Reflect; - } else { - exporter = makeExporter(root.Reflect, exporter); - } + const exporter = makeExporter(Reflect); factory(exporter); function makeExporter(target, previous) { return function (key, value) { @@ -245,9 +231,9 @@ export default (function (Reflect) { if (!IsObject(target)) { throw new TypeError(); } - if (!IsUndefined(propertyKey)) { - propertyKey = ToPropertyKey(propertyKey); - } + // if (!IsUndefined(propertyKey)) { + // propertyKey = ToPropertyKey(propertyKey); + // } return OrdinaryDefineOwnMetadata(metadataKey, metadataValue, target, propertyKey); } exporter('defineMetadata', defineMetadata); @@ -1214,4 +1200,4 @@ export default (function (Reflect) { }); return Reflect; -})(Reflect || (Reflect = {})); +})({}); From 1571f60a6e76054758ce807c5d541985433cc9b2 Mon Sep 17 00:00:00 2001 From: fangsmile <892739385@qq.com> Date: Fri, 17 Nov 2023 16:03:49 +0800 Subject: [PATCH 29/40] feat: add dbltap event #689 --- packages/vrender-core/src/event/event-manager.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/vrender-core/src/event/event-manager.ts b/packages/vrender-core/src/event/event-manager.ts index 03e113257..f56113fde 100644 --- a/packages/vrender-core/src/event/event-manager.ts +++ b/packages/vrender-core/src/event/event-manager.ts @@ -515,6 +515,10 @@ export class EventManager { } } else if (clickEvent.pointerType === 'touch') { this.dispatchEvent(clickEvent, 'tap'); + if (clickHistory.clickCount === 2) { + // 双击 + this.dispatchEvent(clickEvent, 'dbltap'); + } } this.dispatchEvent(clickEvent, 'pointertap'); From 64f821b2a07436454fd5006589303b8ab796d6ca Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Mon, 20 Nov 2023 11:39:16 +0800 Subject: [PATCH 30/40] fix: fix issue with drawLinearAreaHighPerformance --- .../src/render/contributions/render/area-render.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/vrender-core/src/render/contributions/render/area-render.ts b/packages/vrender-core/src/render/contributions/render/area-render.ts index 7872d429d..06673b4f6 100644 --- a/packages/vrender-core/src/render/contributions/render/area-render.ts +++ b/packages/vrender-core/src/render/contributions/render/area-render.ts @@ -156,9 +156,10 @@ export class DefaultCanvasAreaRender extends BaseRender implements IGraph context.lineTo(p.x1 ?? p.x, p.y1 ?? p.y, z); } } + } else if (stroke) { + context.setStrokeStyle(area, area.attribute, originX - offsetX, originY - offsetY, areaAttribute); + context.stroke(); } - context.setStrokeStyle(area, area.attribute, originX - offsetX, originY - offsetY, areaAttribute); - context.stroke(); } drawShape( From 62fa07d5b48d34a9bc80b03dd1c75c2c5bafb3e4 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Mon, 20 Nov 2023 16:16:34 +0800 Subject: [PATCH 31/40] fix: fix area issue --- .../contributions/render/area-render.ts | 36 +- .../contributions/render/base-render.ts | 1 - .../src/render/contributions/render/module.ts | 7 + .../__tests__/browser/src/pages/chart.ts | 3474 ++++------------- 4 files changed, 787 insertions(+), 2731 deletions(-) diff --git a/packages/vrender-core/src/render/contributions/render/area-render.ts b/packages/vrender-core/src/render/contributions/render/area-render.ts index 06673b4f6..16f82effc 100644 --- a/packages/vrender-core/src/render/contributions/render/area-render.ts +++ b/packages/vrender-core/src/render/contributions/render/area-render.ts @@ -91,7 +91,7 @@ export class DefaultCanvasAreaRender extends BaseRender implements IGraph area: IArea, context: IContext2d, fill: boolean, - stroke: IStrokeType | IStrokeType[], + stroke: boolean, fillOpacity: number, strokeOpacity: number, offsetX: number, @@ -140,23 +140,25 @@ export class DefaultCanvasAreaRender extends BaseRender implements IGraph } } - if (isArray(stroke) && (stroke[0] || stroke[2]) && stroke[1] === false) { - context.beginPath(); - if (stroke[0]) { - context.moveTo(startP.x, startP.y, z); - for (let i = 1; i < points.length; i++) { - const p = points[i]; - context.lineTo(p.x, p.y, z); - } - } else if (stroke[2]) { - const endP = points[points.length - 1]; - context.moveTo(endP.x, endP.y, z); - for (let i = points.length - 2; i >= 0; i--) { - const p = points[i]; - context.lineTo(p.x1 ?? p.x, p.y1 ?? p.y, z); + if (stroke) { + const { stroke = areaAttribute && areaAttribute.stroke } = area.attribute; + if (isArray(stroke) && (stroke[0] || stroke[2]) && stroke[1] === false) { + context.beginPath(); + if (stroke[0]) { + context.moveTo(startP.x, startP.y, z); + for (let i = 1; i < points.length; i++) { + const p = points[i]; + context.lineTo(p.x, p.y, z); + } + } else if (stroke[2]) { + const endP = points[points.length - 1]; + context.moveTo(endP.x, endP.y, z); + for (let i = points.length - 2; i >= 0; i--) { + const p = points[i]; + context.lineTo(p.x1 ?? p.x, p.y1 ?? p.y, z); + } } } - } else if (stroke) { context.setStrokeStyle(area, area.attribute, originX - offsetX, originY - offsetY, areaAttribute); context.stroke(); } @@ -206,7 +208,7 @@ export class DefaultCanvasAreaRender extends BaseRender implements IGraph area, context, !!fill, - stroke, + doStroke, fillOpacity, strokeOpacity, x, diff --git a/packages/vrender-core/src/render/contributions/render/base-render.ts b/packages/vrender-core/src/render/contributions/render/base-render.ts index efb3cee5c..eb260921a 100644 --- a/packages/vrender-core/src/render/contributions/render/base-render.ts +++ b/packages/vrender-core/src/render/contributions/render/base-render.ts @@ -20,7 +20,6 @@ import { mat4Allocate } from '../../../allocator/matrix-allocate'; import { drawPathProxy, fillVisible, runFill, runStroke, strokeVisible } from './utils'; import { BaseRenderContributionTime } from '../../../common/enums'; -@injectable() export abstract class BaseRender { camera: ICamera; declare z: number; diff --git a/packages/vrender-core/src/render/contributions/render/module.ts b/packages/vrender-core/src/render/contributions/render/module.ts index 9e333eebc..62a91113a 100644 --- a/packages/vrender-core/src/render/contributions/render/module.ts +++ b/packages/vrender-core/src/render/contributions/render/module.ts @@ -80,6 +80,7 @@ export default new ContainerModule(bind => { // bind(RenderSelector).to(DefaultRenderSelector).inSingletonScope(); // circle 渲染器 + bind(DefaultCanvasCircleRender).toSelf().inSingletonScope(); bind(CircleRender).to(DefaultCanvasCircleRender).inSingletonScope(); bind(GraphicRender).toService(CircleRender); @@ -87,6 +88,7 @@ export default new ContainerModule(bind => { bindContributionProvider(bind, CircleRenderContribution); // rect 渲染器 + bind(DefaultCanvasRectRender).toSelf().inSingletonScope(); bind(RectRender).to(DefaultCanvasRectRender).inSingletonScope(); bind(GraphicRender).toService(RectRender); @@ -103,6 +105,7 @@ export default new ContainerModule(bind => { bindContributionProvider(bind, TextRenderContribution); // path 渲染器 + bind(DefaultCanvasPathRender).toSelf().inSingletonScope(); bind(PathRender).to(DefaultCanvasPathRender).inSingletonScope(); bind(GraphicRender).toService(PathRender); @@ -110,6 +113,7 @@ export default new ContainerModule(bind => { bindContributionProvider(bind, PathRenderContribution); // symbol渲染器 + bind(DefaultCanvasSymbolRender).toSelf().inSingletonScope(); bind(SymbolRender).to(DefaultCanvasSymbolRender).inSingletonScope(); bind(GraphicRender).toService(SymbolRender); @@ -117,6 +121,7 @@ export default new ContainerModule(bind => { bindContributionProvider(bind, SymbolRenderContribution); // arc 渲染器 + bind(DefaultCanvasArcRender).toSelf().inSingletonScope(); bind(ArcRender).to(DefaultCanvasArcRender).inSingletonScope(); bind(GraphicRender).toService(ArcRender); @@ -128,6 +133,7 @@ export default new ContainerModule(bind => { bindContributionProvider(bind, ArcRenderContribution); // line渲染器 + bind(DefaultCanvasLineRender).toSelf().inSingletonScope(); bind(LineRender).to(DefaultCanvasLineRender).inSingletonScope(); bind(GraphicRender).toService(LineRender); @@ -136,6 +142,7 @@ export default new ContainerModule(bind => { bind(DefaultIncrementalCanvasAreaRender).toSelf().inSingletonScope(); // area渲染器 + bind(DefaultCanvasAreaRender).toSelf().inSingletonScope(); bind(AreaRender).to(DefaultCanvasAreaRender).inSingletonScope(); bind(GraphicRender).toService(AreaRender); diff --git a/packages/vrender/__tests__/browser/src/pages/chart.ts b/packages/vrender/__tests__/browser/src/pages/chart.ts index f83d52bdc..f62e796e8 100644 --- a/packages/vrender/__tests__/browser/src/pages/chart.ts +++ b/packages/vrender/__tests__/browser/src/pages/chart.ts @@ -24,52 +24,54 @@ import { import { roughModule } from '@visactor/vrender-kits'; const json = { - attribute: {}, - _uid: 3, + attribute: { + background: 'white' + }, + _uid: 281, type: 'group', children: [ { attribute: {}, - _uid: 9, + _uid: 287, type: 'group', children: [ { attribute: { x: 0, y: 0, - width: 981, - height: 500, + width: 846, + height: 522, sizeAttrs: { x: 0, y: 0, - width: 981, - height: 500 + width: 846, + height: 522 } }, - _uid: 14, + _uid: 291, type: 'group', name: 'root', children: [ { attribute: { visible: true, - clip: true, - x: 68, - y: 70, - width: 845, - height: 334, + clip: false, + x: 47, + y: 26, + width: 779, + height: 452, sizeAttrs: { - x: 68, - y: 70, - width: 845, - height: 334 + x: 47, + y: 26, + width: 779, + height: 452 }, pickable: false, zIndex: 450 }, - _uid: 53, + _uid: 316, type: 'group', - name: 'regionGroup_4', + name: 'regionGroup_47', children: [ { attribute: { @@ -84,311 +86,79 @@ const json = { pickable: false, zIndex: 0 }, - _uid: 54, + _uid: 317, type: 'group', - name: 'seriesGroup_area_5_7', + name: 'seriesGroup_area_48_50', children: [ { attribute: { pickable: false, zIndex: 300 }, - _uid: 223, + _uid: 432, type: 'group', - name: 'area_8', + name: 'area_51', children: [ { attribute: { y1: 0, - defined: true, - points: [ - { - x: 66.71052631578947, - y: 305.75028000000003, - context: 0, - y1: 334 - }, - { - x: 155.65789473684208, - y: 307.73424, - context: 4, - y1: 334 - }, - { - x: 244.60526315789474, - y: 299.12372, - context: 8, - y1: 334 - }, - { - x: 333.5526315789474, - y: 272.16992, - context: 12, - y1: 334 - }, - { - x: 422.5, - y: 311.90256, - context: 16, - y1: 334 - }, - { - x: 511.4473684210526, - y: 297.71424, - context: 20, - y1: 334 - }, - { - x: 600.3947368421053, - y: 242.47732000000002, - context: 24, - y1: 334 - }, - { - x: 689.3421052631578, - y: 307.22656, - context: 28, - y1: 334 - }, - { - x: 778.2894736842105, - y: 209.00384, - context: 32, - y1: 334 - } - ], - segments: null, - visible: true, - lineWidth: 2, - lineCap: 'round', - lineJoin: 'round', - fillOpacity: 0.2, fill: '#1664FF', stroke: ['#1664FF', false, false, false], - connectedType: 'none', - x: 0, - y: 0, - x1: 0, - pickable: true - }, - _uid: 224, - type: 'area', - children: [] - }, - { - attribute: { - y1: 0, - defined: true, - points: [ - { - x: 66.71052631578947, - y: 276.5186, - context: 1, - y1: 305.75028000000003 - }, - { - x: 155.65789473684208, - y: 281.10108, - context: 5, - y1: 307.73424 - }, - { - x: 244.60526315789474, - y: 275.24940000000004, - context: 9, - y1: 299.12372 - }, - { - x: 333.5526315789474, - y: 242.93824, - context: 13, - y1: 272.16992 - }, - { - x: 422.5, - y: 281.3616, - context: 17, - y1: 311.90256 - }, - { - x: 511.4473684210526, - y: 274.88867999999997, - context: 21, - y1: 297.71424 - }, - { - x: 600.3947368421053, - y: 207.53424, - context: 25, - y1: 242.47732000000002 - }, - { - x: 689.3421052631578, - y: 276.6856, - context: 29, - y1: 307.22656 - }, - { - x: 778.2894736842105, - y: 168.02872, - context: 33, - y1: 209.00384 - } - ], - segments: null, - visible: true, - lineWidth: 2, - lineCap: 'round', - lineJoin: 'round', - fillOpacity: 0.2, - fill: '#1AC6FF', - stroke: ['#1AC6FF', false, false, false], - connectedType: 'none', - x: 0, - y: 0, - x1: 0, - pickable: true - }, - _uid: 225, - type: 'area', - children: [] - }, - { - attribute: { - y1: 0, - defined: true, - points: [ - { - x: 66.71052631578947, - y: 256.11788, - context: 2, - y1: 276.5186 - }, - { - x: 155.65789473684208, - y: 247.25352, - context: 6, - y1: 281.10108 - }, - { - x: 244.60526315789474, - y: 228.46268000000003, - context: 10, - y1: 275.24940000000004 - }, - { - x: 333.5526315789474, - y: 182.45752, - context: 14, - y1: 242.93824 - }, - { - x: 422.5, - y: 200.91436, - context: 18, - y1: 281.3616 - }, - { - x: 511.4473684210526, - y: 174.24111999999997, - context: 22, - y1: 274.88867999999997 - }, - { - x: 600.3947368421053, - y: 139.93932, - context: 26, - y1: 207.53424 - }, - { - x: 689.3421052631578, - y: 196.23835999999997, - context: 30, - y1: 276.6856 - }, - { - x: 778.2894736842105, - y: 98.42979999999999, - context: 34, - y1: 168.02872 - } - ], - segments: null, - visible: true, - lineWidth: 2, - lineCap: 'round', - lineJoin: 'round', - fillOpacity: 0.2, - fill: '#FF8A00', - stroke: ['#FF8A00', false, false, false], - connectedType: 'none', - x: 0, - y: 0, - x1: 0, - pickable: true - }, - _uid: 226, - type: 'area', - children: [] - }, - { - attribute: { - y1: 0, defined: true, points: [ { - x: 66.71052631578947, - y: 170.52036, - context: 3, - y1: 256.11788 + x: 61.499999999999964, + y: 271.2, + context: '2:00_0', + y1: 452 }, { - x: 155.65789473684208, - y: 160.33336, - context: 7, - y1: 247.25352 + x: 143.49999999999997, + y: 248.60000000000002, + context: '4:00_0', + y1: 452 }, { - x: 244.60526315789474, - y: 150.81436000000002, - context: 11, - y1: 228.46268000000003 + x: 225.49999999999997, + y: 203.39999999999998, + context: '6:00_0', + y1: 452 }, { - x: 333.5526315789474, - y: 123.58, - context: 15, - y1: 182.45752 + x: 307.49999999999994, + y: 135.60000000000002, + context: '8:00_0', + y1: 452 }, { - x: 422.5, - y: 114.08772, - context: 19, - y1: 200.91436 + x: 389.49999999999994, + y: 90.39999999999998, + context: '10:00_0', + y1: 452 }, { - x: 511.4473684210526, - y: 91.93683999999999, - context: 23, - y1: 174.24111999999997 + x: 471.49999999999994, + y: 67.80000000000001, + context: '12:00_0', + y1: 452 }, { - x: 600.3947368421053, - y: 70.85476, - context: 27, - y1: 139.93932 + x: 553.4999999999999, + y: 67.80000000000001, + context: '14:00_0', + y1: 452 }, { - x: 689.3421052631578, - y: 42.611720000000005, - context: 31, - y1: 196.23835999999997 + x: 635.4999999999999, + y: 90.39999999999998, + context: '16:00_0', + y1: 452 }, { - x: 778.2894736842105, - y: 23.206319999999995, - context: 35, - y1: 98.42979999999999 + x: 717.4999999999999, + y: 113, + context: '18:00_0', + y1: 452 } ], segments: null, @@ -397,15 +167,14 @@ const json = { lineCap: 'round', lineJoin: 'round', fillOpacity: 0.2, - fill: '#3CC780', - stroke: ['#3CC780', false, false, false], connectedType: 'none', x: 0, y: 0, x1: 0, - pickable: true + pickable: true, + clipRange: 1 }, - _uid: 227, + _uid: 433, type: 'area', children: [] } @@ -416,9 +185,9 @@ const json = { pickable: false, zIndex: 300 }, - _uid: 186, + _uid: 422, type: 'group', - name: 'point_10', + name: 'point_53', children: [ { attribute: { @@ -426,17 +195,19 @@ const json = { size: 8, symbolType: 'circle', lineWidth: 1, - stroke: '#202226', + stroke: '#ffffff', fillOpacity: 1, + x: 61.499999999999964, + y: 271.2, fill: '#1664FF', - x: 66.71052631578947, - y: 305.75028000000003, imageAttrs: { fill: '#1664FF' }, - pickable: true + pickable: true, + scaleX: 1, + scaleY: 1 }, - _uid: 187, + _uid: 423, type: 'symbol', children: [] }, @@ -446,17 +217,19 @@ const json = { size: 8, symbolType: 'circle', lineWidth: 1, - stroke: '#202226', + stroke: '#ffffff', fillOpacity: 1, - fill: '#1AC6FF', - x: 66.71052631578947, - y: 276.5186, + x: 143.49999999999997, + y: 248.60000000000002, + fill: '#1664FF', imageAttrs: { - fill: '#1AC6FF' + fill: '#1664FF' }, - pickable: true + pickable: true, + scaleX: 1, + scaleY: 1 }, - _uid: 188, + _uid: 424, type: 'symbol', children: [] }, @@ -466,17 +239,19 @@ const json = { size: 8, symbolType: 'circle', lineWidth: 1, - stroke: '#202226', + stroke: '#ffffff', fillOpacity: 1, - fill: '#FF8A00', - x: 66.71052631578947, - y: 256.11788, + x: 225.49999999999997, + y: 203.39999999999998, + fill: '#1664FF', imageAttrs: { - fill: '#FF8A00' + fill: '#1664FF' }, - pickable: true + pickable: true, + scaleX: 1, + scaleY: 1 }, - _uid: 189, + _uid: 425, type: 'symbol', children: [] }, @@ -486,17 +261,19 @@ const json = { size: 8, symbolType: 'circle', lineWidth: 1, - stroke: '#202226', + stroke: '#ffffff', fillOpacity: 1, - fill: '#3CC780', - x: 66.71052631578947, - y: 170.52036, + x: 307.49999999999994, + y: 135.60000000000002, + fill: '#1664FF', imageAttrs: { - fill: '#3CC780' + fill: '#1664FF' }, - pickable: true + pickable: true, + scaleX: 1, + scaleY: 1 }, - _uid: 190, + _uid: 426, type: 'symbol', children: [] }, @@ -506,17 +283,19 @@ const json = { size: 8, symbolType: 'circle', lineWidth: 1, - stroke: '#202226', + stroke: '#ffffff', fillOpacity: 1, + x: 389.49999999999994, + y: 90.39999999999998, fill: '#1664FF', - x: 155.65789473684208, - y: 307.73424, imageAttrs: { fill: '#1664FF' }, - pickable: true + pickable: true, + scaleX: 1, + scaleY: 1 }, - _uid: 191, + _uid: 427, type: 'symbol', children: [] }, @@ -526,17 +305,19 @@ const json = { size: 8, symbolType: 'circle', lineWidth: 1, - stroke: '#202226', + stroke: '#ffffff', fillOpacity: 1, - fill: '#1AC6FF', - x: 155.65789473684208, - y: 281.10108, + x: 471.49999999999994, + y: 67.80000000000001, + fill: '#1664FF', imageAttrs: { - fill: '#1AC6FF' + fill: '#1664FF' }, - pickable: true + pickable: true, + scaleX: 1, + scaleY: 1 }, - _uid: 192, + _uid: 428, type: 'symbol', children: [] }, @@ -546,17 +327,19 @@ const json = { size: 8, symbolType: 'circle', lineWidth: 1, - stroke: '#202226', + stroke: '#ffffff', fillOpacity: 1, - fill: '#FF8A00', - x: 155.65789473684208, - y: 247.25352, + x: 553.4999999999999, + y: 67.80000000000001, + fill: '#1664FF', imageAttrs: { - fill: '#FF8A00' + fill: '#1664FF' }, - pickable: true + pickable: true, + scaleX: 1, + scaleY: 1 }, - _uid: 193, + _uid: 429, type: 'symbol', children: [] }, @@ -566,17 +349,19 @@ const json = { size: 8, symbolType: 'circle', lineWidth: 1, - stroke: '#202226', + stroke: '#ffffff', fillOpacity: 1, - fill: '#3CC780', - x: 155.65789473684208, - y: 160.33336, + x: 635.4999999999999, + y: 90.39999999999998, + fill: '#1664FF', imageAttrs: { - fill: '#3CC780' + fill: '#1664FF' }, - pickable: true + pickable: true, + scaleX: 1, + scaleY: 1 }, - _uid: 194, + _uid: 430, type: 'symbol', children: [] }, @@ -586,1366 +371,190 @@ const json = { size: 8, symbolType: 'circle', lineWidth: 1, - stroke: '#202226', + stroke: '#ffffff', fillOpacity: 1, + x: 717.4999999999999, + y: 113, fill: '#1664FF', - x: 244.60526315789474, - y: 299.12372, imageAttrs: { fill: '#1664FF' }, - pickable: true + pickable: true, + scaleX: 1, + scaleY: 1 }, - _uid: 195, + _uid: 431, type: 'symbol', children: [] + } + ] + } + ] + } + ] + }, + { + attribute: { + pickable: false, + zIndex: 100 + }, + _uid: 292, + type: 'group', + name: 'axis-bottom_61', + children: [ + { + attribute: { + title: { + space: 8, + padding: 0, + textStyle: { + fontSize: 12, + fill: '#606773', + fontWeight: 'normal', + fillOpacity: 1, + lineHeight: 15.600000000000001 + }, + autoRotate: false, + angle: null, + shape: {}, + background: {}, + state: { + text: null, + shape: null, + background: null + }, + pickable: true, + childrenPickable: true, + text: 'time', + maxWidth: null + }, + label: { + visible: true, + inside: false, + space: 8, + padding: 0, + style: { + fontSize: 12, + fill: '#89909d', + fontWeight: 'normal', + fillOpacity: 1 + }, + formatMethod: null, + state: null + }, + tick: { + visible: true, + inside: false, + alignWithLabel: true, + length: 4, + style: { + lineWidth: 1, + stroke: '#d9dde4', + strokeOpacity: 1 + }, + state: null + }, + subTick: { + visible: false, + inside: false, + count: 4, + length: 2, + style: { + lineWidth: 1, + stroke: '#d9dde4', + strokeOpacity: 1 + }, + state: null + }, + line: { + visible: true, + style: { + lineWidth: 1, + stroke: '#d9dde4', + strokeOpacity: 1 + }, + startSymbol: {}, + endSymbol: {} + }, + x: 47, + y: 478, + start: { + x: 0, + y: 0 + }, + end: { + x: 779, + y: 0 + }, + items: [ + [ + { + id: '2:00', + label: '2:00', + value: 0.07894736842105259, + rawValue: '2:00' }, { - attribute: { - visible: true, - size: 8, - symbolType: 'circle', - lineWidth: 1, - stroke: '#202226', - fillOpacity: 1, - fill: '#1AC6FF', - x: 244.60526315789474, - y: 275.24940000000004, - imageAttrs: { - fill: '#1AC6FF' - }, - pickable: true - }, - _uid: 196, - type: 'symbol', - children: [] + id: '4:00', + label: '4:00', + value: 0.18421052631578944, + rawValue: '4:00' }, { - attribute: { - visible: true, - size: 8, - symbolType: 'circle', - lineWidth: 1, - stroke: '#202226', - fillOpacity: 1, - fill: '#FF8A00', - x: 244.60526315789474, - y: 228.46268000000003, - imageAttrs: { - fill: '#FF8A00' - }, - pickable: true - }, - _uid: 197, - type: 'symbol', - children: [] + id: '6:00', + label: '6:00', + value: 0.28947368421052627, + rawValue: '6:00' }, { - attribute: { - visible: true, - size: 8, - symbolType: 'circle', - lineWidth: 1, - stroke: '#202226', - fillOpacity: 1, - fill: '#3CC780', - x: 244.60526315789474, - y: 150.81436000000002, - imageAttrs: { - fill: '#3CC780' - }, - pickable: true - }, - _uid: 198, - type: 'symbol', - children: [] + id: '8:00', + label: '8:00', + value: 0.3947368421052631, + rawValue: '8:00' }, { - attribute: { - visible: true, - size: 8, - symbolType: 'circle', - lineWidth: 1, - stroke: '#202226', - fillOpacity: 1, - fill: '#1664FF', - x: 333.5526315789474, - y: 272.16992, - imageAttrs: { - fill: '#1664FF' - }, - pickable: true - }, - _uid: 199, - type: 'symbol', - children: [] - }, - { - attribute: { - visible: true, - size: 8, - symbolType: 'circle', - lineWidth: 1, - stroke: '#202226', - fillOpacity: 1, - fill: '#1AC6FF', - x: 333.5526315789474, - y: 242.93824, - imageAttrs: { - fill: '#1AC6FF' - }, - pickable: true - }, - _uid: 200, - type: 'symbol', - children: [] - }, - { - attribute: { - visible: true, - size: 8, - symbolType: 'circle', - lineWidth: 1, - stroke: '#202226', - fillOpacity: 1, - fill: '#FF8A00', - x: 333.5526315789474, - y: 182.45752, - imageAttrs: { - fill: '#FF8A00' - }, - pickable: true - }, - _uid: 201, - type: 'symbol', - children: [] - }, - { - attribute: { - visible: true, - size: 8, - symbolType: 'circle', - lineWidth: 1, - stroke: '#202226', - fillOpacity: 1, - fill: '#3CC780', - x: 333.5526315789474, - y: 123.58, - imageAttrs: { - fill: '#3CC780' - }, - pickable: true - }, - _uid: 202, - type: 'symbol', - children: [] - }, - { - attribute: { - visible: true, - size: 8, - symbolType: 'circle', - lineWidth: 1, - stroke: '#202226', - fillOpacity: 1, - fill: '#1664FF', - x: 422.5, - y: 311.90256, - imageAttrs: { - fill: '#1664FF' - }, - pickable: true - }, - _uid: 203, - type: 'symbol', - children: [] - }, - { - attribute: { - visible: true, - size: 8, - symbolType: 'circle', - lineWidth: 1, - stroke: '#202226', - fillOpacity: 1, - fill: '#1AC6FF', - x: 422.5, - y: 281.3616, - imageAttrs: { - fill: '#1AC6FF' - }, - pickable: true - }, - _uid: 204, - type: 'symbol', - children: [] - }, - { - attribute: { - visible: true, - size: 8, - symbolType: 'circle', - lineWidth: 1, - stroke: '#202226', - fillOpacity: 1, - fill: '#FF8A00', - x: 422.5, - y: 200.91436, - imageAttrs: { - fill: '#FF8A00' - }, - pickable: true - }, - _uid: 205, - type: 'symbol', - children: [] - }, - { - attribute: { - visible: true, - size: 8, - symbolType: 'circle', - lineWidth: 1, - stroke: '#202226', - fillOpacity: 1, - fill: '#3CC780', - x: 422.5, - y: 114.08772, - imageAttrs: { - fill: '#3CC780' - }, - pickable: true - }, - _uid: 206, - type: 'symbol', - children: [] - }, - { - attribute: { - visible: true, - size: 8, - symbolType: 'circle', - lineWidth: 1, - stroke: '#202226', - fillOpacity: 1, - fill: '#1664FF', - x: 511.4473684210526, - y: 297.71424, - imageAttrs: { - fill: '#1664FF' - }, - pickable: true - }, - _uid: 207, - type: 'symbol', - children: [] - }, - { - attribute: { - visible: true, - size: 8, - symbolType: 'circle', - lineWidth: 1, - stroke: '#202226', - fillOpacity: 1, - fill: '#1AC6FF', - x: 511.4473684210526, - y: 274.88867999999997, - imageAttrs: { - fill: '#1AC6FF' - }, - pickable: true - }, - _uid: 208, - type: 'symbol', - children: [] - }, - { - attribute: { - visible: true, - size: 8, - symbolType: 'circle', - lineWidth: 1, - stroke: '#202226', - fillOpacity: 1, - fill: '#FF8A00', - x: 511.4473684210526, - y: 174.24111999999997, - imageAttrs: { - fill: '#FF8A00' - }, - pickable: true - }, - _uid: 209, - type: 'symbol', - children: [] - }, - { - attribute: { - visible: true, - size: 8, - symbolType: 'circle', - lineWidth: 1, - stroke: '#202226', - fillOpacity: 1, - fill: '#3CC780', - x: 511.4473684210526, - y: 91.93683999999999, - imageAttrs: { - fill: '#3CC780' - }, - pickable: true - }, - _uid: 210, - type: 'symbol', - children: [] - }, - { - attribute: { - visible: true, - size: 8, - symbolType: 'circle', - lineWidth: 1, - stroke: '#202226', - fillOpacity: 1, - fill: '#1664FF', - x: 600.3947368421053, - y: 242.47732000000002, - imageAttrs: { - fill: '#1664FF' - }, - pickable: true - }, - _uid: 211, - type: 'symbol', - children: [] - }, - { - attribute: { - visible: true, - size: 8, - symbolType: 'circle', - lineWidth: 1, - stroke: '#202226', - fillOpacity: 1, - fill: '#1AC6FF', - x: 600.3947368421053, - y: 207.53424, - imageAttrs: { - fill: '#1AC6FF' - }, - pickable: true - }, - _uid: 212, - type: 'symbol', - children: [] - }, - { - attribute: { - visible: true, - size: 8, - symbolType: 'circle', - lineWidth: 1, - stroke: '#202226', - fillOpacity: 1, - fill: '#FF8A00', - x: 600.3947368421053, - y: 139.93932, - imageAttrs: { - fill: '#FF8A00' - }, - pickable: true - }, - _uid: 213, - type: 'symbol', - children: [] - }, - { - attribute: { - visible: true, - size: 8, - symbolType: 'circle', - lineWidth: 1, - stroke: '#202226', - fillOpacity: 1, - fill: '#3CC780', - x: 600.3947368421053, - y: 70.85476, - imageAttrs: { - fill: '#3CC780' - }, - pickable: true - }, - _uid: 214, - type: 'symbol', - children: [] - }, - { - attribute: { - visible: true, - size: 8, - symbolType: 'circle', - lineWidth: 1, - stroke: '#202226', - fillOpacity: 1, - fill: '#1664FF', - x: 689.3421052631578, - y: 307.22656, - imageAttrs: { - fill: '#1664FF' - }, - pickable: true - }, - _uid: 215, - type: 'symbol', - children: [] - }, - { - attribute: { - visible: true, - size: 8, - symbolType: 'circle', - lineWidth: 1, - stroke: '#202226', - fillOpacity: 1, - fill: '#1AC6FF', - x: 689.3421052631578, - y: 276.6856, - imageAttrs: { - fill: '#1AC6FF' - }, - pickable: true - }, - _uid: 216, - type: 'symbol', - children: [] - }, - { - attribute: { - visible: true, - size: 8, - symbolType: 'circle', - lineWidth: 1, - stroke: '#202226', - fillOpacity: 1, - fill: '#FF8A00', - x: 689.3421052631578, - y: 196.23835999999997, - imageAttrs: { - fill: '#FF8A00' - }, - pickable: true - }, - _uid: 217, - type: 'symbol', - children: [] - }, - { - attribute: { - visible: true, - size: 8, - symbolType: 'circle', - lineWidth: 1, - stroke: '#202226', - fillOpacity: 1, - fill: '#3CC780', - x: 689.3421052631578, - y: 42.611720000000005, - imageAttrs: { - fill: '#3CC780' - }, - pickable: true - }, - _uid: 218, - type: 'symbol', - children: [] - }, - { - attribute: { - visible: true, - size: 8, - symbolType: 'circle', - lineWidth: 1, - stroke: '#202226', - fillOpacity: 1, - fill: '#1664FF', - x: 778.2894736842105, - y: 209.00384, - imageAttrs: { - fill: '#1664FF' - }, - pickable: true - }, - _uid: 219, - type: 'symbol', - children: [] - }, - { - attribute: { - visible: true, - size: 8, - symbolType: 'circle', - lineWidth: 1, - stroke: '#202226', - fillOpacity: 1, - fill: '#1AC6FF', - x: 778.2894736842105, - y: 168.02872, - imageAttrs: { - fill: '#1AC6FF' - }, - pickable: true - }, - _uid: 220, - type: 'symbol', - children: [] - }, - { - attribute: { - visible: true, - size: 8, - symbolType: 'circle', - lineWidth: 1, - stroke: '#202226', - fillOpacity: 1, - fill: '#FF8A00', - x: 778.2894736842105, - y: 98.42979999999999, - imageAttrs: { - fill: '#FF8A00' - }, - pickable: true - }, - _uid: 221, - type: 'symbol', - children: [] - }, - { - attribute: { - visible: true, - size: 8, - symbolType: 'circle', - lineWidth: 1, - stroke: '#202226', - fillOpacity: 1, - fill: '#3CC780', - x: 778.2894736842105, - y: 23.206319999999995, - imageAttrs: { - fill: '#3CC780' - }, - pickable: true - }, - _uid: 222, - type: 'symbol', - children: [] - } - ] - } - ] - } - ] - }, - { - attribute: { - pickable: false, - zIndex: 100 - }, - _uid: 15, - type: 'group', - name: 'axis-bottom_20', - children: [ - { - attribute: { - title: { - space: 8, - padding: 0, - textStyle: { - fontSize: 12, - fill: '#888c93', - fontWeight: 'normal', - fillOpacity: 1, - lineHeight: 15.600000000000001 - }, - autoRotate: false, - angle: null, - shape: {}, - background: {}, - state: { - text: null, - shape: null, - background: null - }, - pickable: true, - childrenPickable: true, - text: 'type', - maxWidth: null - }, - label: { - visible: true, - inside: false, - space: 8, - padding: 0, - style: { - fontSize: 12, - fill: '#bbbdc3', - fontWeight: 'normal', - fillOpacity: 1 - }, - formatMethod: null, - state: null - }, - tick: { - visible: true, - inside: false, - alignWithLabel: true, - length: 4, - style: { - lineWidth: 1, - stroke: '#4b4f54', - strokeOpacity: 1 - }, - state: null - }, - subTick: { - visible: false, - inside: false, - count: 4, - length: 2, - style: { - lineWidth: 1, - stroke: '#4b4f54', - strokeOpacity: 1 - }, - state: null - }, - line: { - visible: true, - style: { - lineWidth: 1, - stroke: '#4b4f54', - strokeOpacity: 1 - }, - startSymbol: {}, - endSymbol: {} - }, - x: 68, - y: 404, - start: { - x: 0, - y: 0 - }, - end: { - x: 845, - y: 0 - }, - items: [ - [ - { - id: 'Nail polish', - label: 'Nail polish', - value: 0.07894736842105263, - rawValue: 'Nail polish' - }, - { - id: 'Eyebrow pencil', - label: 'Eyebrow pencil', - value: 0.18421052631578944, - rawValue: 'Eyebrow pencil' - }, - { - id: 'Rouge', - label: 'Rouge', - value: 0.2894736842105263, - rawValue: 'Rouge' - }, - { - id: 'Lipstick', - label: 'Lipstick', - value: 0.3947368421052632, - rawValue: 'Lipstick' - }, - { - id: 'Eyeshadows', - label: 'Eyeshadows', - value: 0.5, - rawValue: 'Eyeshadows' - }, - { - id: 'Eyeliner', - label: 'Eyeliner', - value: 0.6052631578947368, - rawValue: 'Eyeliner' - }, - { - id: 'Foundation', - label: 'Foundation', - value: 0.7105263157894738, - rawValue: 'Foundation' - }, - { - id: 'Lip gloss', - label: 'Lip gloss', - value: 0.8157894736842104, - rawValue: 'Lip gloss' - }, - { - id: 'Mascara', - label: 'Mascara', - value: 0.9210526315789473, - rawValue: 'Mascara' - } - ] - ], - visible: true, - pickable: true, - orient: 'bottom', - panel: { - state: null - }, - verticalFactor: 1, - verticalLimitSize: 150, - verticalMinSize: null - }, - _uid: 16, - type: 'group', - name: 'axis', - children: [ - { - attribute: { - x: 0, - y: 0, - pickable: false - }, - _uid: 127, - type: 'group', - children: [ - { - attribute: { - x: 0, - y: 0, - zIndex: 1 - }, - _uid: 128, - type: 'group', - name: 'axis-container', - children: [ - { - attribute: { - visible: true, - lineStyle: { - lineWidth: 1, - stroke: '#4b4f54', - strokeOpacity: 1 - }, - startSymbol: { - visible: false, - autoRotate: true, - symbolType: 'triangle', - size: 12, - refX: 0, - refY: 0, - refAngle: 0, - style: { - fill: '#000', - zIndex: 1 - } - }, - endSymbol: { - visible: false, - autoRotate: true, - symbolType: 'triangle', - size: 12, - refX: 0, - refY: 0, - refAngle: 0, - style: { - fill: '#000', - zIndex: 1 - } - }, - points: [ - { - x: 0, - y: 0 - }, - { - x: 845, - y: 0 - } - ] - }, - _uid: 129, - type: 'group', - name: 'axis-line', - children: [ - { - attribute: { - points: [ - { - x: 0, - y: 0 - }, - { - x: 845, - y: 0 - } - ], - lineWidth: 1, - stroke: '#4b4f54', - strokeOpacity: 1, - fill: false, - closePath: false - }, - _uid: 130, - type: 'polygon', - name: 'axis-line-line', - children: [] - } - ] - }, - { - attribute: { - x: 0, - y: 0, - pickable: false - }, - _uid: 131, - type: 'group', - name: 'axis-tick-container', - children: [ - { - attribute: { - points: [ - { - x: 66.71052631578947, - y: 0 - }, - { - x: 66.71052631578947, - y: 4 - } - ], - lineWidth: 1, - stroke: '#4b4f54', - strokeOpacity: 1 - }, - _uid: 132, - type: 'line', - name: 'axis-tick', - children: [] - }, - { - attribute: { - points: [ - { - x: 155.65789473684208, - y: 0 - }, - { - x: 155.65789473684208, - y: 4 - } - ], - lineWidth: 1, - stroke: '#4b4f54', - strokeOpacity: 1 - }, - _uid: 133, - type: 'line', - name: 'axis-tick', - children: [] - }, - { - attribute: { - points: [ - { - x: 244.60526315789474, - y: 0 - }, - { - x: 244.60526315789474, - y: 4 - } - ], - lineWidth: 1, - stroke: '#4b4f54', - strokeOpacity: 1 - }, - _uid: 134, - type: 'line', - name: 'axis-tick', - children: [] - }, - { - attribute: { - points: [ - { - x: 333.5526315789474, - y: 0 - }, - { - x: 333.5526315789474, - y: 4 - } - ], - lineWidth: 1, - stroke: '#4b4f54', - strokeOpacity: 1 - }, - _uid: 135, - type: 'line', - name: 'axis-tick', - children: [] - }, - { - attribute: { - points: [ - { - x: 422.5, - y: 0 - }, - { - x: 422.5, - y: 4 - } - ], - lineWidth: 1, - stroke: '#4b4f54', - strokeOpacity: 1 - }, - _uid: 136, - type: 'line', - name: 'axis-tick', - children: [] - }, - { - attribute: { - points: [ - { - x: 511.4473684210526, - y: 0 - }, - { - x: 511.4473684210526, - y: 4 - } - ], - lineWidth: 1, - stroke: '#4b4f54', - strokeOpacity: 1 - }, - _uid: 137, - type: 'line', - name: 'axis-tick', - children: [] - }, - { - attribute: { - points: [ - { - x: 600.3947368421053, - y: 0 - }, - { - x: 600.3947368421053, - y: 4 - } - ], - lineWidth: 1, - stroke: '#4b4f54', - strokeOpacity: 1 - }, - _uid: 138, - type: 'line', - name: 'axis-tick', - children: [] - }, - { - attribute: { - points: [ - { - x: 689.3421052631578, - y: 0 - }, - { - x: 689.3421052631578, - y: 4 - } - ], - lineWidth: 1, - stroke: '#4b4f54', - strokeOpacity: 1 - }, - _uid: 139, - type: 'line', - name: 'axis-tick', - children: [] - }, - { - attribute: { - points: [ - { - x: 778.2894736842105, - y: 0 - }, - { - x: 778.2894736842105, - y: 4 - } - ], - lineWidth: 1, - stroke: '#4b4f54', - strokeOpacity: 1 - }, - _uid: 140, - type: 'line', - name: 'axis-tick', - children: [] - } - ] - }, - { - attribute: { - x: 0, - y: 0, - pickable: false - }, - _uid: 141, - type: 'group', - name: 'axis-label-container', - children: [ - { - attribute: { - x: 0, - y: 0, - pickable: false - }, - _uid: 142, - type: 'group', - name: 'axis-label-container-layer-0', - children: [ - { - attribute: { - x: 66.71052631578947, - y: 12, - text: 'Nail polish', - lineHeight: 12, - textAlign: 'center', - textBaseline: 'top', - fontSize: 12, - fill: '#bbbdc3', - fontWeight: 'normal', - fillOpacity: 1 - }, - _uid: 143, - type: 'text', - name: 'axis-label', - children: [] - }, - { - attribute: { - x: 155.65789473684208, - y: 12, - text: 'Eyebrow pencil', - lineHeight: 12, - textAlign: 'center', - textBaseline: 'top', - fontSize: 12, - fill: '#bbbdc3', - fontWeight: 'normal', - fillOpacity: 1 - }, - _uid: 144, - type: 'text', - name: 'axis-label', - children: [] - }, - { - attribute: { - x: 244.60526315789474, - y: 12, - text: 'Rouge', - lineHeight: 12, - textAlign: 'center', - textBaseline: 'top', - fontSize: 12, - fill: '#bbbdc3', - fontWeight: 'normal', - fillOpacity: 1 - }, - _uid: 145, - type: 'text', - name: 'axis-label', - children: [] - }, - { - attribute: { - x: 333.5526315789474, - y: 12, - text: 'Lipstick', - lineHeight: 12, - textAlign: 'center', - textBaseline: 'top', - fontSize: 12, - fill: '#bbbdc3', - fontWeight: 'normal', - fillOpacity: 1 - }, - _uid: 146, - type: 'text', - name: 'axis-label', - children: [] - }, - { - attribute: { - x: 422.5, - y: 12, - text: 'Eyeshadows', - lineHeight: 12, - textAlign: 'center', - textBaseline: 'top', - fontSize: 12, - fill: '#bbbdc3', - fontWeight: 'normal', - fillOpacity: 1 - }, - _uid: 147, - type: 'text', - name: 'axis-label', - children: [] - }, - { - attribute: { - x: 511.4473684210526, - y: 12, - text: 'Eyeliner', - lineHeight: 12, - textAlign: 'center', - textBaseline: 'top', - fontSize: 12, - fill: '#bbbdc3', - fontWeight: 'normal', - fillOpacity: 1 - }, - _uid: 148, - type: 'text', - name: 'axis-label', - children: [] - }, - { - attribute: { - x: 600.3947368421053, - y: 12, - text: 'Foundation', - lineHeight: 12, - textAlign: 'center', - textBaseline: 'top', - fontSize: 12, - fill: '#bbbdc3', - fontWeight: 'normal', - fillOpacity: 1 - }, - _uid: 149, - type: 'text', - name: 'axis-label', - children: [] - }, - { - attribute: { - x: 689.3421052631578, - y: 12, - text: 'Lip gloss', - lineHeight: 12, - textAlign: 'center', - textBaseline: 'top', - fontSize: 12, - fill: '#bbbdc3', - fontWeight: 'normal', - fillOpacity: 1 - }, - _uid: 150, - type: 'text', - name: 'axis-label', - children: [] - }, - { - attribute: { - x: 778.2894736842105, - y: 12, - text: 'Mascara', - lineHeight: 12, - textAlign: 'center', - textBaseline: 'top', - fontSize: 12, - fill: '#bbbdc3', - fontWeight: 'normal', - fillOpacity: 1 - }, - _uid: 151, - type: 'text', - name: 'axis-label', - children: [] - } - ] - } - ] - } - ] - } - ] - } - ] - } - ] - }, - { - attribute: { - pickable: false, - zIndex: 100 - }, - _uid: 25, - type: 'group', - name: 'axis-left_23', - children: [ - { - attribute: { - title: { - space: 12, - padding: 0, - textStyle: { - fontSize: 12, - fill: '#888c93', - fontWeight: 'normal', - fillOpacity: 1, - textAlign: 'center', - textBaseline: 'bottom', - lineHeight: 15.600000000000001 - }, - autoRotate: false, - angle: -1.5707963267948966, - shape: {}, - background: {}, - state: { - text: null, - shape: null, - background: null - }, - pickable: true, - childrenPickable: true, - text: 'value', - maxWidth: null - }, - label: { - visible: true, - inside: false, - space: 12, - padding: 0, - style: { - fontSize: 12, - fill: '#bbbdc3', - fontWeight: 'normal', - fillOpacity: 1 - }, - formatMethod: null, - state: null, - autoLimit: true - }, - tick: { - visible: false, - inside: false, - alignWithLabel: true, - length: 4, - style: { - lineWidth: 1, - stroke: '#4b4f54', - strokeOpacity: 1 - }, - state: null - }, - subTick: { - visible: false, - inside: false, - count: 4, - length: 2, - style: { - lineWidth: 1, - stroke: '#4b4f54', - strokeOpacity: 1 - }, - state: null - }, - line: { - visible: false, - style: { - lineWidth: 1, - stroke: '#4b4f54', - strokeOpacity: 1 - }, - startSymbol: {}, - endSymbol: {} - }, - x: 68, - y: 70, - start: { - x: 0, - y: 0 - }, - end: { - x: 0, - y: 334 - }, - items: [ - [ - { - id: 0, - label: 0, - value: 1, - rawValue: 0 + id: '10:00', + label: '10:00', + value: 0.49999999999999994, + rawValue: '10:00' }, { - id: 10000, - label: 10000, - value: 0.7999999999999999, - rawValue: 10000 + id: '12:00', + label: '12:00', + value: 0.6052631578947367, + rawValue: '12:00' }, { - id: 20000, - label: 20000, - value: 0.6, - rawValue: 20000 + id: '14:00', + label: '14:00', + value: 0.7105263157894736, + rawValue: '14:00' }, { - id: 30000, - label: 30000, - value: 0.39999999999999997, - rawValue: 30000 - }, - { - id: 40000, - label: 40000, - value: 0.19999999999999996, - rawValue: 40000 + id: '16:00', + label: '16:00', + value: 0.8157894736842104, + rawValue: '16:00' }, { - id: 50000, - label: 50000, - value: 0, - rawValue: 50000 + id: '18:00', + label: '18:00', + value: 0.9210526315789472, + rawValue: '18:00' } ] ], visible: true, pickable: true, - orient: 'left', + orient: 'bottom', panel: { state: null }, verticalFactor: 1, - verticalLimitSize: 294.3, + verticalLimitSize: 156.6, verticalMinSize: null }, - _uid: 26, + _uid: 293, type: 'group', name: 'axis', children: [ @@ -1955,7 +564,7 @@ const json = { y: 0, pickable: false }, - _uid: 152, + _uid: 382, type: 'group', children: [ { @@ -1964,17 +573,292 @@ const json = { y: 0, zIndex: 1 }, - _uid: 153, + _uid: 383, type: 'group', name: 'axis-container', children: [ + { + attribute: { + visible: true, + lineStyle: { + lineWidth: 1, + stroke: '#d9dde4', + strokeOpacity: 1 + }, + startSymbol: { + visible: false, + autoRotate: true, + symbolType: 'triangle', + size: 12, + refX: 0, + refY: 0, + refAngle: 0, + style: { + fill: '#000', + zIndex: 1 + } + }, + endSymbol: { + visible: false, + autoRotate: true, + symbolType: 'triangle', + size: 12, + refX: 0, + refY: 0, + refAngle: 0, + style: { + fill: '#000', + zIndex: 1 + } + }, + points: [ + { + x: 0, + y: 0 + }, + { + x: 779, + y: 0 + } + ] + }, + _uid: 384, + type: 'group', + name: 'axis-line', + children: [ + { + attribute: { + points: [ + { + x: 0, + y: 0 + }, + { + x: 779, + y: 0 + } + ], + lineWidth: 1, + stroke: '#d9dde4', + strokeOpacity: 1, + fill: false, + closePath: false + }, + _uid: 385, + type: 'polygon', + name: 'axis-line-line', + children: [] + } + ] + }, + { + attribute: { + x: 0, + y: 0, + pickable: false + }, + _uid: 386, + type: 'group', + name: 'axis-tick-container', + children: [ + { + attribute: { + points: [ + { + x: 61.499999999999964, + y: 0 + }, + { + x: 61.499999999999964, + y: 3.9999999999999996 + } + ], + lineWidth: 1, + stroke: '#d9dde4', + strokeOpacity: 1 + }, + _uid: 387, + type: 'line', + name: 'axis-tick', + children: [] + }, + { + attribute: { + points: [ + { + x: 143.49999999999997, + y: 0 + }, + { + x: 143.49999999999997, + y: 3.9999999999999996 + } + ], + lineWidth: 1, + stroke: '#d9dde4', + strokeOpacity: 1 + }, + _uid: 388, + type: 'line', + name: 'axis-tick', + children: [] + }, + { + attribute: { + points: [ + { + x: 225.49999999999997, + y: 0 + }, + { + x: 225.49999999999997, + y: 3.9999999999999996 + } + ], + lineWidth: 1, + stroke: '#d9dde4', + strokeOpacity: 1 + }, + _uid: 389, + type: 'line', + name: 'axis-tick', + children: [] + }, + { + attribute: { + points: [ + { + x: 307.49999999999994, + y: 0 + }, + { + x: 307.49999999999994, + y: 3.9999999999999996 + } + ], + lineWidth: 1, + stroke: '#d9dde4', + strokeOpacity: 1 + }, + _uid: 390, + type: 'line', + name: 'axis-tick', + children: [] + }, + { + attribute: { + points: [ + { + x: 389.49999999999994, + y: 0 + }, + { + x: 389.49999999999994, + y: 3.9999999999999996 + } + ], + lineWidth: 1, + stroke: '#d9dde4', + strokeOpacity: 1 + }, + _uid: 391, + type: 'line', + name: 'axis-tick', + children: [] + }, + { + attribute: { + points: [ + { + x: 471.4999999999999, + y: 0 + }, + { + x: 471.4999999999999, + y: 3.9999999999999996 + } + ], + lineWidth: 1, + stroke: '#d9dde4', + strokeOpacity: 1 + }, + _uid: 392, + type: 'line', + name: 'axis-tick', + children: [] + }, + { + attribute: { + points: [ + { + x: 553.4999999999999, + y: 0 + }, + { + x: 553.4999999999999, + y: 3.9999999999999996 + } + ], + lineWidth: 1, + stroke: '#d9dde4', + strokeOpacity: 1 + }, + _uid: 393, + type: 'line', + name: 'axis-tick', + children: [] + }, + { + attribute: { + points: [ + { + x: 635.4999999999999, + y: 0 + }, + { + x: 635.4999999999999, + y: 3.9999999999999996 + } + ], + lineWidth: 1, + stroke: '#d9dde4', + strokeOpacity: 1 + }, + _uid: 394, + type: 'line', + name: 'axis-tick', + children: [] + }, + { + attribute: { + points: [ + { + x: 717.4999999999999, + y: 0 + }, + { + x: 717.4999999999999, + y: 3.9999999999999996 + } + ], + lineWidth: 1, + stroke: '#d9dde4', + strokeOpacity: 1 + }, + _uid: 395, + type: 'line', + name: 'axis-tick', + children: [] + } + ] + }, { attribute: { x: 0, y: 0, pickable: false }, - _uid: 154, + _uid: 396, type: 'group', name: 'axis-label-container', children: [ @@ -1984,114 +868,168 @@ const json = { y: 0, pickable: false }, - _uid: 155, + _uid: 397, type: 'group', name: 'axis-label-container-layer-0', children: [ { attribute: { - x: -12, - y: 334, - text: 0, + x: 61.499999999999964, + y: 11.999999999999998, + text: '2:00', lineHeight: 12, - textAlign: 'end', - textBaseline: 'middle', + textAlign: 'center', + textBaseline: 'top', fontSize: 12, - fill: '#bbbdc3', + fill: '#89909d', fontWeight: 'normal', fillOpacity: 1 }, - _uid: 156, + _uid: 398, type: 'text', name: 'axis-label', children: [] }, { attribute: { - x: -12, - y: 267.2, - text: 10000, + x: 143.49999999999997, + y: 11.999999999999998, + text: '4:00', lineHeight: 12, - textAlign: 'end', - textBaseline: 'middle', + textAlign: 'center', + textBaseline: 'top', fontSize: 12, - fill: '#bbbdc3', + fill: '#89909d', fontWeight: 'normal', fillOpacity: 1 }, - _uid: 157, + _uid: 399, type: 'text', name: 'axis-label', children: [] }, { attribute: { - x: -12, - y: 200.4, - text: 20000, + x: 225.49999999999997, + y: 11.999999999999998, + text: '6:00', lineHeight: 12, - textAlign: 'end', - textBaseline: 'middle', + textAlign: 'center', + textBaseline: 'top', fontSize: 12, - fill: '#bbbdc3', + fill: '#89909d', fontWeight: 'normal', fillOpacity: 1 }, - _uid: 158, + _uid: 400, type: 'text', name: 'axis-label', children: [] }, { attribute: { - x: -12, - y: 133.6, - text: 30000, + x: 307.49999999999994, + y: 11.999999999999998, + text: '8:00', lineHeight: 12, - textAlign: 'end', - textBaseline: 'middle', + textAlign: 'center', + textBaseline: 'top', fontSize: 12, - fill: '#bbbdc3', + fill: '#89909d', fontWeight: 'normal', fillOpacity: 1 }, - _uid: 159, + _uid: 401, type: 'text', name: 'axis-label', children: [] }, { attribute: { - x: -12, - y: 66.79999999999998, - text: 40000, + x: 389.49999999999994, + y: 11.999999999999998, + text: '10:00', lineHeight: 12, - textAlign: 'end', - textBaseline: 'middle', + textAlign: 'center', + textBaseline: 'top', fontSize: 12, - fill: '#bbbdc3', + fill: '#89909d', fontWeight: 'normal', fillOpacity: 1 }, - _uid: 160, + _uid: 402, type: 'text', name: 'axis-label', children: [] }, { attribute: { - x: -12, - y: 0, - text: 50000, + x: 471.4999999999999, + y: 11.999999999999998, + text: '12:00', lineHeight: 12, - textAlign: 'end', - textBaseline: 'middle', + textAlign: 'center', + textBaseline: 'top', + fontSize: 12, + fill: '#89909d', + fontWeight: 'normal', + fillOpacity: 1 + }, + _uid: 403, + type: 'text', + name: 'axis-label', + children: [] + }, + { + attribute: { + x: 553.4999999999999, + y: 11.999999999999998, + text: '14:00', + lineHeight: 12, + textAlign: 'center', + textBaseline: 'top', + fontSize: 12, + fill: '#89909d', + fontWeight: 'normal', + fillOpacity: 1 + }, + _uid: 404, + type: 'text', + name: 'axis-label', + children: [] + }, + { + attribute: { + x: 635.4999999999999, + y: 11.999999999999998, + text: '16:00', + lineHeight: 12, + textAlign: 'center', + textBaseline: 'top', + fontSize: 12, + fill: '#89909d', + fontWeight: 'normal', + fillOpacity: 1 + }, + _uid: 405, + type: 'text', + name: 'axis-label', + children: [] + }, + { + attribute: { + x: 717.4999999999999, + y: 11.999999999999998, + text: '18:00', + lineHeight: 12, + textAlign: 'center', + textBaseline: 'top', fontSize: 12, - fill: '#bbbdc3', + fill: '#89909d', fontWeight: 'normal', fillOpacity: 1 }, - _uid: 161, + _uid: 406, type: 'text', name: 'axis-label', children: [] @@ -2108,199 +1046,14 @@ const json = { } ] }, - { - attribute: { - pickable: false, - zIndex: 50 - }, - _uid: 35, - type: 'group', - name: 'axis-left-grid_24', - children: [ - { - attribute: { - style: { - lineWidth: 1, - stroke: '#404349', - strokeOpacity: 1, - lineDash: [] - }, - subGrid: { - visible: false, - style: { - lineWidth: 1, - stroke: '#404349', - strokeOpacity: 1, - lineDash: [4, 4] - }, - type: 'line' - }, - visible: true, - x: 68, - y: 70, - pickable: true, - type: 'line', - start: { - x: 0, - y: 0 - }, - end: { - x: 0, - y: 334 - }, - items: [ - { - id: 0, - label: 0, - value: 1, - rawValue: 0 - }, - { - id: 10000, - label: 10000, - value: 0.7999999999999999, - rawValue: 10000 - }, - { - id: 20000, - label: 20000, - value: 0.6, - rawValue: 20000 - }, - { - id: 30000, - label: 30000, - value: 0.39999999999999997, - rawValue: 30000 - }, - { - id: 40000, - label: 40000, - value: 0.19999999999999996, - rawValue: 40000 - }, - { - id: 50000, - label: 50000, - value: 0, - rawValue: 50000 - } - ], - verticalFactor: 1, - depth: 0, - length: 845 - }, - _uid: 36, - type: 'group', - name: 'axis-grid', - children: [ - { - attribute: { - x: 0, - y: 0, - pickable: false - }, - _uid: 162, - type: 'group', - children: [ - { - attribute: { - path: 'M0,334L845,334', - z: 0, - lineWidth: 1, - stroke: '#404349', - strokeOpacity: 1, - lineDash: [] - }, - _uid: 163, - type: 'path', - name: 'axis-grid-line', - children: [] - }, - { - attribute: { - path: 'M0,267.2L845,267.2', - z: 0, - lineWidth: 1, - stroke: '#404349', - strokeOpacity: 1, - lineDash: [] - }, - _uid: 164, - type: 'path', - name: 'axis-grid-line', - children: [] - }, - { - attribute: { - path: 'M0,200.4L845,200.4', - z: 0, - lineWidth: 1, - stroke: '#404349', - strokeOpacity: 1, - lineDash: [] - }, - _uid: 165, - type: 'path', - name: 'axis-grid-line', - children: [] - }, - { - attribute: { - path: 'M0,133.6L845,133.6', - z: 0, - lineWidth: 1, - stroke: '#404349', - strokeOpacity: 1, - lineDash: [] - }, - _uid: 166, - type: 'path', - name: 'axis-grid-line', - children: [] - }, - { - attribute: { - path: 'M0,66.79999999999998L845,66.79999999999998', - z: 0, - lineWidth: 1, - stroke: '#404349', - strokeOpacity: 1, - lineDash: [] - }, - _uid: 167, - type: 'path', - name: 'axis-grid-line', - children: [] - }, - { - attribute: { - path: 'M0,0L845,0', - z: 0, - lineWidth: 1, - stroke: '#404349', - strokeOpacity: 1, - lineDash: [] - }, - _uid: 168, - type: 'path', - name: 'axis-grid-line', - children: [] - } - ] - } - ] - } - ] - }, { attribute: { pickable: false, zIndex: 100 }, - _uid: 39, + _uid: 302, type: 'group', - name: 'axis-right_27', + name: 'axis-left_64', children: [ { attribute: { @@ -2309,7 +1062,7 @@ const json = { padding: 0, textStyle: { fontSize: 12, - fill: '#888c93', + fill: '#606773', fontWeight: 'normal', fillOpacity: 1, textAlign: 'center', @@ -2317,7 +1070,7 @@ const json = { lineHeight: 15.600000000000001 }, autoRotate: false, - angle: 1.5707963267948966, + angle: -1.5707963267948966, shape: {}, background: {}, state: { @@ -2337,7 +1090,7 @@ const json = { padding: 0, style: { fontSize: 12, - fill: '#bbbdc3', + fill: '#89909d', fontWeight: 'normal', fillOpacity: 1 }, @@ -2352,7 +1105,7 @@ const json = { length: 4, style: { lineWidth: 1, - stroke: '#4b4f54', + stroke: '#d9dde4', strokeOpacity: 1 }, state: null @@ -2364,7 +1117,7 @@ const json = { length: 2, style: { lineWidth: 1, - stroke: '#4b4f54', + stroke: '#d9dde4', strokeOpacity: 1 }, state: null @@ -2373,21 +1126,21 @@ const json = { visible: false, style: { lineWidth: 1, - stroke: '#4b4f54', + stroke: '#d9dde4', strokeOpacity: 1 }, startSymbol: {}, endSymbol: {} }, - x: 913, - y: 70, + x: 47, + y: 26, start: { x: 0, y: 0 }, end: { x: 0, - y: 334 + y: 452 }, items: [ [ @@ -2398,48 +1151,42 @@ const json = { rawValue: 0 }, { - id: 10000, - label: 10000, - value: 0.7999999999999999, - rawValue: 10000 - }, - { - id: 20000, - label: 20000, - value: 0.6, - rawValue: 20000 + id: 5, + label: 5, + value: 0.75, + rawValue: 5 }, { - id: 30000, - label: 30000, - value: 0.39999999999999997, - rawValue: 30000 + id: 10, + label: 10, + value: 0.5, + rawValue: 10 }, { - id: 40000, - label: 40000, - value: 0.19999999999999996, - rawValue: 40000 + id: 15, + label: 15, + value: 0.25, + rawValue: 15 }, { - id: 50000, - label: 50000, + id: 20, + label: 20, value: 0, - rawValue: 50000 + rawValue: 20 } ] ], visible: true, pickable: true, - orient: 'right', + orient: 'left', panel: { state: null }, - verticalFactor: -1, - verticalLimitSize: 294.3, + verticalFactor: 1, + verticalLimitSize: 253.8, verticalMinSize: null }, - _uid: 40, + _uid: 303, type: 'group', name: 'axis', children: [ @@ -2449,7 +1196,7 @@ const json = { y: 0, pickable: false }, - _uid: 169, + _uid: 407, type: 'group', children: [ { @@ -2458,7 +1205,7 @@ const json = { y: 0, zIndex: 1 }, - _uid: 170, + _uid: 408, type: 'group', name: 'axis-container', children: [ @@ -2468,7 +1215,7 @@ const json = { y: 0, pickable: false }, - _uid: 171, + _uid: 409, type: 'group', name: 'axis-label-container', children: [ @@ -2478,114 +1225,96 @@ const json = { y: 0, pickable: false }, - _uid: 172, + _uid: 410, type: 'group', name: 'axis-label-container-layer-0', children: [ { attribute: { - x: 12, - y: 334, + x: -12, + y: 452, text: 0, lineHeight: 12, - textAlign: 'start', - textBaseline: 'middle', - fontSize: 12, - fill: '#bbbdc3', - fontWeight: 'normal', - fillOpacity: 1 - }, - _uid: 173, - type: 'text', - name: 'axis-label', - children: [] - }, - { - attribute: { - x: 12, - y: 267.2, - text: 10000, - lineHeight: 12, - textAlign: 'start', + textAlign: 'end', textBaseline: 'middle', fontSize: 12, - fill: '#bbbdc3', + fill: '#89909d', fontWeight: 'normal', fillOpacity: 1 }, - _uid: 174, + _uid: 411, type: 'text', name: 'axis-label', children: [] }, { attribute: { - x: 12, - y: 200.4, - text: 20000, + x: -12, + y: 339, + text: 5, lineHeight: 12, - textAlign: 'start', + textAlign: 'end', textBaseline: 'middle', fontSize: 12, - fill: '#bbbdc3', + fill: '#89909d', fontWeight: 'normal', fillOpacity: 1 }, - _uid: 175, + _uid: 412, type: 'text', name: 'axis-label', children: [] }, { attribute: { - x: 12, - y: 133.6, - text: 30000, + x: -12, + y: 226, + text: 10, lineHeight: 12, - textAlign: 'start', + textAlign: 'end', textBaseline: 'middle', fontSize: 12, - fill: '#bbbdc3', + fill: '#89909d', fontWeight: 'normal', fillOpacity: 1 }, - _uid: 176, + _uid: 413, type: 'text', name: 'axis-label', children: [] }, { attribute: { - x: 12, - y: 66.79999999999998, - text: 40000, + x: -12, + y: 113, + text: 15, lineHeight: 12, - textAlign: 'start', + textAlign: 'end', textBaseline: 'middle', fontSize: 12, - fill: '#bbbdc3', + fill: '#89909d', fontWeight: 'normal', fillOpacity: 1 }, - _uid: 177, + _uid: 414, type: 'text', name: 'axis-label', children: [] }, { attribute: { - x: 12, + x: -12, y: 0, - text: 50000, + text: 20, lineHeight: 12, - textAlign: 'start', + textAlign: 'end', textBaseline: 'middle', fontSize: 12, - fill: '#bbbdc3', + fill: '#89909d', fontWeight: 'normal', fillOpacity: 1 }, - _uid: 178, + _uid: 415, type: 'text', name: 'axis-label', children: [] @@ -2607,15 +1336,15 @@ const json = { pickable: false, zIndex: 50 }, - _uid: 49, + _uid: 312, type: 'group', - name: 'axis-right-grid_28', + name: 'axis-left-grid_65', children: [ { attribute: { style: { lineWidth: 1, - stroke: '#404349', + stroke: '#f1f2f5', strokeOpacity: 1, lineDash: [] }, @@ -2623,15 +1352,15 @@ const json = { visible: false, style: { lineWidth: 1, - stroke: '#404349', + stroke: '#f1f2f5', strokeOpacity: 1, lineDash: [4, 4] }, type: 'line' }, visible: true, - x: 913, - y: 70, + x: 47, + y: 26, pickable: true, type: 'line', start: { @@ -2640,7 +1369,7 @@ const json = { }, end: { x: 0, - y: 334 + y: 452 }, items: [ { @@ -2650,41 +1379,35 @@ const json = { rawValue: 0 }, { - id: 10000, - label: 10000, - value: 0.7999999999999999, - rawValue: 10000 - }, - { - id: 20000, - label: 20000, - value: 0.6, - rawValue: 20000 + id: 5, + label: 5, + value: 0.75, + rawValue: 5 }, { - id: 30000, - label: 30000, - value: 0.39999999999999997, - rawValue: 30000 + id: 10, + label: 10, + value: 0.5, + rawValue: 10 }, { - id: 40000, - label: 40000, - value: 0.19999999999999996, - rawValue: 40000 + id: 15, + label: 15, + value: 0.25, + rawValue: 15 }, { - id: 50000, - label: 50000, + id: 20, + label: 20, value: 0, - rawValue: 50000 + rawValue: 20 } ], - verticalFactor: -1, + verticalFactor: 1, depth: 0, - length: 845 + length: 779 }, - _uid: 50, + _uid: 313, type: 'group', name: 'axis-grid', children: [ @@ -2694,89 +1417,75 @@ const json = { y: 0, pickable: false }, - _uid: 179, + _uid: 416, type: 'group', children: [ { attribute: { - path: 'M0,334L-845,334', - z: 0, - lineWidth: 1, - stroke: '#404349', - strokeOpacity: 1, - lineDash: [] - }, - _uid: 180, - type: 'path', - name: 'axis-grid-line', - children: [] - }, - { - attribute: { - path: 'M0,267.2L-845,267.2', + path: 'M0,452L779,452', z: 0, lineWidth: 1, - stroke: '#404349', + stroke: '#f1f2f5', strokeOpacity: 1, lineDash: [] }, - _uid: 181, + _uid: 417, type: 'path', name: 'axis-grid-line', children: [] }, { attribute: { - path: 'M0,200.4L-845,200.4', + path: 'M0,339L779,339', z: 0, lineWidth: 1, - stroke: '#404349', + stroke: '#f1f2f5', strokeOpacity: 1, lineDash: [] }, - _uid: 182, + _uid: 418, type: 'path', name: 'axis-grid-line', children: [] }, { attribute: { - path: 'M0,133.6L-845,133.6', + path: 'M0,226L779,226', z: 0, lineWidth: 1, - stroke: '#404349', + stroke: '#f1f2f5', strokeOpacity: 1, lineDash: [] }, - _uid: 183, + _uid: 419, type: 'path', name: 'axis-grid-line', children: [] }, { attribute: { - path: 'M0,66.79999999999998L-845,66.79999999999998', + path: 'M0,113L779,113', z: 0, lineWidth: 1, - stroke: '#404349', + stroke: '#f1f2f5', strokeOpacity: 1, lineDash: [] }, - _uid: 184, + _uid: 420, type: 'path', name: 'axis-grid-line', children: [] }, { attribute: { - path: 'M0,0L-845,0', + path: 'M0,0L779,0', z: 0, lineWidth: 1, - stroke: '#404349', + stroke: '#f1f2f5', strokeOpacity: 1, lineDash: [] }, - _uid: 185, + _uid: 421, type: 'path', name: 'axis-grid-line', children: [] @@ -2786,667 +1495,6 @@ const json = { ] } ] - }, - { - attribute: { - textStyle: { - ellipsis: '...', - fill: '#fdfdfd', - fontSize: 16, - fontWeight: 'bold', - textAlign: 'left', - textBaseline: 'top', - width: 941, - lineHeight: 24 - }, - subtextStyle: { - ellipsis: '...', - fill: '#888c93', - fontSize: 14, - fontWeight: 'normal', - textAlign: 'left', - textBaseline: 'top', - width: 941, - lineHeight: 21 - }, - text: 'Stacked area chart of cosmetic products sales', - subtext: '', - x: 20, - y: 24, - width: 941, - align: 'left', - verticalAlign: 'top' - }, - _uid: 55, - type: 'group', - name: 'title', - children: [ - { - attribute: { - x: 0, - y: 0, - zIndex: 1, - width: 941, - height: 26 - }, - _uid: 56, - type: 'group', - name: 'title-container', - children: [ - { - attribute: { - text: ['Stacked area chart of cosmetic products sales'], - ellipsis: '...', - fill: '#fdfdfd', - fontSize: 16, - fontWeight: 'bold', - textAlign: 'left', - textBaseline: 'top', - width: 941, - lineHeight: 24, - maxLineWidth: 941, - x: 0, - y: 0 - }, - _uid: 57, - type: 'text', - name: 'mainTitle', - children: [] - }, - { - attribute: { - text: [''], - ellipsis: '...', - fill: '#888c93', - fontSize: 14, - fontWeight: 'normal', - textAlign: 'left', - textBaseline: 'top', - width: 941, - lineHeight: 21, - maxLineWidth: 941, - x: 0, - y: 26 - }, - _uid: 58, - type: 'text', - name: 'subTitle', - children: [] - } - ] - } - ] - }, - { - attribute: { - layout: 'horizontal', - title: { - align: 'start', - space: 12, - textStyle: { - fontSize: 12, - fontWeight: 'bold', - fill: '#2C3542' - } - }, - item: { - spaceCol: 10, - spaceRow: 6, - shape: { - space: 6, - style: { - size: 10, - cursor: 'pointer', - lineWidth: 0, - fillOpacity: 1, - opacity: 1 - }, - state: { - selectedHover: { - opacity: 0.85 - }, - unSelected: { - opacity: 1, - fillOpacity: 0.2 - } - } - }, - label: { - space: 6, - style: { - fontSize: 12, - fill: '#888c93', - cursor: 'pointer', - lineHeight: 15.600000000000001, - opacity: 1 - }, - state: { - selectedHover: { - opacity: 0.85 - }, - unSelected: { - fill: '#55595f', - opacity: 1 - } - } - }, - value: { - alignRight: false, - style: { - fontSize: 12, - fill: '#ccc', - cursor: 'pointer' - }, - state: { - selectedHover: { - opacity: 0.85 - }, - unSelected: { - fill: '#D8D8D8' - } - } - }, - background: { - style: { - cursor: 'pointer' - }, - state: { - selectedHover: { - fill: '#404349' - }, - unSelectedHover: { - fill: '#404349' - } - } - }, - focus: false, - focusIconStyle: { - size: 10, - symbolType: - 'M8 1C11.866 1 15 4.13401 15 8C15 11.866 11.866 15 8 15C4.13401 15 1 11.866 1 8C1 4.13401 4.13401 1 8 1ZM8.75044 2.55077L8.75 3.75H7.25L7.25006 2.5507C4.81247 2.88304 2.88304 4.81247 2.5507 7.25006L3.75 7.25V8.75L2.55077 8.75044C2.8833 11.1878 4.81264 13.117 7.25006 13.4493L7.25 12.25H8.75L8.75044 13.4492C11.1876 13.1167 13.1167 11.1876 13.4492 8.75044L12.25 8.75V7.25L13.4493 7.25006C13.117 4.81264 11.1878 2.8833 8.75044 2.55077ZM8 5.5C9.38071 5.5 10.5 6.61929 10.5 8C10.5 9.38071 9.38071 10.5 8 10.5C6.61929 10.5 5.5 9.38071 5.5 8C5.5 6.61929 6.61929 5.5 8 5.5ZM8 7C7.44772 7 7 7.44772 7 8C7 8.55228 7.44772 9 8 9C8.55228 9 9 8.55228 9 8C9 7.44772 8.55228 7 8 7Z', - fill: '#333', - cursor: 'pointer' - }, - visible: true, - padding: { - right: 2, - bottom: 2, - left: 2, - top: 2 - } - }, - autoPage: true, - pager: { - space: 12, - handler: { - style: { - size: 10 - }, - space: 4 - } - }, - hover: true, - select: true, - selectMode: 'multiple', - allowAllCanceled: false, - items: [ - { - label: 'Africa', - shape: { - fill: '#1664FF', - symbolType: 'square', - stroke: ['#1664FF', false, false, false], - fillOpacity: 0.2, - strokeOpacity: 1, - opacity: 1, - texture: null, - texturePadding: null, - textureSize: null, - textureColor: null, - innerBorder: null, - outerBorder: null - }, - id: 'Africa', - index: 0 - }, - { - label: 'EU', - shape: { - fill: '#1AC6FF', - symbolType: 'square', - stroke: ['#1AC6FF', false, false, false], - fillOpacity: 0.2, - strokeOpacity: 1, - opacity: 1, - texture: null, - texturePadding: null, - textureSize: null, - textureColor: null, - innerBorder: null, - outerBorder: null - }, - id: 'EU', - index: 1 - }, - { - label: 'China', - shape: { - fill: '#FF8A00', - symbolType: 'square', - stroke: ['#FF8A00', false, false, false], - fillOpacity: 0.2, - strokeOpacity: 1, - opacity: 1, - texture: null, - texturePadding: null, - textureSize: null, - textureColor: null, - innerBorder: null, - outerBorder: null - }, - id: 'China', - index: 2 - }, - { - label: 'USA', - shape: { - fill: '#3CC780', - symbolType: 'square', - stroke: ['#3CC780', false, false, false], - fillOpacity: 0.2, - strokeOpacity: 1, - opacity: 1, - texture: null, - texturePadding: null, - textureSize: null, - textureColor: null, - innerBorder: null, - outerBorder: null - }, - id: 'USA', - index: 3 - } - ], - zIndex: 500, - maxWidth: 893, - maxHeight: 394, - defaultSelected: ['Africa', 'EU', 'China', 'USA'], - width: 58.083953857421875, - height: 27.400000000000002, - dx: 414.95802307128906, - dy: 0, - x: 44, - y: 444 - }, - _uid: 59, - type: 'group', - name: 'legend', - children: [ - { - attribute: { - x: 0, - y: 0, - pickable: true, - childrenPickable: true - }, - _uid: 60, - type: 'group', - name: 'innerView', - children: [ - { - attribute: { - x: 0, - y: 0 - }, - _uid: 61, - type: 'group', - children: [ - { - attribute: { - x: 0, - y: 0, - cursor: 'pointer', - width: 53.083953857421875, - height: 19.6 - }, - _uid: 62, - type: 'group', - name: 'legendItem', - children: [ - { - attribute: { - x: 7, - y: 9.8, - pickable: false - }, - _uid: 63, - type: 'group', - children: [ - { - attribute: { - x: 0, - y: 0, - symbolType: 'square', - strokeBoundsBuffer: 0, - fill: '#1664FF', - stroke: ['#1664FF', false, false, false], - fillOpacity: 1, - strokeOpacity: 1, - opacity: 1, - texture: null, - texturePadding: null, - textureSize: null, - textureColor: null, - innerBorder: null, - outerBorder: null, - size: 10, - cursor: 'pointer', - lineWidth: 0 - }, - _uid: 64, - type: 'symbol', - name: 'legendItemShape', - children: [] - }, - { - attribute: { - x: 11, - y: 0, - textAlign: 'start', - textBaseline: 'middle', - lineHeight: 15.600000000000001, - fontSize: 12, - fill: '#888c93', - cursor: 'pointer', - opacity: 1, - text: 'Africa' - }, - _uid: 65, - type: 'text', - name: 'legendItemLabel', - children: [] - } - ] - } - ] - }, - { - attribute: { - x: 63.083953857421875, - y: 0, - cursor: 'pointer', - width: 36.21199035644531, - height: 19.6 - }, - _uid: 66, - type: 'group', - name: 'legendItem', - children: [ - { - attribute: { - x: 7, - y: 9.8, - pickable: false - }, - _uid: 67, - type: 'group', - children: [ - { - attribute: { - x: 0, - y: 0, - symbolType: 'square', - strokeBoundsBuffer: 0, - fill: '#1AC6FF', - stroke: ['#1AC6FF', false, false, false], - fillOpacity: 1, - strokeOpacity: 1, - opacity: 1, - texture: null, - texturePadding: null, - textureSize: null, - textureColor: null, - innerBorder: null, - outerBorder: null, - size: 10, - cursor: 'pointer', - lineWidth: 0 - }, - _uid: 68, - type: 'symbol', - name: 'legendItemShape', - children: [] - }, - { - attribute: { - x: 11, - y: 0, - textAlign: 'start', - textBaseline: 'middle', - lineHeight: 15.600000000000001, - fontSize: 12, - fill: '#888c93', - cursor: 'pointer', - opacity: 1, - text: 'EU' - }, - _uid: 69, - type: 'text', - name: 'legendItemLabel', - children: [] - } - ] - } - ] - }, - { - attribute: { - x: 109.29594421386719, - y: 0, - cursor: 'pointer', - width: 51.895965576171875, - height: 19.6 - }, - _uid: 70, - type: 'group', - name: 'legendItem', - children: [ - { - attribute: { - x: 7, - y: 9.8, - pickable: false - }, - _uid: 71, - type: 'group', - children: [ - { - attribute: { - x: 0, - y: 0, - symbolType: 'square', - strokeBoundsBuffer: 0, - fill: '#FF8A00', - stroke: ['#FF8A00', false, false, false], - fillOpacity: 1, - strokeOpacity: 1, - opacity: 1, - texture: null, - texturePadding: null, - textureSize: null, - textureColor: null, - innerBorder: null, - outerBorder: null, - size: 10, - cursor: 'pointer', - lineWidth: 0 - }, - _uid: 72, - type: 'symbol', - name: 'legendItemShape', - children: [] - }, - { - attribute: { - x: 11, - y: 0, - textAlign: 'start', - textBaseline: 'middle', - lineHeight: 15.600000000000001, - fontSize: 12, - fill: '#888c93', - cursor: 'pointer', - opacity: 1, - text: 'China' - }, - _uid: 73, - type: 'text', - name: 'legendItemLabel', - children: [] - } - ] - } - ] - }, - { - attribute: { - x: 171.19190979003906, - y: 0, - cursor: 'pointer', - width: 44.035980224609375, - height: 19.6 - }, - _uid: 74, - type: 'group', - name: 'legendItem', - children: [ - { - attribute: { - x: 7, - y: 9.8, - pickable: false - }, - _uid: 75, - type: 'group', - children: [ - { - attribute: { - x: 0, - y: 0, - symbolType: 'square', - strokeBoundsBuffer: 0, - fill: '#3CC780', - stroke: ['#3CC780', false, false, false], - fillOpacity: 1, - strokeOpacity: 1, - opacity: 1, - texture: null, - texturePadding: null, - textureSize: null, - textureColor: null, - innerBorder: null, - outerBorder: null, - size: 10, - cursor: 'pointer', - lineWidth: 0 - }, - _uid: 76, - type: 'symbol', - name: 'legendItemShape', - children: [] - }, - { - attribute: { - x: 11, - y: 0, - textAlign: 'start', - textBaseline: 'middle', - lineHeight: 15.600000000000001, - fontSize: 12, - fill: '#888c93', - cursor: 'pointer', - opacity: 1, - text: 'USA' - }, - _uid: 77, - type: 'text', - name: 'legendItemLabel', - children: [] - } - ] - } - ] - } - ] - } - ] - } - ] - }, - { - attribute: { - direction: 'horizontal', - round: true, - sliderSize: 20, - sliderStyle: { - fill: '#ffffff', - fillOpacity: 0.5 - }, - railStyle: { - fill: 'rgba(0, 0, 0, .0)' - }, - padding: 2, - scrollRange: [0, 1], - zIndex: 500, - x: 68, - y: 428, - width: 845, - height: 0, - range: [0, 1] - }, - _uid: 123, - type: 'group', - name: 'scrollbar', - children: [ - { - attribute: {}, - _uid: 124, - type: 'group', - name: 'scrollbar-container', - children: [ - { - attribute: { - x: 0, - y: 0, - width: 845, - height: 0, - fill: 'rgba(0, 0, 0, .0)' - }, - _uid: 125, - type: 'rect', - name: 'scrollbar-rail', - children: [] - }, - { - attribute: { - x: 2, - y: 2, - width: 841, - height: -4, - cornerRadius: -4, - fill: '#ffffff', - fillOpacity: 0.5, - boundsPadding: [2, 2, 2, 2], - pickMode: 'imprecise' - }, - _uid: 126, - type: 'rect', - name: 'slider', - children: [] - } - ] - } - ] } ] } From 791b4475d9446a6e673839f0b1acecdf931faba1 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Mon, 20 Nov 2023 18:36:12 +0800 Subject: [PATCH 32/40] feat: upgrade vutils --- common/config/rush/pnpm-lock.yaml | 42 +++++++++++------------ docs/demos/package.json | 2 +- docs/package.json | 2 +- packages/react-vrender-utils/package.json | 2 +- packages/react-vrender/package.json | 2 +- packages/vrender-components/package.json | 6 ++-- packages/vrender-core/package.json | 2 +- packages/vrender-kits/package.json | 2 +- packages/vrender/package.json | 2 +- 9 files changed, 31 insertions(+), 31 deletions(-) diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 50a398b01..241a2ed22 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -15,7 +15,7 @@ importers: '@visactor/vchart': 1.3.0 '@visactor/vgrammar': ~0.5.7 '@visactor/vrender': workspace:0.16.13 - '@visactor/vutils': 0.16.8-alpha.1 + '@visactor/vutils': 0.16.12 '@vitejs/plugin-react': 3.1.0 axios: ^1.4.0 chalk: ^3.0.0 @@ -38,7 +38,7 @@ importers: '@visactor/vchart': 1.3.0 '@visactor/vgrammar': 0.5.7 '@visactor/vrender': link:../packages/vrender - '@visactor/vutils': 0.16.8-alpha.1 + '@visactor/vutils': 0.16.12 axios: 1.6.1 highlight.js: 11.9.0 lodash: 4.17.21 @@ -72,7 +72,7 @@ importers: '@types/react-dom': ^18.0.0 '@types/react-reconciler': ^0.28.2 '@visactor/vrender': workspace:0.16.13 - '@visactor/vutils': 0.16.8-alpha.1 + '@visactor/vutils': 0.16.12 '@vitejs/plugin-react': 3.1.0 eslint: ~8.18.0 react: ^18.0.0 @@ -83,7 +83,7 @@ importers: vite: 3.2.6 dependencies: '@visactor/vrender': link:../vrender - '@visactor/vutils': 0.16.8-alpha.1 + '@visactor/vutils': 0.16.12 react-reconciler: 0.29.0_react@18.2.0 tslib: 2.6.2 devDependencies: @@ -111,7 +111,7 @@ importers: '@types/react-dom': ^18.0.0 '@visactor/react-vrender': workspace:0.16.13 '@visactor/vrender': workspace:0.16.13 - '@visactor/vutils': 0.16.8-alpha.1 + '@visactor/vutils': 0.16.12 '@vitejs/plugin-react': 3.1.0 eslint: ~8.18.0 react: ^18.0.0 @@ -123,7 +123,7 @@ importers: dependencies: '@visactor/react-vrender': link:../react-vrender '@visactor/vrender': link:../vrender - '@visactor/vutils': 0.16.8-alpha.1 + '@visactor/vutils': 0.16.12 react-reconciler: 0.29.0_react@18.2.0 tslib: 2.6.2 devDependencies: @@ -151,7 +151,7 @@ importers: '@types/react-dom': ^18.0.0 '@visactor/vrender-core': workspace:0.16.13 '@visactor/vrender-kits': workspace:0.16.13 - '@visactor/vutils': 0.16.8-alpha.1 + '@visactor/vutils': 0.16.12 '@vitejs/plugin-react': 3.1.0 canvas: 2.11.2 eslint: ~8.18.0 @@ -174,7 +174,7 @@ importers: '@types/jest': 26.0.24 '@types/react': 18.2.37 '@types/react-dom': 18.2.15 - '@visactor/vutils': 0.16.8-alpha.1 + '@visactor/vutils': 0.16.12 '@vitejs/plugin-react': 3.1.0_vite@3.2.6 canvas: 2.11.2 eslint: 8.18.0 @@ -196,8 +196,8 @@ importers: '@types/jest': ^26.0.0 '@visactor/vrender-core': workspace:0.16.13 '@visactor/vrender-kits': workspace:0.16.13 - '@visactor/vscale': 0.16.8-alpha.1 - '@visactor/vutils': 0.16.8-alpha.1 + '@visactor/vscale': 0.16.12 + '@visactor/vutils': 0.16.12 eslint: ~8.18.0 jest: ^26.0.0 jest-electron: ^0.1.12 @@ -208,8 +208,8 @@ importers: dependencies: '@visactor/vrender-core': link:../vrender-core '@visactor/vrender-kits': link:../vrender-kits - '@visactor/vscale': 0.16.8-alpha.1 - '@visactor/vutils': 0.16.8-alpha.1 + '@visactor/vscale': 0.16.12 + '@visactor/vutils': 0.16.12 devDependencies: '@internal/bundler': link:../../tools/bundler '@internal/eslint-config': link:../../share/eslint-config @@ -233,7 +233,7 @@ importers: '@types/jest': ^26.0.0 '@types/react': ^18.0.0 '@types/react-dom': ^18.0.0 - '@visactor/vutils': 0.16.8-alpha.1 + '@visactor/vutils': 0.16.12 '@vitejs/plugin-react': 3.1.0 color-convert: 2.0.1 eslint: ~8.18.0 @@ -246,7 +246,7 @@ importers: typescript: 4.9.5 vite: 3.2.6 dependencies: - '@visactor/vutils': 0.16.8-alpha.1 + '@visactor/vutils': 0.16.12 color-convert: 2.0.1 devDependencies: '@internal/bundler': link:../../tools/bundler @@ -278,7 +278,7 @@ importers: '@types/react': ^18.0.0 '@types/react-dom': ^18.0.0 '@visactor/vrender-core': workspace:0.16.13 - '@visactor/vutils': 0.16.8-alpha.1 + '@visactor/vutils': 0.16.12 '@vitejs/plugin-react': 3.1.0 canvas: 2.11.2 eslint: ~8.18.0 @@ -291,7 +291,7 @@ importers: dependencies: '@resvg/resvg-js': 2.4.1 '@visactor/vrender-core': link:../vrender-core - '@visactor/vutils': 0.16.8-alpha.1 + '@visactor/vutils': 0.16.12 roughjs: 4.5.2 devDependencies: '@internal/bundler': link:../../tools/bundler @@ -3349,10 +3349,10 @@ packages: '@visactor/vutils': 0.15.14 dev: false - /@visactor/vscale/0.16.8-alpha.1: - resolution: {integrity: sha512-c6irHSly20nmVUaKUtgiUo6Hjjoz0eruewiasjV2miBH5XkzG2S+YzcNDC+LdtIKo/e6gn0XCjFFzFjWNh3j2g==} + /@visactor/vscale/0.16.12: + resolution: {integrity: sha512-St+1wjcPf3xPLOyjBCFUt0olcDtAToRBvxh99cLsKtSyS3ASLWKwXsgFbFC8d4wv/mrzOZr2jtQJgeogl4d1rw==} dependencies: - '@visactor/vutils': 0.16.8-alpha.1 + '@visactor/vutils': 0.16.12 dev: false /@visactor/vutils/0.13.3: @@ -3371,8 +3371,8 @@ packages: eventemitter3: 4.0.7 dev: false - /@visactor/vutils/0.16.8-alpha.1: - resolution: {integrity: sha512-m/VxRxxb55/x3VyfNiFPHre3t/s5Q8sGWUB+/Balt+QlllroEJHNV/v9Br+gsmuCCnbHNd4KWndrCvI4VffHuQ==} + /@visactor/vutils/0.16.12: + resolution: {integrity: sha512-oGj+kjzmTHLNKCu/Fx2ol/PKRTZonCwvw8pBV9RttG64guWIX/aDMd2VIRe418Psr6Ec6aws3GsG5sE5QU3+WQ==} dependencies: '@turf/helpers': 6.5.0 '@turf/invariant': 6.5.0 diff --git a/docs/demos/package.json b/docs/demos/package.json index 19fb21162..30bb07ff2 100644 --- a/docs/demos/package.json +++ b/docs/demos/package.json @@ -12,7 +12,7 @@ "@internal/eslint-config": "workspace:*", "@internal/ts-config": "workspace:*", "@visactor/vrender-kits": "workspace:0.14.8", - "@visactor/vutils": "0.16.8-alpha.1", + "@visactor/vutils": "0.16.12", "d3-scale-chromatic": "^3.0.0", "lodash": "4.17.21", "dat.gui": "^0.7.9", diff --git a/docs/package.json b/docs/package.json index 71f1386ab..7ee021c13 100644 --- a/docs/package.json +++ b/docs/package.json @@ -12,7 +12,7 @@ "dependencies": { "@arco-design/web-react": "2.46.1", "@visactor/vchart": "1.3.0", - "@visactor/vutils": "0.16.8-alpha.1", + "@visactor/vutils": "0.16.12", "@visactor/vgrammar": "~0.5.7", "@visactor/vrender": "workspace:0.16.13", "markdown-it": "^13.0.0", diff --git a/packages/react-vrender-utils/package.json b/packages/react-vrender-utils/package.json index d7b0da09c..077739bed 100644 --- a/packages/react-vrender-utils/package.json +++ b/packages/react-vrender-utils/package.json @@ -27,7 +27,7 @@ "dependencies": { "@visactor/vrender": "workspace:0.16.13", "@visactor/react-vrender": "workspace:0.16.13", - "@visactor/vutils": "0.16.8-alpha.1", + "@visactor/vutils": "0.16.12", "react-reconciler": "^0.29.0", "tslib": "^2.3.1" }, diff --git a/packages/react-vrender/package.json b/packages/react-vrender/package.json index eb3f26cd1..26cc7bb2c 100644 --- a/packages/react-vrender/package.json +++ b/packages/react-vrender/package.json @@ -25,7 +25,7 @@ }, "dependencies": { "@visactor/vrender": "workspace:0.16.13", - "@visactor/vutils": "0.16.8-alpha.1", + "@visactor/vutils": "0.16.12", "react-reconciler": "^0.29.0", "tslib": "^2.3.1" }, diff --git a/packages/vrender-components/package.json b/packages/vrender-components/package.json index 44dab5397..dd76f06d3 100644 --- a/packages/vrender-components/package.json +++ b/packages/vrender-components/package.json @@ -26,15 +26,15 @@ "dependencies": { "@visactor/vrender-core": "workspace:0.16.13", "@visactor/vrender-kits": "workspace:0.16.13", - "@visactor/vutils": "0.16.8-alpha.1", - "@visactor/vscale": "0.16.8-alpha.1" + "@visactor/vutils": "0.16.12", + "@visactor/vscale": "0.16.12" }, "devDependencies": { "@internal/bundler": "workspace:*", "@internal/eslint-config": "workspace:*", "@internal/ts-config": "workspace:*", "@rushstack/eslint-patch": "~1.1.4", - "@visactor/vscale": "0.16.8-alpha.1", + "@visactor/vscale": "0.16.12", "@types/jest": "^26.0.0", "jest": "^26.0.0", "jest-electron": "^0.1.12", diff --git a/packages/vrender-core/package.json b/packages/vrender-core/package.json index 63cfd7196..1ba0d6701 100644 --- a/packages/vrender-core/package.json +++ b/packages/vrender-core/package.json @@ -26,7 +26,7 @@ }, "dependencies": { "color-convert": "2.0.1", - "@visactor/vutils": "0.16.8-alpha.1" + "@visactor/vutils": "0.16.12" }, "devDependencies": { "@internal/bundler": "workspace:*", diff --git a/packages/vrender-kits/package.json b/packages/vrender-kits/package.json index 7027d1435..adc55db6e 100644 --- a/packages/vrender-kits/package.json +++ b/packages/vrender-kits/package.json @@ -22,7 +22,7 @@ }, "dependencies": { "@visactor/vrender-core": "workspace:0.16.13", - "@visactor/vutils": "0.16.8-alpha.1", + "@visactor/vutils": "0.16.12", "@resvg/resvg-js": "2.4.1", "roughjs": "4.5.2" }, diff --git a/packages/vrender/package.json b/packages/vrender/package.json index 5ba817b23..72fda1fa8 100644 --- a/packages/vrender/package.json +++ b/packages/vrender/package.json @@ -33,7 +33,7 @@ "@internal/eslint-config": "workspace:*", "@internal/ts-config": "workspace:*", "@rushstack/eslint-patch": "~1.1.4", - "@visactor/vutils": "0.16.8-alpha.1", + "@visactor/vutils": "0.16.12", "canvas": "2.11.2", "react": "^18.0.0", "react-dom": "^18.0.0", From 48c4ba4e1da278df710daa6c146702a49a624358 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Tue, 21 Nov 2023 17:08:42 +0800 Subject: [PATCH 33/40] feat: support disableCheckGraphicWidthOutRange to skip check if graphic out of range --- packages/vrender-core/src/core/global.ts | 3 - packages/vrender-core/src/core/stage.ts | 44 +++++---- packages/vrender-core/src/graphic/graphic.ts | 8 +- packages/vrender-core/src/interface/global.ts | 2 - packages/vrender-core/src/interface/stage.ts | 4 + .../contributions/render/base-render.ts | 19 +++- .../contributions/render/draw-contribution.ts | 23 ++--- .../contributions/render/draw-interceptor.ts | 91 +++++++++++++++---- .../src/render/contributions/render/module.ts | 12 +-- .../contributions/render/path-render.ts | 8 +- .../contributions/render/rect-render.ts | 9 +- .../vrender-core/src/render/render-service.ts | 5 + 12 files changed, 156 insertions(+), 72 deletions(-) diff --git a/packages/vrender-core/src/core/global.ts b/packages/vrender-core/src/core/global.ts index 6bdef174c..3884e739e 100644 --- a/packages/vrender-core/src/core/global.ts +++ b/packages/vrender-core/src/core/global.ts @@ -108,8 +108,6 @@ export class DefaultGlobal implements IGlobal { // 是否在不显示canvas的时候停止绘图操作,默认false optimizeVisible: boolean; - // 在场景树小于某个数的情况下,不进行图元超出边界判断,默认0 - optmizeSkipCheckBoundariesThreshold: number; envParams?: any; declare measureTextMethod: 'native' | 'simple' | 'quick'; @@ -129,7 +127,6 @@ export class DefaultGlobal implements IGlobal { }; this.measureTextMethod = 'native'; this.optimizeVisible = false; - this.optmizeSkipCheckBoundariesThreshold = 0; } protected bindContribution(params?: any): void | Promise { diff --git a/packages/vrender-core/src/core/stage.ts b/packages/vrender-core/src/core/stage.ts index a8eab8e5d..85a61afb8 100644 --- a/packages/vrender-core/src/core/stage.ts +++ b/packages/vrender-core/src/core/stage.ts @@ -193,7 +193,7 @@ export class Stage extends Group implements IStage { * 1. 如果没有传入宽高,那么默认为canvas宽高,如果传入了宽高则stage使用传入宽高作为视口宽高 * @param params */ - constructor(params: Partial) { + constructor(params: Partial = {}) { super({}); this.params = params; this.theme = new Theme(); @@ -275,6 +275,9 @@ export class Stage extends Group implements IStage { this.timeline = new DefaultTimeline(); this.ticker.addTimeline(this.timeline); this.timeline.pause(); + if (!params.optimize) { + params.optimize = {}; + } this.optmize(params.optimize); // 如果背景是图片,触发加载图片操作 if (params.background && isString(this._background) && this._background.includes('/')) { @@ -313,7 +316,7 @@ export class Stage extends Group implements IStage { this._skipRender = -Infinity; } else { // 判断是否需要outRange优化 - if (this.params && this.params.optimize && this.params.optimize.skipRenderWithOutRange !== false) { + if (this.params.optimize.skipRenderWithOutRange !== false) { this._skipRender = this.window.isVisible() ? 0 : 1; } else { this._skipRender = 0; @@ -322,8 +325,9 @@ export class Stage extends Group implements IStage { } // 优化策略 - optmize(params?: IOptimizeType) { - this.optmizeRender(params?.skipRenderWithOutRange); + optmize(params: IOptimizeType) { + this.optmizeRender(params.skipRenderWithOutRange); + this.params.optimize = params; } // 优化渲染 @@ -333,23 +337,25 @@ export class Stage extends Group implements IStage { } // 不在视口内的时候,跳过渲染 this._skipRender = this._skipRender < 0 ? this._skipRender : this.window.isVisible() ? 0 : 1; - this.window.onVisibleChange(visible => { - if (this._skipRender < 0) { - return; + this.window.onVisibleChange(this._onVisibleChange); + } + + protected _onVisibleChange = (visible: boolean) => { + if (this._skipRender < 0) { + return; + } + if (visible) { + if (this.dirtyBounds) { + this.dirtyBounds.setValue(0, 0, this._viewBox.width(), this._viewBox.height()); } - if (visible) { - if (this.dirtyBounds) { - this.dirtyBounds.setValue(0, 0, this._viewBox.width(), this._viewBox.height()); - } - if (this._skipRender > 1) { - this.renderNextFrame(); - } - this._skipRender = 0; - } else { - this._skipRender = 1; + if (this._skipRender > 1) { + this.renderNextFrame(); } - }); - } + this._skipRender = 0; + } else { + this._skipRender = 1; + } + }; getTimeline() { return this.timeline; diff --git a/packages/vrender-core/src/graphic/graphic.ts b/packages/vrender-core/src/graphic/graphic.ts index 6032c79da..696a2a0d2 100644 --- a/packages/vrender-core/src/graphic/graphic.ts +++ b/packages/vrender-core/src/graphic/graphic.ts @@ -286,10 +286,10 @@ export abstract class Graphic = Partial void; setActiveEnvContribution: (contribution: IEnvContribution) => void; diff --git a/packages/vrender-core/src/interface/stage.ts b/packages/vrender-core/src/interface/stage.ts index f647a0377..dada55d41 100644 --- a/packages/vrender-core/src/interface/stage.ts +++ b/packages/vrender-core/src/interface/stage.ts @@ -66,6 +66,10 @@ export interface IStageParams { export type IOptimizeType = { // 视口不在可视区,跳过渲染,默认为true skipRenderWithOutRange?: boolean; + // 跳过图元在区间外的判断 + // 不存在dirtyBounds的时候,根据该配置判断是否关闭图元的超出边界判定 + // 如果有dirtyBounds那么该配置不生效 + disableCheckGraphicWidthOutRange?: boolean; }; export interface IOption3D { diff --git a/packages/vrender-core/src/render/contributions/render/base-render.ts b/packages/vrender-core/src/render/contributions/render/base-render.ts index eb260921a..d6b14ac29 100644 --- a/packages/vrender-core/src/render/contributions/render/base-render.ts +++ b/packages/vrender-core/src/render/contributions/render/base-render.ts @@ -20,6 +20,8 @@ import { mat4Allocate } from '../../../allocator/matrix-allocate'; import { drawPathProxy, fillVisible, runFill, runStroke, strokeVisible } from './utils'; import { BaseRenderContributionTime } from '../../../common/enums'; +const result: IPointLike & { z: number; lastModelMatrix: mat4 } = { x: 0, y: 0, z: 0, lastModelMatrix: null }; + export abstract class BaseRender { camera: ICamera; declare z: number; @@ -188,7 +190,7 @@ export abstract class BaseRender { context: IContext2d, use3dMatrixIn3dMode: boolean = false ): IPointLike & { z: number; lastModelMatrix: mat4 } { - const transMatrix = graphic.transMatrix; + // const transMatrix = graphic.transMatrix; const { x = graphicAttribute.x, y = graphicAttribute.y, @@ -198,14 +200,25 @@ export abstract class BaseRender { angle = graphicAttribute.angle, postMatrix } = graphic.attribute; - const onlyTranslate = transMatrix.onlyTranslate() && !postMatrix; + // const onlyTranslate = transMatrix.onlyTranslate() && !postMatrix; // 存在3d变换的时候,需要计算3d矩阵 const lastModelMatrix = context.modelMatrix; const camera = context.camera; - const result: IPointLike & { z: number; lastModelMatrix: mat4 } = { x, y, z, lastModelMatrix }; + // const result: IPointLike & { z: number; lastModelMatrix: mat4 } = { x, y, z, lastModelMatrix }; + result.x = x; + result.y = y; + result.z = z; + result.lastModelMatrix = lastModelMatrix; + // 是否应该进行3d变换 const shouldTransform3d = camera && (use3dMatrixIn3dMode || shouldUseMat4(graphic)); + + // 是否仅有translate + const onlyTranslate = shouldTransform3d + ? graphic.transMatrix.onlyTranslate() && !postMatrix + : scaleX === 1 && scaleY === 1 && angle === 0 && !postMatrix; + if (shouldTransform3d) { const nextModelMatrix = mat4Allocate.allocate(); // 计算模型矩阵 diff --git a/packages/vrender-core/src/render/contributions/render/draw-contribution.ts b/packages/vrender-core/src/render/contributions/render/draw-contribution.ts index a50435e97..9f4575723 100644 --- a/packages/vrender-core/src/render/contributions/render/draw-contribution.ts +++ b/packages/vrender-core/src/render/contributions/render/draw-contribution.ts @@ -84,12 +84,12 @@ export class DefaultDrawContribution implements IDrawContribution { } prepareForDraw(renderService: IRenderService, drawContext: IDrawContext) { - const count = renderService.renderTreeRoots.reduce((a, b) => a + b.count, 0); - // 小于500个元素就不用计算dirtyBounds了 - if (count < this.global.optmizeSkipCheckBoundariesThreshold) { - this.useDirtyBounds = false; - } else { + // 有dirtyBounds用dirtyBounds + if (drawContext.updateBounds) { this.useDirtyBounds = true; + } else { + // 没有的话,看看是否需要跳过outRange的渲染 + this.useDirtyBounds = !drawContext.stage.params.optimize.disableCheckGraphicWidthOutRange; } } @@ -184,7 +184,7 @@ export class DefaultDrawContribution implements IDrawContribution { return null; } - renderGroup(group: IGroup, drawContext: IDrawContext, parentMatrix: IMatrixLike, skipSort?: boolean) { + renderGroup(group: IGroup, drawContext: IDrawContext, parentMatrix: IMatrix, skipSort?: boolean) { if (drawContext.break || group.attribute.visibleAll === false) { return; } @@ -198,7 +198,7 @@ export class DefaultDrawContribution implements IDrawContribution { return; } - let nextM: IMatrix; + let nextM: IMatrix = parentMatrix; let tempBounds: IBounds; if (this.useDirtyBounds) { @@ -325,10 +325,11 @@ export class DefaultDrawContribution implements IDrawContribution { if (this.InterceptorContributions.length) { for (let i = 0; i < this.InterceptorContributions.length; i++) { const drawContribution = this.InterceptorContributions[i]; - if (drawContribution.beforeDrawItem) { - if (drawContribution.beforeDrawItem(graphic, this.currentRenderService, drawContext, this, params)) { - return; - } + if ( + drawContribution.beforeDrawItem && + drawContribution.beforeDrawItem(graphic, this.currentRenderService, drawContext, this, params) + ) { + return; } } } diff --git a/packages/vrender-core/src/render/contributions/render/draw-interceptor.ts b/packages/vrender-core/src/render/contributions/render/draw-interceptor.ts index 9d054398a..b19a84ca5 100644 --- a/packages/vrender-core/src/render/contributions/render/draw-interceptor.ts +++ b/packages/vrender-core/src/render/contributions/render/draw-interceptor.ts @@ -31,7 +31,7 @@ const tempDirtyBounds = new AABBBounds(); /** * 影子节点拦截器,用于渲染影子节点 */ -@injectable() +// @injectable() export class ShadowRootDrawItemInterceptorContribution implements IDrawItemInterceptorContribution { order: number = 1; afterDrawItem( @@ -96,30 +96,25 @@ export class ShadowRootDrawItemInterceptorContribution implements IDrawItemInter } } -@injectable() -export class CommonDrawItemInterceptorContribution implements IDrawItemInterceptorContribution { +// @injectable() +export class DebugDrawItemInterceptorContribution implements IDrawItemInterceptorContribution { order: number = 1; - afterDrawItem( - graphic: IGraphic, - renderService: IRenderService, - drawContext: IDrawContext, - drawContribution: IDrawContribution, - params?: IGraphicRenderDrawParams - ): boolean { - if (graphic.attribute.shadowRootIdx > 0 || !graphic.attribute.shadowRootIdx) { - this.drawItem(graphic, renderService, drawContext, drawContribution, params); - } - return false; + interceptors: IDrawItemInterceptorContribution[]; + constructor() { + this.interceptors = [ + new ShadowRootDrawItemInterceptorContribution(), + new Canvas3DDrawItemInterceptor(), + new InteractiveDrawItemInterceptorContribution() + ]; } - - beforeDrawItem( + afterDrawItem( graphic: IGraphic, renderService: IRenderService, drawContext: IDrawContext, drawContribution: IDrawContribution, params?: IGraphicRenderDrawParams ): boolean { - if (graphic.attribute.shadowRootIdx < 0) { + if (graphic.attribute._debug_bounds) { this.drawItem(graphic, renderService, drawContext, drawContribution, params); } return false; @@ -157,10 +152,68 @@ export class CommonDrawItemInterceptorContribution implements IDrawItemIntercept } } +@injectable() +export class CommonDrawItemInterceptorContribution implements IDrawItemInterceptorContribution { + order: number = 1; + interceptors: IDrawItemInterceptorContribution[]; + constructor() { + this.interceptors = [ + new ShadowRootDrawItemInterceptorContribution(), + new Canvas3DDrawItemInterceptor(), + new InteractiveDrawItemInterceptorContribution(), + new DebugDrawItemInterceptorContribution() + ]; + } + afterDrawItem( + graphic: IGraphic, + renderService: IRenderService, + drawContext: IDrawContext, + drawContribution: IDrawContribution, + params?: IGraphicRenderDrawParams + ): boolean { + for (let i = 0; i < this.interceptors.length; i++) { + if ( + this.interceptors[i].afterDrawItem && + this.interceptors[i].afterDrawItem(graphic, renderService, drawContext, drawContribution, params) + ) { + return true; + } + } + return false; + } + + beforeDrawItem( + graphic: IGraphic, + renderService: IRenderService, + drawContext: IDrawContext, + drawContribution: IDrawContribution, + params?: IGraphicRenderDrawParams + ): boolean { + // 【性能方案】判定写在外层,减少遍历判断耗时,10000条数据减少1ms + if ( + (!graphic.in3dMode || drawContext.in3dInterceptor) && + !graphic.shadowRoot && + !(graphic.baseGraphic || graphic.attribute.globalZIndex || graphic.interactiveGraphic) + ) { + return false; + } + + for (let i = 0; i < this.interceptors.length; i++) { + if ( + this.interceptors[i].beforeDrawItem && + this.interceptors[i].beforeDrawItem(graphic, renderService, drawContext, drawContribution, params) + ) { + return true; + } + } + return false; + } +} + /** * 交互层节点拦截器,用于支持交互层图元 */ -@injectable() +// @injectable() export class InteractiveDrawItemInterceptorContribution implements IDrawItemInterceptorContribution { order: number = 1; processing: boolean; @@ -300,7 +353,7 @@ export class InteractiveDrawItemInterceptorContribution implements IDrawItemInte /** * 3d拦截器,用于渲染3d视角 */ -@injectable() +// @injectable() export class Canvas3DDrawItemInterceptor implements IDrawItemInterceptorContribution { // canvas?: ICanvas; order: number = 1; diff --git a/packages/vrender-core/src/render/contributions/render/module.ts b/packages/vrender-core/src/render/contributions/render/module.ts index 62a91113a..f0b3ad436 100644 --- a/packages/vrender-core/src/render/contributions/render/module.ts +++ b/packages/vrender-core/src/render/contributions/render/module.ts @@ -198,13 +198,13 @@ export default new ContainerModule(bind => { bindContributionProvider(bind, GraphicRender); // interceptor - bind(ShadowRootDrawItemInterceptorContribution).toSelf().inSingletonScope(); - bind(DrawItemInterceptor).toService(ShadowRootDrawItemInterceptorContribution); + // bind(ShadowRootDrawItemInterceptorContribution).toSelf().inSingletonScope(); + // bind(DrawItemInterceptor).toService(ShadowRootDrawItemInterceptorContribution); bind(CommonDrawItemInterceptorContribution).toSelf().inSingletonScope(); bind(DrawItemInterceptor).toService(CommonDrawItemInterceptorContribution); - bind(Canvas3DDrawItemInterceptor).toSelf().inSingletonScope(); - bind(DrawItemInterceptor).toService(Canvas3DDrawItemInterceptor); - bind(InteractiveDrawItemInterceptorContribution).toSelf().inSingletonScope(); - bind(DrawItemInterceptor).toService(InteractiveDrawItemInterceptorContribution); + // bind(Canvas3DDrawItemInterceptor).toSelf().inSingletonScope(); + // bind(DrawItemInterceptor).toService(Canvas3DDrawItemInterceptor); + // bind(InteractiveDrawItemInterceptorContribution).toSelf().inSingletonScope(); + // bind(DrawItemInterceptor).toService(InteractiveDrawItemInterceptorContribution); bindContributionProvider(bind, DrawItemInterceptor); }); diff --git a/packages/vrender-core/src/render/contributions/render/path-render.ts b/packages/vrender-core/src/render/contributions/render/path-render.ts index 1cbc55dc7..a16ee0a3e 100644 --- a/packages/vrender-core/src/render/contributions/render/path-render.ts +++ b/packages/vrender-core/src/render/contributions/render/path-render.ts @@ -14,7 +14,8 @@ import type { IContributionProvider, IDrawContext, IGraphicRenderDrawParams, - IRenderService + IRenderService, + IPathGraphicAttribute } from '../../../interface'; import { getTheme } from '../../../graphic/theme'; import { PATH_NUMBER_TYPE } from '../../../graphic/constants'; @@ -32,6 +33,7 @@ import { export class DefaultCanvasPathRender extends BaseRender implements IGraphicRender { type: 'path'; numberType: number = PATH_NUMBER_TYPE; + tempTheme: Required; constructor( @inject(ContributionProvider) @@ -62,7 +64,7 @@ export class DefaultCanvasPathRender extends BaseRender implements IGraph ) => boolean ) { // const pathAttribute = graphicService.themeService.getCurrentTheme().pathAttribute; - const pathAttribute = getTheme(path, params?.theme).path; + const pathAttribute = this.tempTheme ?? getTheme(path, params?.theme).path; const { x: originX = pathAttribute.x, y: originY = pathAttribute.y } = path.attribute; const z = this.z ?? 0; @@ -134,6 +136,8 @@ export class DefaultCanvasPathRender extends BaseRender implements IGraph draw(path: IPath, renderService: IRenderService, drawContext: IDrawContext, params?: IGraphicRenderDrawParams) { const pathAttribute = getTheme(path, params?.theme).path; + this.tempTheme = pathAttribute; this._draw(path, pathAttribute, false, drawContext, params); + this.tempTheme = null; } } diff --git a/packages/vrender-core/src/render/contributions/render/rect-render.ts b/packages/vrender-core/src/render/contributions/render/rect-render.ts index 5d44eed75..8cba6ce2b 100644 --- a/packages/vrender-core/src/render/contributions/render/rect-render.ts +++ b/packages/vrender-core/src/render/contributions/render/rect-render.ts @@ -16,7 +16,8 @@ import type { IGraphicRenderDrawParams, IRenderService, IRectRenderContribution, - IContributionProvider + IContributionProvider, + IRectGraphicAttribute } from '../../../interface'; import { RectRenderContribution } from './contributions/constants'; import { rectFillVisible, rectStrokeVisible, runFill, runStroke } from './utils'; @@ -33,6 +34,7 @@ import { export class DefaultCanvasRectRender extends BaseRender implements IGraphicRender { type = 'rect'; numberType: number = RECT_NUMBER_TYPE; + tempTheme: Required; constructor( @inject(ContributionProvider) @@ -68,8 +70,7 @@ export class DefaultCanvasRectRender extends BaseRender implements IGraph themeAttribute: IThemeAttribute ) => boolean ) { - // const rectAttribute = graphicService.themeService.getCurrentTheme().rectAttribute; - const rectAttribute = getTheme(rect, params?.theme).rect; + const rectAttribute = this.tempTheme ?? getTheme(rect, params?.theme).rect; const { fill = rectAttribute.fill, background, @@ -177,6 +178,8 @@ export class DefaultCanvasRectRender extends BaseRender implements IGraph draw(rect: IRect, renderService: IRenderService, drawContext: IDrawContext, params?: IGraphicRenderDrawParams) { const rectAttribute = getTheme(rect, params?.theme).rect; + this.tempTheme = rectAttribute; this._draw(rect, rectAttribute, false, drawContext, params); + this.tempTheme = null; } } diff --git a/packages/vrender-core/src/render/render-service.ts b/packages/vrender-core/src/render/render-service.ts index 98cc50772..a533df861 100644 --- a/packages/vrender-core/src/render/render-service.ts +++ b/packages/vrender-core/src/render/render-service.ts @@ -25,6 +25,11 @@ export class DefaultRenderService implements IRenderService { // 渲染前准备工作,计算bounds等逻辑 prepare(updateBounds: boolean): void { + // 如果不需要计算Bounds,那么transMatrix也不需要计算 + // TODO 后期可能存在依赖transMatrix的插件,但目前不存在 + if (!updateBounds) { + return; + } this.renderTreeRoots.forEach(g => { this._prepare(g, updateBounds); }); From 40711e85b449e9cd4e74c93bc4db98cca49b52bb Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Tue, 21 Nov 2023 18:12:31 +0800 Subject: [PATCH 34/40] chore: add change file --- .../feat-no-outrange_2023-11-21-10-12.json | 10 ++++++++++ .../feat-no-outrange_2023-11-21-10-12.json | 10 ++++++++++ .../feat-no-outrange_2023-11-21-10-12.json | 10 ++++++++++ 3 files changed, 30 insertions(+) create mode 100644 common/changes/@visactor/react-vrender-utils/feat-no-outrange_2023-11-21-10-12.json create mode 100644 common/changes/@visactor/react-vrender/feat-no-outrange_2023-11-21-10-12.json create mode 100644 common/changes/@visactor/vrender-core/feat-no-outrange_2023-11-21-10-12.json diff --git a/common/changes/@visactor/react-vrender-utils/feat-no-outrange_2023-11-21-10-12.json b/common/changes/@visactor/react-vrender-utils/feat-no-outrange_2023-11-21-10-12.json new file mode 100644 index 000000000..178a03753 --- /dev/null +++ b/common/changes/@visactor/react-vrender-utils/feat-no-outrange_2023-11-21-10-12.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/react-vrender-utils", + "comment": "", + "type": "none" + } + ], + "packageName": "@visactor/react-vrender-utils" +} \ No newline at end of file diff --git a/common/changes/@visactor/react-vrender/feat-no-outrange_2023-11-21-10-12.json b/common/changes/@visactor/react-vrender/feat-no-outrange_2023-11-21-10-12.json new file mode 100644 index 000000000..92bf64099 --- /dev/null +++ b/common/changes/@visactor/react-vrender/feat-no-outrange_2023-11-21-10-12.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/react-vrender", + "comment": "", + "type": "none" + } + ], + "packageName": "@visactor/react-vrender" +} \ No newline at end of file diff --git a/common/changes/@visactor/vrender-core/feat-no-outrange_2023-11-21-10-12.json b/common/changes/@visactor/vrender-core/feat-no-outrange_2023-11-21-10-12.json new file mode 100644 index 000000000..bb43dfbd1 --- /dev/null +++ b/common/changes/@visactor/vrender-core/feat-no-outrange_2023-11-21-10-12.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vrender-core", + "comment": "feat: support disableCheckGraphicWidthOutRange to skip check if graphic out of range", + "type": "none" + } + ], + "packageName": "@visactor/vrender-core" +} \ No newline at end of file From 75e149ced87fb8395c5a8fe41d77ccc3424dbfd3 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Tue, 21 Nov 2023 18:11:45 +0800 Subject: [PATCH 35/40] feat: rect support x1 and y1 --- .../feat-rect-x1y1_2023-11-21-10-17.json | 10 +++++ .../feat-rect-x1y1_2023-11-21-10-17.json | 10 +++++ .../vrender-core/src/common/shape/rect.ts | 8 ++++ packages/vrender-core/src/core/stage.ts | 3 +- packages/vrender-core/src/graphic/config.ts | 4 ++ .../graphic-service/graphic-service.ts | 7 +++- packages/vrender-core/src/graphic/rect.ts | 31 +++++++------- .../src/interface/graphic/rect.ts | 2 + .../contributions/rect-contribution-render.ts | 11 +++-- .../contributions/render/rect-render.ts | 7 +++- .../src/render/contributions/render/utils.ts | 4 +- .../render/contributions/rough/rough-rect.ts | 10 ++++- .../__tests__/browser/src/pages/rect.ts | 40 +++++++++++++------ 13 files changed, 107 insertions(+), 40 deletions(-) create mode 100644 common/changes/@visactor/vrender-core/feat-rect-x1y1_2023-11-21-10-17.json create mode 100644 common/changes/@visactor/vrender-kits/feat-rect-x1y1_2023-11-21-10-17.json diff --git a/common/changes/@visactor/vrender-core/feat-rect-x1y1_2023-11-21-10-17.json b/common/changes/@visactor/vrender-core/feat-rect-x1y1_2023-11-21-10-17.json new file mode 100644 index 000000000..a3982abd4 --- /dev/null +++ b/common/changes/@visactor/vrender-core/feat-rect-x1y1_2023-11-21-10-17.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vrender-core", + "comment": "feat: rect support x1 and y1", + "type": "none" + } + ], + "packageName": "@visactor/vrender-core" +} \ No newline at end of file diff --git a/common/changes/@visactor/vrender-kits/feat-rect-x1y1_2023-11-21-10-17.json b/common/changes/@visactor/vrender-kits/feat-rect-x1y1_2023-11-21-10-17.json new file mode 100644 index 000000000..b65bbff73 --- /dev/null +++ b/common/changes/@visactor/vrender-kits/feat-rect-x1y1_2023-11-21-10-17.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vrender-kits", + "comment": "feat: rect support x1 and y1", + "type": "none" + } + ], + "packageName": "@visactor/vrender-kits" +} \ No newline at end of file diff --git a/packages/vrender-core/src/common/shape/rect.ts b/packages/vrender-core/src/common/shape/rect.ts index 696a22782..513996a5f 100644 --- a/packages/vrender-core/src/common/shape/rect.ts +++ b/packages/vrender-core/src/common/shape/rect.ts @@ -12,6 +12,14 @@ export function createRectPath( height: number, rectCornerRadius: number | number[] ) { + if (width < 0) { + x += width; + width = -width; + } + if (height < 0) { + y += height; + height = -height; + } // 匹配cornerRadius let cornerRadius: vec4; if (isNumber(rectCornerRadius, true)) { diff --git a/packages/vrender-core/src/core/stage.ts b/packages/vrender-core/src/core/stage.ts index 85a61afb8..bf39c7053 100644 --- a/packages/vrender-core/src/core/stage.ts +++ b/packages/vrender-core/src/core/stage.ts @@ -169,7 +169,6 @@ export class Stage extends Group implements IStage { readonly layerService: ILayerService; private _eventSystem?: EventSystem; private get eventSystem(): EventSystem { - this.tryInitEventSystem(); return this._eventSystem; } @@ -231,7 +230,7 @@ export class Stage extends Group implements IStage { this.state = 'normal'; this.renderCount = 0; - + this.tryInitEventSystem(); // // 没有传入xy就默认为0 // this._x = params.x ?? DefaultConfig.X; // this._y = params.y ?? DefaultConfig.Y; diff --git a/packages/vrender-core/src/graphic/config.ts b/packages/vrender-core/src/graphic/config.ts index d532beaf7..87c8ab832 100644 --- a/packages/vrender-core/src/graphic/config.ts +++ b/packages/vrender-core/src/graphic/config.ts @@ -263,6 +263,8 @@ export const DefaultRectAttribute: Required = { ...DefaultAttribute, width: 0, height: 0, + x1: 0, + y1: 0, strokeBoundsBuffer: 0, cornerRadius: 0 }; @@ -271,6 +273,8 @@ export const DefaultRect3dAttribute: Required = { ...DefaultAttribute, width: 0, height: 0, + x1: 0, + y1: 0, cornerRadius: 0, length: 0 }; diff --git a/packages/vrender-core/src/graphic/graphic-service/graphic-service.ts b/packages/vrender-core/src/graphic/graphic-service/graphic-service.ts index 45981d3ce..6aac55607 100644 --- a/packages/vrender-core/src/graphic/graphic-service/graphic-service.ts +++ b/packages/vrender-core/src/graphic/graphic-service/graphic-service.ts @@ -719,8 +719,11 @@ export class DefaultGraphicService implements IGraphicService { graphic?: IGraphic ) { if (!this.updatePathProxyAABBBounds(aabbBounds, graphic)) { - const { width = rectTheme.width, height = rectTheme.height } = attribute; - aabbBounds.set(0, 0, width, height); + let { width, height } = attribute; + const { x1, y1, x, y } = attribute; + width = width ?? x1 - x; + height = height ?? y1 - y; + aabbBounds.set(0, 0, width || 0, height || 0); } const tb1 = this.tempAABBBounds1; diff --git a/packages/vrender-core/src/graphic/rect.ts b/packages/vrender-core/src/graphic/rect.ts index a2f01e458..176323960 100644 --- a/packages/vrender-core/src/graphic/rect.ts +++ b/packages/vrender-core/src/graphic/rect.ts @@ -1,13 +1,13 @@ import type { AABBBounds, OBBBounds } from '@visactor/vutils'; import { Graphic, GRAPHIC_UPDATE_TAG_KEY, NOWORK_ANIMATE_ATTR } from './graphic'; -import type { GraphicType, IRect, IRectGraphicAttribute } from '../interface'; +import type { GraphicType, ICustomPath2D, IRect, IRectGraphicAttribute } from '../interface'; import { CustomPath2D } from '../common/custom-path2d'; import { parsePadding } from '../common/utils'; import { getTheme } from './theme'; import { application } from '../application'; import { RECT_NUMBER_TYPE } from './constants'; -const RECT_UPDATE_TAG_KEY = ['width', 'height', 'cornerRadius', ...GRAPHIC_UPDATE_TAG_KEY]; +const RECT_UPDATE_TAG_KEY = ['width', 'x1', 'y1', 'height', 'cornerRadius', ...GRAPHIC_UPDATE_TAG_KEY]; export class Rect extends Graphic implements IRect { type: GraphicType = 'rect'; @@ -23,8 +23,10 @@ export class Rect extends Graphic implements IRect { return super.isValid() && this._isValid(); } private _isValid(): boolean { - const { width, height } = this.attribute; - return this._validNumber(width) && this._validNumber(height); + return true; + // 暂时不判断,理论上认为都是合法的,节省性能耗时 + // const { width, x1, y1, height } = this.attribute; + // return (this._validNumber(width) || this._validNumber(x1)) && (this._validNumber(height) || this._validNumber(y1)); } protected doUpdateAABBBounds(): AABBBounds { @@ -64,18 +66,19 @@ export class Rect extends Graphic implements IRect { return super.needUpdateTag(key, RECT_UPDATE_TAG_KEY); } - toCustomPath() { - const attribute = this.attribute; - const width = attribute.width; - const height = attribute.height; - const x = 0; - const y = 0; + toCustomPath(): ICustomPath2D { + throw new Error('暂不支持'); + // const attribute = this.attribute; + // const width = attribute.width; + // const height = attribute.height; + // const x = 0; + // const y = 0; - const path = new CustomPath2D(); - path.moveTo(x, y); - path.rect(x, y, width, height); + // const path = new CustomPath2D(); + // path.moveTo(x, y); + // path.rect(x, y, width, height); - return path; + // return path; } clone() { diff --git a/packages/vrender-core/src/interface/graphic/rect.ts b/packages/vrender-core/src/interface/graphic/rect.ts index 58b9a5939..c6ed1a88a 100644 --- a/packages/vrender-core/src/interface/graphic/rect.ts +++ b/packages/vrender-core/src/interface/graphic/rect.ts @@ -4,6 +4,8 @@ import type { ICustomPath2D } from '../path'; export type IRectAttribute = { width: number; height: number; + x1: number; + y1: number; cornerRadius: number | number[]; }; diff --git a/packages/vrender-core/src/render/contributions/render/contributions/rect-contribution-render.ts b/packages/vrender-core/src/render/contributions/render/contributions/rect-contribution-render.ts index 22a198bf6..3ba1b7187 100644 --- a/packages/vrender-core/src/render/contributions/render/contributions/rect-contribution-render.ts +++ b/packages/vrender-core/src/render/contributions/render/contributions/rect-contribution-render.ts @@ -51,16 +51,21 @@ export class DefaultRectRenderContribution implements IRectRenderContribution { return; } const { - width = rectAttribute.width, - height = rectAttribute.height, cornerRadius = rectAttribute.cornerRadius, opacity = rectAttribute.opacity, x: originX = rectAttribute.x, y: originY = rectAttribute.y, scaleX = rectAttribute.scaleX, - scaleY = rectAttribute.scaleY + scaleY = rectAttribute.scaleY, + x1, + y1 } = rect.attribute; + let { width, height } = rect.attribute; + + width = (width ?? x1 - x) || 0; + height = (height ?? y1 - y) || 0; + const doStrokeOuter = !!(outerBorder && outerBorder.stroke); const doStrokeInner = !!(innerBorder && innerBorder.stroke); diff --git a/packages/vrender-core/src/render/contributions/render/rect-render.ts b/packages/vrender-core/src/render/contributions/render/rect-render.ts index 8cba6ce2b..3f8c6323a 100644 --- a/packages/vrender-core/src/render/contributions/render/rect-render.ts +++ b/packages/vrender-core/src/render/contributions/render/rect-render.ts @@ -75,17 +75,20 @@ export class DefaultCanvasRectRender extends BaseRender implements IGraph fill = rectAttribute.fill, background, stroke = rectAttribute.stroke, - width = rectAttribute.width, - height = rectAttribute.height, cornerRadius = rectAttribute.cornerRadius, opacity = rectAttribute.opacity, fillOpacity = rectAttribute.fillOpacity, lineWidth = rectAttribute.lineWidth, strokeOpacity = rectAttribute.strokeOpacity, visible = rectAttribute.visible, + x1, + y1, x: originX = rectAttribute.x, y: originY = rectAttribute.y } = rect.attribute; + let { width, height } = rect.attribute; + width = (width ?? x1 - originX) || 0; + height = (height ?? y1 - originY) || 0; // 不绘制或者透明 const fVisible = rectFillVisible(opacity, fillOpacity, width, height, fill); diff --git a/packages/vrender-core/src/render/contributions/render/utils.ts b/packages/vrender-core/src/render/contributions/render/utils.ts index 92f36314a..2f782f205 100644 --- a/packages/vrender-core/src/render/contributions/render/utils.ts +++ b/packages/vrender-core/src/render/contributions/render/utils.ts @@ -53,7 +53,7 @@ export function fillVisible(opacity: number, fillOpacity: number, fill: IFillTyp } export function rectFillVisible(opacity: number, fillOpacity: number, width: number, height: number, fill: IFillType) { - return fill && opacity * fillOpacity > 0 && width > 0 && height > 0; + return fill && opacity * fillOpacity > 0 && width !== 0 && height !== 0; } /** @@ -68,7 +68,7 @@ export function strokeVisible(opacity: number, strokeOpacity: number) { } export function rectStrokeVisible(opacity: number, strokeOpacity: number, width: number, height: number) { - return opacity * strokeOpacity > 0 && width > 0 && height > 0; + return opacity * strokeOpacity > 0 && width !== 0 && height !== 0; } export function drawPathProxy( diff --git a/packages/vrender-kits/src/render/contributions/rough/rough-rect.ts b/packages/vrender-kits/src/render/contributions/rough/rough-rect.ts index 974b7083b..2d2cf8e43 100644 --- a/packages/vrender-kits/src/render/contributions/rough/rough-rect.ts +++ b/packages/vrender-kits/src/render/contributions/rough/rough-rect.ts @@ -60,8 +60,8 @@ export class RoughCanvasRectRender implements IGraphicRender { stroke = rectAttribute.stroke, fillColor = rectAttribute.fill, strokeColor = rectAttribute.stroke, - width = rectAttribute.width, - height = rectAttribute.height, + x1, + y1, lineWidth = rectAttribute.lineWidth, maxRandomnessOffset = defaultRouthThemeSpec.maxRandomnessOffset, roughness = defaultRouthThemeSpec.roughness, @@ -85,6 +85,12 @@ export class RoughCanvasRectRender implements IGraphicRender { preserveVertices = defaultRouthThemeSpec.preserveVertices, fixedDecimalPlaceDigits = defaultRouthThemeSpec.fixedDecimalPlaceDigits } = rect.attribute as any; + + let { width = rectAttribute.width, height = rectAttribute.height } = rect.attribute; + + width = (width ?? x1 - x) || 0; + height = (height ?? y1 - y) || 0; + rc.rectangle(x, y, width, height, { fill: fill ? (fillColor as string) : undefined, stroke: stroke ? (strokeColor as string) : undefined, diff --git a/packages/vrender/__tests__/browser/src/pages/rect.ts b/packages/vrender/__tests__/browser/src/pages/rect.ts index 4649c8646..cdb14350f 100644 --- a/packages/vrender/__tests__/browser/src/pages/rect.ts +++ b/packages/vrender/__tests__/browser/src/pages/rect.ts @@ -5,18 +5,31 @@ import { addShapesToStage, colorPools } from '../utils'; // container.load(roughModule); export const page = () => { const graphics: IGraphic[] = []; - graphics.push( - createRect({ - x: 100, - y: 100, - width: 20, - height: 100, - fill: colorPools[10], - stroke: [colorPools[0], colorPools[0], colorPools[0], colorPools[0]], - cornerRadius: 10, - lineWidth: 5 - }) - ); + // graphics.push( + // createRect({ + // x: 100, + // y: 100, + // width: 20, + // height: 100, + // fill: colorPools[10], + // stroke: [colorPools[0], colorPools[0], colorPools[0], colorPools[0]], + // cornerRadius: 10, + // lineWidth: 5 + // }) + // ); + + const rect = createRect({ + x: 120, + y: 200, + x1: 100, + y1: 100, + fill: 'red', + // stroke: [colorPools[0], colorPools[0], colorPools[0], colorPools[0]], + _debug_bounds: true, + cornerRadius: 10, + lineWidth: 5 + }); + graphics.push(rect); const r = createRect({ x: 300, @@ -40,6 +53,7 @@ export const page = () => { cornerRadius: [5, 10, 15, 20], lineWidth: 5 }); + graphics.push(r); r.animate().to({ scaleX: 2, scaleY: 2 }, 1000, 'linear'); @@ -60,7 +74,7 @@ export const page = () => { canvas: 'main', autoRender: true }); - + rect.addEventListener('pointerenter', () => console.log('abc')); graphics.forEach(g => { stage.defaultLayer.add(g); }); From 12ab40eedeb201919799348a13a1a51addbab1e0 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Wed, 22 Nov 2023 11:56:28 +0800 Subject: [PATCH 36/40] fix: fix issue with getNamed --- packages/vrender-core/src/common/inversify/container.ts | 4 +++- .../src/common/inversify/syntax/constraint_helpers.ts | 8 +++++++- packages/vrender/src/index.ts | 4 ++-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/packages/vrender-core/src/common/inversify/container.ts b/packages/vrender-core/src/common/inversify/container.ts index 239780f84..fda8aeaaf 100644 --- a/packages/vrender-core/src/common/inversify/container.ts +++ b/packages/vrender-core/src/common/inversify/container.ts @@ -170,7 +170,9 @@ export class Container { private _get(getArgs: GetArgs): T | T[] { const result: T[] = []; - const bindings = this._bindingDictionary.get(getArgs.serviceIdentifier) as Binding[]; + const bindings = this._bindingDictionary.get(getArgs.serviceIdentifier).filter(b => { + return b.constraint(getArgs as any); + }) as Binding[]; bindings.forEach(binding => { result.push(this._resolveFromBinding(binding)); }); diff --git a/packages/vrender-core/src/common/inversify/syntax/constraint_helpers.ts b/packages/vrender-core/src/common/inversify/syntax/constraint_helpers.ts index f55a83c58..62806dd94 100644 --- a/packages/vrender-core/src/common/inversify/syntax/constraint_helpers.ts +++ b/packages/vrender-core/src/common/inversify/syntax/constraint_helpers.ts @@ -4,7 +4,13 @@ import { NAMED_TAG } from '../metadata_keys'; const taggedConstraint = (key: string | number | symbol) => (value: unknown) => { const constraint: interfaces.ConstraintFunction = (request: any) => { - if (request == null || request.constructorArgsMetadata == null) { + if (request == null) { + return false; + } + if (request.key === key && request.value === value) { + return true; + } + if (request.constructorArgsMetadata == null) { return false; } const constructorArgsMetadata = request.constructorArgsMetadata; diff --git a/packages/vrender/src/index.ts b/packages/vrender/src/index.ts index 6b6018ec5..62c40af38 100644 --- a/packages/vrender/src/index.ts +++ b/packages/vrender/src/index.ts @@ -1,10 +1,10 @@ import { container } from '@visactor/vrender-core'; -import { loadBrowserEnv } from '@visactor/vrender-kits'; +import { loadAllEnv, loadBrowserEnv } from '@visactor/vrender-kits'; // 导出版本号 export const version = __VERSION__; -loadBrowserEnv(container); +loadAllEnv(container); export * from '@visactor/vrender-core'; export * from '@visactor/vrender-kits'; From d05f72f462c02d5e1b9cb768feea43961a25889f Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Thu, 23 Nov 2023 19:18:09 +0800 Subject: [PATCH 37/40] feat: upgrade vutils --- common/config/rush/pnpm-lock.yaml | 93 ++++++++--------------- docs/demos/package.json | 2 +- docs/package.json | 2 +- packages/react-vrender-utils/package.json | 2 +- packages/react-vrender/package.json | 2 +- packages/vrender-components/package.json | 6 +- packages/vrender-core/package.json | 2 +- packages/vrender-kits/package.json | 2 +- packages/vrender/package.json | 2 +- 9 files changed, 43 insertions(+), 70 deletions(-) diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 60dfd938d..45789ce9c 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -15,7 +15,7 @@ importers: '@visactor/vchart': 1.3.0 '@visactor/vgrammar': ~0.5.7 '@visactor/vrender': workspace:0.16.16 - '@visactor/vutils': ~0.16.12 + '@visactor/vutils': ~0.16.16 '@vitejs/plugin-react': 3.1.0 axios: ^1.4.0 chalk: ^3.0.0 @@ -38,7 +38,7 @@ importers: '@visactor/vchart': 1.3.0 '@visactor/vgrammar': 0.5.7 '@visactor/vrender': link:../packages/vrender - '@visactor/vutils': 0.16.12 + '@visactor/vutils': 0.16.17 axios: 1.6.2 highlight.js: 11.9.0 lodash: 4.17.21 @@ -72,7 +72,7 @@ importers: '@types/react-dom': ^18.0.0 '@types/react-reconciler': ^0.28.2 '@visactor/vrender': workspace:0.16.16 - '@visactor/vutils': ~0.16.12 + '@visactor/vutils': ~0.16.16 '@vitejs/plugin-react': 3.1.0 eslint: ~8.18.0 react: ^18.0.0 @@ -83,7 +83,7 @@ importers: vite: 3.2.6 dependencies: '@visactor/vrender': link:../vrender - '@visactor/vutils': 0.16.12 + '@visactor/vutils': 0.16.17 react-reconciler: 0.29.0_react@18.2.0 tslib: 2.6.2 devDependencies: @@ -111,7 +111,7 @@ importers: '@types/react-dom': ^18.0.0 '@visactor/react-vrender': workspace:0.16.16 '@visactor/vrender': workspace:0.16.16 - '@visactor/vutils': ~0.16.12 + '@visactor/vutils': ~0.16.16 '@vitejs/plugin-react': 3.1.0 eslint: ~8.18.0 react: ^18.0.0 @@ -123,7 +123,7 @@ importers: dependencies: '@visactor/react-vrender': link:../react-vrender '@visactor/vrender': link:../vrender - '@visactor/vutils': 0.16.12 + '@visactor/vutils': 0.16.17 react-reconciler: 0.29.0_react@18.2.0 tslib: 2.6.2 devDependencies: @@ -151,7 +151,7 @@ importers: '@types/react-dom': ^18.0.0 '@visactor/vrender-core': workspace:0.16.16 '@visactor/vrender-kits': workspace:0.16.16 - '@visactor/vutils': ~0.16.12 + '@visactor/vutils': ~0.16.16 '@vitejs/plugin-react': 3.1.0 canvas: 2.11.2 eslint: ~8.18.0 @@ -174,7 +174,7 @@ importers: '@types/jest': 26.0.24 '@types/react': 18.2.37 '@types/react-dom': 18.2.15 - '@visactor/vutils': 0.16.12 + '@visactor/vutils': 0.16.17 '@vitejs/plugin-react': 3.1.0_vite@3.2.6 canvas: 2.11.2 eslint: 8.18.0 @@ -196,8 +196,8 @@ importers: '@types/jest': ^26.0.0 '@visactor/vrender-core': workspace:0.16.16 '@visactor/vrender-kits': workspace:0.16.16 - '@visactor/vscale': ~0.16.12 - '@visactor/vutils': ~0.16.12 + '@visactor/vscale': ~0.16.16 + '@visactor/vutils': ~0.16.16 eslint: ~8.18.0 jest: ^26.0.0 jest-electron: ^0.1.12 @@ -208,8 +208,8 @@ importers: dependencies: '@visactor/vrender-core': link:../vrender-core '@visactor/vrender-kits': link:../vrender-kits - '@visactor/vscale': 0.16.12 - '@visactor/vutils': 0.16.12 + '@visactor/vscale': 0.16.17 + '@visactor/vutils': 0.16.17 devDependencies: '@internal/bundler': link:../../tools/bundler '@internal/eslint-config': link:../../share/eslint-config @@ -233,7 +233,7 @@ importers: '@types/jest': ^26.0.0 '@types/react': ^18.0.0 '@types/react-dom': ^18.0.0 - '@visactor/vutils': ~0.16.12 + '@visactor/vutils': ~0.16.16 '@vitejs/plugin-react': 3.1.0 color-convert: 2.0.1 eslint: ~8.18.0 @@ -246,7 +246,7 @@ importers: typescript: 4.9.5 vite: 3.2.6 dependencies: - '@visactor/vutils': 0.16.12 + '@visactor/vutils': 0.16.17 color-convert: 2.0.1 devDependencies: '@internal/bundler': link:../../tools/bundler @@ -278,7 +278,7 @@ importers: '@types/react': ^18.0.0 '@types/react-dom': ^18.0.0 '@visactor/vrender-core': workspace:0.16.16 - '@visactor/vutils': ~0.16.12 + '@visactor/vutils': ~0.16.16 '@vitejs/plugin-react': 3.1.0 canvas: 2.11.2 eslint: ~8.18.0 @@ -291,7 +291,7 @@ importers: dependencies: '@resvg/resvg-js': 2.4.1 '@visactor/vrender-core': link:../vrender-core - '@visactor/vutils': 0.16.12 + '@visactor/vutils': 0.16.17 roughjs: 4.5.2 devDependencies: '@internal/bundler': link:../../tools/bundler @@ -2011,6 +2011,7 @@ packages: - supports-color - ts-node - utf-8-validate + dev: true /@jest/core/26.6.3_canvas@2.11.2: resolution: {integrity: sha512-xvV1kKbhfUqFVuZ8Cyo+JPpipAHHAV3kcDBftiduK8EICXmTFddryy3P7NfZt8Pv37rA9nEJBKCCkglCPt/Xjw==} @@ -2050,7 +2051,6 @@ packages: - supports-color - ts-node - utf-8-validate - dev: true /@jest/environment/24.9.0: resolution: {integrity: sha512-5A1QluTPhvdIPFYnO3sZC3smkNeXPVELz7ikPbhUj0bQjB07EoE9qtLrem14ZUYWdVayYbsjVwIiL4WBIMV4aQ==} @@ -2196,6 +2196,7 @@ packages: - supports-color - ts-node - utf-8-validate + dev: true /@jest/test-sequencer/26.6.3_canvas@2.11.2: resolution: {integrity: sha512-YHlVIjP5nfEyjlrSr8t/YdNfU/1XEt7c5b4OxcXCjyRhjzLYu/rO69/WHPuYcbCWkz8kAeZVZp2N2+IOLLEPGw==} @@ -2212,7 +2213,6 @@ packages: - supports-color - ts-node - utf-8-validate - dev: true /@jest/transform/24.9.0: resolution: {integrity: sha512-TcQUmyNRxV94S0QpMOnZl0++6RMiqpbH/ZMccFB/amku6Uwvyb1cjYX7xkp5nGNkbX4QPH/FcB6q1HBTHynLmQ==} @@ -2333,7 +2333,6 @@ packages: transitivePeerDependencies: - encoding - supports-color - dev: true /@nodelib/fs.scandir/2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} @@ -3350,10 +3349,10 @@ packages: '@visactor/vutils': 0.15.14 dev: false - /@visactor/vscale/0.16.12: - resolution: {integrity: sha512-St+1wjcPf3xPLOyjBCFUt0olcDtAToRBvxh99cLsKtSyS3ASLWKwXsgFbFC8d4wv/mrzOZr2jtQJgeogl4d1rw==} + /@visactor/vscale/0.16.17: + resolution: {integrity: sha512-PlerM4g3OYzZBEzVLPMMhLZe8KoWraeMDPZQzcOFJBfe8g6INpLsrj1VlbAmJamDGGqaPbtEdGWLra2TseL9IA==} dependencies: - '@visactor/vutils': 0.16.12 + '@visactor/vutils': 0.16.17 dev: false /@visactor/vutils/0.13.3: @@ -3372,8 +3371,8 @@ packages: eventemitter3: 4.0.7 dev: false - /@visactor/vutils/0.16.12: - resolution: {integrity: sha512-oGj+kjzmTHLNKCu/Fx2ol/PKRTZonCwvw8pBV9RttG64guWIX/aDMd2VIRe418Psr6Ec6aws3GsG5sE5QU3+WQ==} + /@visactor/vutils/0.16.17: + resolution: {integrity: sha512-9vj8hLsUbOnMS467jC0aZM6dJhXJcgNBnL6MwrBtS2aaEJCUWb0DYbitKYPex9GMOryR5k6LrQFWj64vjEkroQ==} dependencies: '@turf/helpers': 6.5.0 '@turf/invariant': 6.5.0 @@ -3439,7 +3438,6 @@ packages: /abbrev/1.1.1: resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} - dev: true /abs-svg-path/0.1.1: resolution: {integrity: sha512-d8XPSGjfyzlXC3Xx891DJRyZfqk5JU0BJrDQcsWomFIV1/BIzPW5HDH5iDdWpqWaav0YVIEzT1RHTwWr0FFshA==} @@ -3613,7 +3611,6 @@ packages: /aproba/2.0.0: resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} - dev: true /archy/1.0.0: resolution: {integrity: sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==} @@ -3625,7 +3622,6 @@ packages: dependencies: delegates: 1.0.0 readable-stream: 3.6.2 - dev: true /arg/4.1.3: resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} @@ -4264,7 +4260,6 @@ packages: transitivePeerDependencies: - encoding - supports-color - dev: true /capture-exit/2.0.0: resolution: {integrity: sha512-PiT/hQmTonHhl/HFGN+Lx3JJUznrVYJ3+AQsnthneZbvW7x+f08Tk7yLJTLEOUvBTbduLeeBkxEaYXUOUrRq6g==} @@ -4359,7 +4354,6 @@ packages: /chownr/2.0.0: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} engines: {node: '>=10'} - dev: true /ci-info/2.0.0: resolution: {integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==} @@ -4596,7 +4590,6 @@ packages: /console-control-strings/1.1.0: resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} - dev: true /convert-source-map/1.9.0: resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} @@ -4808,7 +4801,6 @@ packages: engines: {node: '>=8'} dependencies: mimic-response: 2.1.0 - dev: true /deep-eql/4.1.3: resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} @@ -4886,7 +4878,6 @@ packages: /delegates/1.0.0: resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} - dev: true /detect-file/1.0.0: resolution: {integrity: sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==} @@ -4896,7 +4887,6 @@ packages: /detect-libc/2.0.2: resolution: {integrity: sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==} engines: {node: '>=8'} - dev: true /detect-newline/2.1.0: resolution: {integrity: sha512-CwffZFvlJffUg9zZA0uqrjQayUTC8ob94pnr5sFwaVv3IOmkfUHcWH+jXaQK3askE51Cqe8/9Ql/0uXNwqZ8Zg==} @@ -6032,7 +6022,6 @@ packages: engines: {node: '>= 8'} dependencies: minipass: 3.3.6 - dev: true /fs-mkdirp-stream/1.0.0: resolution: {integrity: sha512-+vSd9frUnapVC2RZYfL3FCB2p3g4TBhaUmrsWlSudsGdnxIuUvBB2QM1VZeBtc49QFwrp+wQLrDs3+xxDgI5gQ==} @@ -6094,7 +6083,6 @@ packages: string-width: 4.2.3 strip-ansi: 6.0.1 wide-align: 1.1.5 - dev: true /gensync/1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} @@ -6524,7 +6512,6 @@ packages: /has-unicode/2.0.1: resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} - dev: true /has-value/0.3.1: resolution: {integrity: sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==} @@ -7156,6 +7143,7 @@ packages: - supports-color - ts-node - utf-8-validate + dev: true /jest-cli/26.6.3_canvas@2.11.2: resolution: {integrity: sha512-GF9noBSa9t08pSyl3CY4frMrqp+aQXFGFkf5hEPbh/pIUFYWMK6ZLTfbmadxJVcJrdRoChlWQsA2VkJcDFK8hg==} @@ -7181,7 +7169,6 @@ packages: - supports-color - ts-node - utf-8-validate - dev: true /jest-config/24.9.0: resolution: {integrity: sha512-RATtQJtVYQrp7fvWg6f5y3pEFj9I+H8sWw4aKxnDZ96mob5i5SD6ZEGWgMLXQ4LE8UurrjbdlLWdUeo+28QpfQ==} @@ -7240,6 +7227,7 @@ packages: - canvas - supports-color - utf-8-validate + dev: true /jest-config/26.6.3_canvas@2.11.2: resolution: {integrity: sha512-t5qdIj/bCj2j7NFVHb2nFB4aUdfucDn3JRKgrZnplb8nieAirAzRSHP8uDEd+qV6ygzg9Pz4YG7UTJf94LPSyg==} @@ -7273,7 +7261,6 @@ packages: - canvas - supports-color - utf-8-validate - dev: true /jest-diff/24.9.0: resolution: {integrity: sha512-qMfrTs8AdJE2iqrTp0hzh7kTd2PQWrsFyj9tORoKmu32xjPjeE4NyjVRDz8ybYwqS2ik8N4hsIpiVTyFeo2lBQ==} @@ -7344,7 +7331,7 @@ packages: jest: ^24.0.0 dependencies: electron: 11.5.0 - jest: 26.6.3 + jest: 26.6.3_canvas@2.11.2 jest-haste-map: 24.9.0 jest-message-util: 24.9.0 jest-mock: 24.9.0 @@ -7388,6 +7375,7 @@ packages: - canvas - supports-color - utf-8-validate + dev: true /jest-environment-jsdom/26.6.2_canvas@2.11.2: resolution: {integrity: sha512-jgPqCruTlt3Kwqg5/WVFyHIOJHsiAvhcp2qiR2QQstuG9yWox5+iHpU3ZrcBxW14T4fe5Z68jAfLRh7joCSP2Q==} @@ -7405,7 +7393,6 @@ packages: - canvas - supports-color - utf-8-validate - dev: true /jest-environment-node/24.9.0: resolution: {integrity: sha512-6d4V2f4nxzIzwendo27Tr0aFm+IXWa0XEUnaH6nU0FMaozxovt+sfRvh4J47wL1OvF83I3SSTu0XK+i4Bqe7uA==} @@ -7546,6 +7533,7 @@ packages: - supports-color - ts-node - utf-8-validate + dev: true /jest-jasmine2/26.6.3_canvas@2.11.2: resolution: {integrity: sha512-kPKUrQtc8aYwBV7CqBg5pu+tmYXlvFlSFYn18ev4gPFtrRzB15N2gW/Roew3187q2w2eHuu0MU9TJz6w0/nPEg==} @@ -7575,7 +7563,6 @@ packages: - supports-color - ts-node - utf-8-validate - dev: true /jest-leak-detector/24.9.0: resolution: {integrity: sha512-tYkFIDsiKTGwb2FG1w8hX9V0aUb2ot8zY/2nFg087dUageonw1zrLMP4W6zsRO59dPkTSKie+D4rhMuP9nRmrA==} @@ -7784,6 +7771,7 @@ packages: - supports-color - ts-node - utf-8-validate + dev: true /jest-runner/26.6.3_canvas@2.11.2: resolution: {integrity: sha512-atgKpRHnaA2OvByG/HpGA4g6CSPS/1LK0jK3gATJAoptC1ojltpmVlYC3TYgdmGp+GLuhzpH30Gvs36szSL2JQ==} @@ -7815,7 +7803,6 @@ packages: - supports-color - ts-node - utf-8-validate - dev: true /jest-runtime/24.9.0: resolution: {integrity: sha512-8oNqgnmF3v2J6PVRM2Jfuj8oX3syKmaynlDMMKQ4iyzbQzIG6th5ub/lM2bCMTmoTKM3ykcUYI2Pw9xwNtjMnw==} @@ -7887,6 +7874,7 @@ packages: - supports-color - ts-node - utf-8-validate + dev: true /jest-runtime/26.6.3_canvas@2.11.2: resolution: {integrity: sha512-lrzyR3N8sacTAMeonbqpnSka1dHNux2uk0qqDXVkMv2c/A3wYnvQ4EXuI013Y6+gSKSCxdaczvf4HF0mVXHRdw==} @@ -7926,7 +7914,6 @@ packages: - supports-color - ts-node - utf-8-validate - dev: true /jest-serializer/24.9.0: resolution: {integrity: sha512-DxYipDr8OvfrKH3Kel6NdED3OXxjvxXZ1uIY2I9OFbGg+vUkkg7AGvi65qbhbWNPvDckXmzMPbK3u3HaDO49bQ==} @@ -8074,6 +8061,7 @@ packages: - supports-color - ts-node - utf-8-validate + dev: true /jest/26.6.3_canvas@2.11.2: resolution: {integrity: sha512-lGS5PXGAzR4RF7V5+XObhqz2KZIDUA1yD0DG6pBVmy10eh0ZIXQImRuzocsI/N2XZ1GrLFwTS27In2i2jlpq1Q==} @@ -8089,7 +8077,6 @@ packages: - supports-color - ts-node - utf-8-validate - dev: true /js-string-escape/1.0.1: resolution: {integrity: sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==} @@ -8187,6 +8174,7 @@ packages: - bufferutil - supports-color - utf-8-validate + dev: true /jsdom/16.7.0_canvas@2.11.2: resolution: {integrity: sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==} @@ -8229,7 +8217,6 @@ packages: - bufferutil - supports-color - utf-8-validate - dev: true /jsesc/0.5.0: resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} @@ -8731,7 +8718,6 @@ packages: /mimic-response/2.1.0: resolution: {integrity: sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==} engines: {node: '>=8'} - dev: true /minimatch/3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} @@ -8761,12 +8747,10 @@ packages: engines: {node: '>=8'} dependencies: yallist: 4.0.0 - dev: true /minipass/5.0.0: resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} engines: {node: '>=8'} - dev: true /minizlib/2.1.2: resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} @@ -8774,7 +8758,6 @@ packages: dependencies: minipass: 3.3.6 yallist: 4.0.0 - dev: true /mixin-deep/1.3.2: resolution: {integrity: sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==} @@ -8880,7 +8863,6 @@ packages: optional: true dependencies: whatwg-url: 5.0.0 - dev: true /node-int64/0.4.0: resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} @@ -8906,7 +8888,6 @@ packages: hasBin: true dependencies: abbrev: 1.1.1 - dev: true /normalize-package-data/2.5.0: resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} @@ -8971,7 +8952,6 @@ packages: console-control-strings: 1.1.0 gauge: 3.0.2 set-blocking: 2.0.0 - dev: true /number-is-nan/1.0.1: resolution: {integrity: sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ==} @@ -10373,7 +10353,6 @@ packages: /simple-concat/1.0.1: resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} - dev: true /simple-get/3.1.1: resolution: {integrity: sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==} @@ -10381,7 +10360,6 @@ packages: decompress-response: 4.2.1 once: 1.4.0 simple-concat: 1.0.1 - dev: true /simple-statistics/7.8.3: resolution: {integrity: sha512-JFvMY00t6SBGtwMuJ+nqgsx9ylkMiJ5JlK9bkj8AdvniIe5615wWQYkKHXe84XtSuc40G/tlrPu0A5/NlJvv8A==} @@ -10804,7 +10782,6 @@ packages: minizlib: 2.1.2 mkdirp: 1.0.4 yallist: 4.0.0 - dev: true /terminal-link/2.1.1: resolution: {integrity: sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==} @@ -11016,7 +10993,6 @@ packages: /tr46/0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - dev: true /tr46/1.0.1: resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} @@ -11041,7 +11017,7 @@ packages: bs-logger: 0.2.6 buffer-from: 1.1.2 fast-json-stable-stringify: 2.1.0 - jest: 26.6.3 + jest: 26.6.3_canvas@2.11.2 jest-util: 26.6.2 json5: 2.2.3 lodash: 4.17.21 @@ -11679,7 +11655,6 @@ packages: /webidl-conversions/3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - dev: true /webidl-conversions/4.0.2: resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} @@ -11711,7 +11686,6 @@ packages: dependencies: tr46: 0.0.3 webidl-conversions: 3.0.1 - dev: true /whatwg-url/6.5.0: resolution: {integrity: sha512-rhRZRqx/TLJQWUpQ6bmrt2UV4f0HCQ463yQuONJqC6fO2VoEb1pTYddbe59SkYq87aoM5A3bdhMZiUiVws+fzQ==} @@ -11789,7 +11763,6 @@ packages: resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} dependencies: string-width: 4.2.3 - dev: true /word-wrap/1.2.5: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} diff --git a/docs/demos/package.json b/docs/demos/package.json index ec7128476..b2df53791 100644 --- a/docs/demos/package.json +++ b/docs/demos/package.json @@ -12,7 +12,7 @@ "@internal/eslint-config": "workspace:*", "@internal/ts-config": "workspace:*", "@visactor/vrender-kits": "workspace:0.14.8", - "@visactor/vutils": "~0.16.12", + "@visactor/vutils": "~0.16.16", "d3-scale-chromatic": "^3.0.0", "lodash": "4.17.21", "dat.gui": "^0.7.9", diff --git a/docs/package.json b/docs/package.json index 303b975f3..0d5ea2e51 100644 --- a/docs/package.json +++ b/docs/package.json @@ -12,7 +12,7 @@ "dependencies": { "@arco-design/web-react": "2.46.1", "@visactor/vchart": "1.3.0", - "@visactor/vutils": "~0.16.12", + "@visactor/vutils": "~0.16.16", "@visactor/vgrammar": "~0.5.7", "@visactor/vrender": "workspace:0.16.16", "markdown-it": "^13.0.0", diff --git a/packages/react-vrender-utils/package.json b/packages/react-vrender-utils/package.json index ca7373c6d..9e2b83cb2 100644 --- a/packages/react-vrender-utils/package.json +++ b/packages/react-vrender-utils/package.json @@ -27,7 +27,7 @@ "dependencies": { "@visactor/vrender": "workspace:0.16.16", "@visactor/react-vrender": "workspace:0.16.16", - "@visactor/vutils": "~0.16.12", + "@visactor/vutils": "~0.16.16", "react-reconciler": "^0.29.0", "tslib": "^2.3.1" }, diff --git a/packages/react-vrender/package.json b/packages/react-vrender/package.json index aa377166a..fc0364342 100644 --- a/packages/react-vrender/package.json +++ b/packages/react-vrender/package.json @@ -25,7 +25,7 @@ }, "dependencies": { "@visactor/vrender": "workspace:0.16.16", - "@visactor/vutils": "~0.16.12", + "@visactor/vutils": "~0.16.16", "react-reconciler": "^0.29.0", "tslib": "^2.3.1" }, diff --git a/packages/vrender-components/package.json b/packages/vrender-components/package.json index 77df4d80b..92dcdfac0 100644 --- a/packages/vrender-components/package.json +++ b/packages/vrender-components/package.json @@ -26,15 +26,15 @@ "dependencies": { "@visactor/vrender-core": "workspace:0.16.16", "@visactor/vrender-kits": "workspace:0.16.16", - "@visactor/vutils": "~0.16.12", - "@visactor/vscale": "~0.16.12" + "@visactor/vutils": "~0.16.16", + "@visactor/vscale": "~0.16.16" }, "devDependencies": { "@internal/bundler": "workspace:*", "@internal/eslint-config": "workspace:*", "@internal/ts-config": "workspace:*", "@rushstack/eslint-patch": "~1.1.4", - "@visactor/vscale": "~0.16.12", + "@visactor/vscale": "~0.16.16", "@types/jest": "^26.0.0", "jest": "^26.0.0", "jest-electron": "^0.1.12", diff --git a/packages/vrender-core/package.json b/packages/vrender-core/package.json index bf7c87d41..ab31729d6 100644 --- a/packages/vrender-core/package.json +++ b/packages/vrender-core/package.json @@ -26,7 +26,7 @@ }, "dependencies": { "color-convert": "2.0.1", - "@visactor/vutils": "~0.16.12" + "@visactor/vutils": "~0.16.16" }, "devDependencies": { "@internal/bundler": "workspace:*", diff --git a/packages/vrender-kits/package.json b/packages/vrender-kits/package.json index 15d79f7c3..94c8da0cd 100644 --- a/packages/vrender-kits/package.json +++ b/packages/vrender-kits/package.json @@ -22,7 +22,7 @@ }, "dependencies": { "@visactor/vrender-core": "workspace:0.16.16", - "@visactor/vutils": "~0.16.12", + "@visactor/vutils": "~0.16.16", "@resvg/resvg-js": "2.4.1", "roughjs": "4.5.2" }, diff --git a/packages/vrender/package.json b/packages/vrender/package.json index d62db38d5..6d6fdca63 100644 --- a/packages/vrender/package.json +++ b/packages/vrender/package.json @@ -33,7 +33,7 @@ "@internal/eslint-config": "workspace:*", "@internal/ts-config": "workspace:*", "@rushstack/eslint-patch": "~1.1.4", - "@visactor/vutils": "~0.16.12", + "@visactor/vutils": "~0.16.16", "canvas": "2.11.2", "react": "^18.0.0", "react-dom": "^18.0.0", From 85218e81cfcaed78670ebbf6b98e8989514abb53 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Fri, 24 Nov 2023 19:12:30 +0800 Subject: [PATCH 38/40] feat: text support background, closed #711 --- ...feat-text-background_2023-11-24-11-16.json | 10 +++ .../contributions/text-contribution-render.ts | 73 +++++++++++++++---- .../contributions/render/richtext-render.ts | 36 ++++++++- .../contributions/render/text-render.ts | 2 + .../__tests__/browser/src/pages/richtext.ts | 1 + .../__tests__/browser/src/pages/text.ts | 3 +- 6 files changed, 106 insertions(+), 19 deletions(-) create mode 100644 common/changes/@visactor/vrender-core/feat-text-background_2023-11-24-11-16.json diff --git a/common/changes/@visactor/vrender-core/feat-text-background_2023-11-24-11-16.json b/common/changes/@visactor/vrender-core/feat-text-background_2023-11-24-11-16.json new file mode 100644 index 000000000..07f1e35a5 --- /dev/null +++ b/common/changes/@visactor/vrender-core/feat-text-background_2023-11-24-11-16.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vrender-core", + "comment": "feat: text support background, closed #711", + "type": "none" + } + ], + "packageName": "@visactor/vrender-core" +} \ No newline at end of file diff --git a/packages/vrender-core/src/render/contributions/render/contributions/text-contribution-render.ts b/packages/vrender-core/src/render/contributions/render/contributions/text-contribution-render.ts index 38de8818a..e5bd2edf5 100644 --- a/packages/vrender-core/src/render/contributions/render/contributions/text-contribution-render.ts +++ b/packages/vrender-core/src/render/contributions/render/contributions/text-contribution-render.ts @@ -1,22 +1,63 @@ -import { injectable } from '../../../../common/inversify-lite'; +import { BaseRenderContributionTime } from '../../../../common/enums'; import type { - IGraphicAttribute, IContext2d, - IMarkAttribute, - IArc, - IArcGraphicAttribute, - IThemeAttribute, - IArcRenderContribution, - ITextRenderContribution + IDrawContext, + IGraphicAttribute, + IText, + ITextRenderContribution, + IThemeAttribute } from '../../../../interface'; -import { getScaledStroke } from '../../../../common/canvas-utils'; -import { - DefaultBaseBackgroundRenderContribution, - // DefaultBasePopTipRenderContribution, - DefaultBaseTextureRenderContribution -} from './base-contribution-render'; -import { drawArcPath } from '../utils'; -import { BaseRenderContributionTime } from '../../../../common/enums'; +import { DefaultBaseBackgroundRenderContribution } from './base-contribution-render'; + +export class DefaultTextBackgroundRenderContribution + extends DefaultBaseBackgroundRenderContribution + implements ITextRenderContribution +{ + time: BaseRenderContributionTime = BaseRenderContributionTime.beforeFillStroke; + + drawShape( + graphic: IText, + context: IContext2d, + x: number, + y: number, + doFill: boolean, + doStroke: boolean, + fVisible: boolean, + sVisible: boolean, + graphicAttribute: Required, + drawContext: IDrawContext, + fillCb?: (ctx: IContext2d, markAttribute: Partial, themeAttribute: IThemeAttribute) => boolean, + strokeCb?: (ctx: IContext2d, markAttribute: Partial, themeAttribute: IThemeAttribute) => boolean + ) { + const { background, backgroundMode = graphicAttribute.backgroundMode } = graphic.attribute; + if (!background) { + return; + } + + const b = graphic.AABBBounds; + if (graphic.backgroundImg && graphic.resources) { + const res = graphic.resources.get(background); + if (res.state !== 'success' || !res.data) { + return; + } + + context.highPerformanceSave(); + + context.setTransformFromMatrix(graphic.parent.globalTransMatrix, true); + + this.doDrawImage(context, res.data, b, backgroundMode); + context.highPerformanceRestore(); + context.setTransformForCurrent(); + } else { + context.highPerformanceSave(); + context.fillStyle = background as string; + context.fillRect(b.x1, b.y1, b.width(), b.height()); + context.highPerformanceRestore(); + } + } +} + +export const defaultTextBackgroundRenderContribution = new DefaultTextBackgroundRenderContribution(); // @injectable() // export class DefaultTextPopTipRenderContribution diff --git a/packages/vrender-core/src/render/contributions/render/richtext-render.ts b/packages/vrender-core/src/render/contributions/render/richtext-render.ts index 9be7640a5..06a9e2298 100644 --- a/packages/vrender-core/src/render/contributions/render/richtext-render.ts +++ b/packages/vrender-core/src/render/contributions/render/richtext-render.ts @@ -12,17 +12,23 @@ import type { } from '../../../interface'; import { fillVisible } from './utils'; import { BaseRender } from './base-render'; +import { defaultTextBackgroundRenderContribution } from './contributions/text-contribution-render'; @injectable() export class DefaultCanvasRichTextRender extends BaseRender implements IGraphicRender { type: 'richtext'; numberType: number = RICHTEXT_NUMBER_TYPE; + constructor() { + super(); + this.builtinContributions = [defaultTextBackgroundRenderContribution as any]; + this.init(); + } + drawShape(richtext: IRichText, context: IContext2d, x: number, y: number, drawContext: IDrawContext) { const richtextAttribute = getTheme(richtext).richtext; const { - width = richtextAttribute.width, - height = richtextAttribute.height, + strokeOpacity = richtextAttribute.strokeOpacity, opacity = richtextAttribute.opacity, fillOpacity = richtextAttribute.fillOpacity, visible = richtextAttribute.visible @@ -33,13 +39,39 @@ export class DefaultCanvasRichTextRender extends BaseRender implement } const fVisible = fillVisible(opacity, fillOpacity, true); + const sVisible = fillVisible(opacity, strokeOpacity, true); if (!fVisible) { return; } context.translate(x, y); + this.beforeRenderStep( + richtext, + context, + x, + y, + fVisible, + sVisible, + fVisible, + sVisible, + richtextAttribute, + drawContext + ); const frame = richtext.getFrameCache(); frame.draw(context, this.drawIcon); + + this.afterRenderStep( + richtext, + context, + x, + y, + fVisible, + sVisible, + fVisible, + sVisible, + richtextAttribute, + drawContext + ); } drawIcon(icon: IRichTextIcon, context: IContext2d, x: number, y: number, baseline: number) { diff --git a/packages/vrender-core/src/render/contributions/render/text-render.ts b/packages/vrender-core/src/render/contributions/render/text-render.ts index a07789852..3e5079b6d 100644 --- a/packages/vrender-core/src/render/contributions/render/text-render.ts +++ b/packages/vrender-core/src/render/contributions/render/text-render.ts @@ -21,6 +21,7 @@ import { TextRenderContribution } from './contributions/constants'; import { matrixAllocate } from '../../../allocator/matrix-allocate'; import { max } from '@visactor/vutils'; import { calculateLineHeight } from '../../../common/utils'; +import { defaultTextBackgroundRenderContribution } from './contributions/text-contribution-render'; @injectable() export class DefaultCanvasTextRender extends BaseRender implements IGraphicRender { @@ -33,6 +34,7 @@ export class DefaultCanvasTextRender extends BaseRender implements IGraph protected readonly textRenderContribitions: IContributionProvider ) { super(); + this.builtinContributions = [defaultTextBackgroundRenderContribution as any]; this.init(textRenderContribitions); } diff --git a/packages/vrender/__tests__/browser/src/pages/richtext.ts b/packages/vrender/__tests__/browser/src/pages/richtext.ts index 73a78f5a4..89fd7182a 100644 --- a/packages/vrender/__tests__/browser/src/pages/richtext.ts +++ b/packages/vrender/__tests__/browser/src/pages/richtext.ts @@ -13,6 +13,7 @@ export const page = () => { visible: true, fontSize: 26, width: 0, + background: 'green', // "textAlign": "center", textConfig: [ { diff --git a/packages/vrender/__tests__/browser/src/pages/text.ts b/packages/vrender/__tests__/browser/src/pages/text.ts index f5c8a9784..0a27d2cf6 100644 --- a/packages/vrender/__tests__/browser/src/pages/text.ts +++ b/packages/vrender/__tests__/browser/src/pages/text.ts @@ -53,7 +53,8 @@ export const page = () => { y: 100, fontFamily: 'Arial', text: 'aaa这是aaa', - fill: 'red' + fill: 'red', + background: 'green' }); console.log(t.AABBBounds); graphics.push(t); From 476986b345f8550b9fc827877803c65a5a314dd8 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Mon, 27 Nov 2023 20:37:24 +0800 Subject: [PATCH 39/40] fix: fix issue with vrender-kits tree shaking --- packages/vrender-kits/src/env/all.ts | 3 +- packages/vrender-kits/src/env/browser.ts | 15 +- .../src/env/contributions/module.ts | 138 +++++++++--------- packages/vrender-kits/src/env/feishu.ts | 14 +- packages/vrender-kits/src/env/index.ts | 2 +- packages/vrender-kits/src/env/lynx.ts | 15 +- packages/vrender-kits/src/env/node.ts | 19 ++- packages/vrender-kits/src/env/taro.ts | 15 +- packages/vrender-kits/src/env/wx.ts | 15 +- packages/vrender-kits/src/picker/index.ts | 3 +- packages/vrender-kits/src/picker/module.ts | 40 ----- packages/vrender/src/index.ts | 10 +- 12 files changed, 160 insertions(+), 129 deletions(-) delete mode 100644 packages/vrender-kits/src/picker/module.ts diff --git a/packages/vrender-kits/src/env/all.ts b/packages/vrender-kits/src/env/all.ts index 779c9b801..8d015a90c 100644 --- a/packages/vrender-kits/src/env/all.ts +++ b/packages/vrender-kits/src/env/all.ts @@ -6,7 +6,8 @@ import { loadNodeEnv } from './node'; import { loadTaroEnv } from './taro'; import { loadWxEnv } from './wx'; import { loadCanvasPicker } from '../picker/canvas-module'; -import { loadMathPicker } from '../picker'; +import { loadMathPicker } from '../picker/math-module'; +// import { loadMathPicker } from '../picker'; export function loadAllEnv(container: Container) { loadAllModule(container); diff --git a/packages/vrender-kits/src/env/browser.ts b/packages/vrender-kits/src/env/browser.ts index 5162ab410..ddafa7af4 100644 --- a/packages/vrender-kits/src/env/browser.ts +++ b/packages/vrender-kits/src/env/browser.ts @@ -1,8 +1,19 @@ -import { container, type Container } from '@visactor/vrender-core'; -import { browserEnvModule } from './contributions/module'; +import { container, ContainerModule, type Container, EnvContribution } from '@visactor/vrender-core'; +// import { browserEnvModule } from './contributions/module'; import { browserCanvasModule } from '../canvas/contributions/browser/modules'; import { loadCanvasPicker } from '../picker/canvas-module'; import { browserWindowModule } from '../window/contributions/browser-contribution'; +import { BrowserEnvContribution } from './contributions/browser-contribution'; + +let isBrowserBound = false; +export const browserEnvModule = new ContainerModule(bind => { + // browser + if (!isBrowserBound) { + isBrowserBound = true; + bind(BrowserEnvContribution).toSelf().inSingletonScope(); + bind(EnvContribution).toService(BrowserEnvContribution); + } +}); let loaded = false; export function loadBrowserEnv(container: Container, loadPicker: boolean = true) { diff --git a/packages/vrender-kits/src/env/contributions/module.ts b/packages/vrender-kits/src/env/contributions/module.ts index 6427667fb..0adf97534 100644 --- a/packages/vrender-kits/src/env/contributions/module.ts +++ b/packages/vrender-kits/src/env/contributions/module.ts @@ -1,76 +1,76 @@ -import { ContainerModule, EnvContribution } from '@visactor/vrender-core'; -import { BrowserEnvContribution } from './browser-contribution'; -import { FeishuEnvContribution } from './feishu-contribution'; -import { TaroEnvContribution } from './taro-contribution'; -import { LynxEnvContribution } from './lynx-contribution'; -import { WxEnvContribution } from './wx-contribution'; -import { NodeEnvContribution } from './node-contribution'; +// import { ContainerModule, EnvContribution } from '@visactor/vrender-core'; +// import { BrowserEnvContribution } from './browser-contribution'; +// import { FeishuEnvContribution } from './feishu-contribution'; +// import { TaroEnvContribution } from './taro-contribution'; +// import { LynxEnvContribution } from './lynx-contribution'; +// import { WxEnvContribution } from './wx-contribution'; +// import { NodeEnvContribution } from './node-contribution'; -let isBrowserBound = false; -export const browserEnvModule = new ContainerModule(bind => { - // browser - if (!isBrowserBound) { - isBrowserBound = true; - bind(BrowserEnvContribution).toSelf().inSingletonScope(); - bind(EnvContribution).toService(BrowserEnvContribution); - } -}); +// let isBrowserBound = false; +// export const browserEnvModule = new ContainerModule(bind => { +// // browser +// if (!isBrowserBound) { +// isBrowserBound = true; +// bind(BrowserEnvContribution).toSelf().inSingletonScope(); +// bind(EnvContribution).toService(BrowserEnvContribution); +// } +// }); -let isFeishuBound = false; -export const feishuEnvModule = new ContainerModule(bind => { - // feishu - if (!isFeishuBound) { - isFeishuBound = true; - bind(FeishuEnvContribution).toSelf().inSingletonScope(); - bind(EnvContribution).toService(FeishuEnvContribution); - } -}); +// let isFeishuBound = false; +// export const feishuEnvModule = new ContainerModule(bind => { +// // feishu +// if (!isFeishuBound) { +// isFeishuBound = true; +// bind(FeishuEnvContribution).toSelf().inSingletonScope(); +// bind(EnvContribution).toService(FeishuEnvContribution); +// } +// }); -let isTaroBound = false; -export const taroEnvModule = new ContainerModule(bind => { - // taro - if (!isTaroBound) { - isTaroBound = true; - bind(TaroEnvContribution).toSelf().inSingletonScope(); - bind(EnvContribution).toService(TaroEnvContribution); - } -}); +// let isTaroBound = false; +// export const taroEnvModule = new ContainerModule(bind => { +// // taro +// if (!isTaroBound) { +// isTaroBound = true; +// bind(TaroEnvContribution).toSelf().inSingletonScope(); +// bind(EnvContribution).toService(TaroEnvContribution); +// } +// }); -let isTTBound = false; -export const ttEnvModule = new ContainerModule(bind => { - if (!isTTBound) { - isTTBound = true; - bind(TaroEnvContribution).toSelf().inSingletonScope(); - bind(EnvContribution).toService(TaroEnvContribution); - } -}); +// let isTTBound = false; +// export const ttEnvModule = new ContainerModule(bind => { +// if (!isTTBound) { +// isTTBound = true; +// bind(TaroEnvContribution).toSelf().inSingletonScope(); +// bind(EnvContribution).toService(TaroEnvContribution); +// } +// }); -let isLynxBound = false; -export const lynxEnvModule = new ContainerModule(bind => { - // lynx - if (!isLynxBound) { - isLynxBound = true; - bind(LynxEnvContribution).toSelf().inSingletonScope(); - bind(EnvContribution).toService(LynxEnvContribution); - } -}); +// let isLynxBound = false; +// export const lynxEnvModule = new ContainerModule(bind => { +// // lynx +// if (!isLynxBound) { +// isLynxBound = true; +// bind(LynxEnvContribution).toSelf().inSingletonScope(); +// bind(EnvContribution).toService(LynxEnvContribution); +// } +// }); -let isWxBound = false; -export const wxEnvModule = new ContainerModule(bind => { - // wx - if (!isWxBound) { - isWxBound = true; - bind(WxEnvContribution).toSelf().inSingletonScope(); - bind(EnvContribution).toService(WxEnvContribution); - } -}); +// let isWxBound = false; +// export const wxEnvModule = new ContainerModule(bind => { +// // wx +// if (!isWxBound) { +// isWxBound = true; +// bind(WxEnvContribution).toSelf().inSingletonScope(); +// bind(EnvContribution).toService(WxEnvContribution); +// } +// }); -let isNodeBound = false; -export const nodeEnvModule = new ContainerModule(bind => { - // node - if (!isNodeBound) { - isNodeBound = true; - bind(NodeEnvContribution).toSelf().inSingletonScope(); - bind(EnvContribution).toService(NodeEnvContribution); - } -}); +// let isNodeBound = false; +// export const nodeEnvModule = new ContainerModule(bind => { +// // node +// if (!isNodeBound) { +// isNodeBound = true; +// bind(NodeEnvContribution).toSelf().inSingletonScope(); +// bind(EnvContribution).toService(NodeEnvContribution); +// } +// }); diff --git a/packages/vrender-kits/src/env/feishu.ts b/packages/vrender-kits/src/env/feishu.ts index e1a94ad84..ffa3a2bbc 100644 --- a/packages/vrender-kits/src/env/feishu.ts +++ b/packages/vrender-kits/src/env/feishu.ts @@ -1,8 +1,18 @@ -import { container, type Container } from '@visactor/vrender-core'; -import { feishuEnvModule } from './contributions/module'; +import { container, ContainerModule, type Container, EnvContribution } from '@visactor/vrender-core'; import { feishuCanvasModule } from '../canvas/contributions/feishu/modules'; import { feishuWindowModule } from '../window/contributions/feishu-contribution'; import { loadMathPicker } from '../picker/math-module'; +import { FeishuEnvContribution } from './contributions/feishu-contribution'; + +let isFeishuBound = false; +export const feishuEnvModule = new ContainerModule(bind => { + // feishu + if (!isFeishuBound) { + isFeishuBound = true; + bind(FeishuEnvContribution).toSelf().inSingletonScope(); + bind(EnvContribution).toService(FeishuEnvContribution); + } +}); let loaded = false; export function loadFeishuEnv(container: Container, loadPicker: boolean = true) { diff --git a/packages/vrender-kits/src/env/index.ts b/packages/vrender-kits/src/env/index.ts index af5ed830b..2cf515f50 100644 --- a/packages/vrender-kits/src/env/index.ts +++ b/packages/vrender-kits/src/env/index.ts @@ -1,6 +1,6 @@ export * from './all'; export * from './browser'; -export * from './feishu'; +// export * from './feishu'; export * from './lynx'; export * from './node'; export * from './taro'; diff --git a/packages/vrender-kits/src/env/lynx.ts b/packages/vrender-kits/src/env/lynx.ts index 637741a23..ec339b594 100644 --- a/packages/vrender-kits/src/env/lynx.ts +++ b/packages/vrender-kits/src/env/lynx.ts @@ -1,8 +1,19 @@ -import { container, type Container } from '@visactor/vrender-core'; +import { container, ContainerModule, type Container, EnvContribution } from '@visactor/vrender-core'; import { loadMathPicker } from '../picker/math-module'; import { lynxWindowModule } from '../window/contributions/lynx-contribution'; import { lynxCanvasModule } from '../canvas/contributions/lynx/modules'; -import { lynxEnvModule } from './contributions/module'; +import { LynxEnvContribution } from './contributions/lynx-contribution'; +// import { lynxEnvModule } from './contributions/module'; + +let isLynxBound = false; +export const lynxEnvModule = new ContainerModule(bind => { + // lynx + if (!isLynxBound) { + isLynxBound = true; + bind(LynxEnvContribution).toSelf().inSingletonScope(); + bind(EnvContribution).toService(LynxEnvContribution); + } +}); let loaded = false; export function loadLynxEnv(container: Container, loadPicker: boolean = true) { diff --git a/packages/vrender-kits/src/env/node.ts b/packages/vrender-kits/src/env/node.ts index e4f27c65f..a3e68a6a0 100644 --- a/packages/vrender-kits/src/env/node.ts +++ b/packages/vrender-kits/src/env/node.ts @@ -1,8 +1,19 @@ -import { container, type Container } from '@visactor/vrender-core'; -import { loadMathPicker } from '../picker/math-module'; -import { nodeEnvModule } from './contributions/module'; +import { container, ContainerModule, type Container, EnvContribution } from '@visactor/vrender-core'; +// import { loadMathPicker } from '../picker/math-module'; +// import { nodeEnvModule } from './contributions/module'; import { nodeCanvasModule } from '../canvas/contributions/node/modules'; import { nodeWindowModule } from '../window/contributions/node-contribution'; +import { NodeEnvContribution } from './contributions/node-contribution'; + +let isNodeBound = false; +export const nodeEnvModule = new ContainerModule(bind => { + // node + if (!isNodeBound) { + isNodeBound = true; + bind(NodeEnvContribution).toSelf().inSingletonScope(); + bind(EnvContribution).toService(NodeEnvContribution); + } +}); let loaded = false; export function loadNodeEnv(container: Container, loadPicker: boolean = true) { @@ -11,7 +22,7 @@ export function loadNodeEnv(container: Container, loadPicker: boolean = true) { container.load(nodeEnvModule); container.load(nodeCanvasModule); container.load(nodeWindowModule); - loadPicker && loadMathPicker(container); + // loadPicker && loadMathPicker(container); } } diff --git a/packages/vrender-kits/src/env/taro.ts b/packages/vrender-kits/src/env/taro.ts index 2fbf0a5aa..db7eb03b7 100644 --- a/packages/vrender-kits/src/env/taro.ts +++ b/packages/vrender-kits/src/env/taro.ts @@ -1,8 +1,19 @@ -import { container, type Container } from '@visactor/vrender-core'; +import { container, ContainerModule, type Container, EnvContribution } from '@visactor/vrender-core'; import { loadMathPicker } from '../picker/math-module'; -import { taroEnvModule } from './contributions/module'; +// import { taroEnvModule } from './contributions/module'; import { taroCanvasModule } from '../canvas/contributions/taro/modules'; import { taroWindowModule } from '../window/contributions/taro-contribution'; +import { TaroEnvContribution } from './contributions/taro-contribution'; + +let isTaroBound = false; +export const taroEnvModule = new ContainerModule(bind => { + // taro + if (!isTaroBound) { + isTaroBound = true; + bind(TaroEnvContribution).toSelf().inSingletonScope(); + bind(EnvContribution).toService(TaroEnvContribution); + } +}); let loaded = false; export function loadTaroEnv(container: Container, loadPicker: boolean = true) { diff --git a/packages/vrender-kits/src/env/wx.ts b/packages/vrender-kits/src/env/wx.ts index 7b5dae8f5..8611e06ea 100644 --- a/packages/vrender-kits/src/env/wx.ts +++ b/packages/vrender-kits/src/env/wx.ts @@ -1,8 +1,19 @@ -import { container, type Container } from '@visactor/vrender-core'; +import { container, ContainerModule, type Container, EnvContribution } from '@visactor/vrender-core'; import { loadMathPicker } from '../picker/math-module'; -import { wxEnvModule } from './contributions/module'; +// import { wxEnvModule } from './contributions/module'; import { wxCanvasModule } from '../canvas/contributions/wx/modules'; import { wxWindowModule } from '../window/contributions/wx-contribution'; +import { WxEnvContribution } from './contributions/wx-contribution'; + +let isWxBound = false; +export const wxEnvModule = new ContainerModule(bind => { + // wx + if (!isWxBound) { + isWxBound = true; + bind(WxEnvContribution).toSelf().inSingletonScope(); + bind(EnvContribution).toService(WxEnvContribution); + } +}); let loaded = false; export function loadWxEnv(container: Container, loadPicker: boolean = true) { diff --git a/packages/vrender-kits/src/picker/index.ts b/packages/vrender-kits/src/picker/index.ts index 20a96c9a5..ba9e376c5 100644 --- a/packages/vrender-kits/src/picker/index.ts +++ b/packages/vrender-kits/src/picker/index.ts @@ -1 +1,2 @@ -export * from './module'; +// export * from './canvas-module'; +// export * from './math-module'; diff --git a/packages/vrender-kits/src/picker/module.ts b/packages/vrender-kits/src/picker/module.ts deleted file mode 100644 index 3b1fbd421..000000000 --- a/packages/vrender-kits/src/picker/module.ts +++ /dev/null @@ -1,40 +0,0 @@ -import type { container } from '@visactor/vrender-core'; -import { ContainerModule, PickerService } from '@visactor/vrender-core'; -import { DefaultCanvasPickerService } from './canvas-picker-service'; -import canvasModule from './contributions/canvas-picker/module'; -import mathModule from './contributions/math-picker/module'; -import { DefaultMathPickerService } from './math-picker-service'; - -// canvas -export const canvasPickerModule = new ContainerModule((bind, unbind, isBound, rebind) => { - if (!isBound(DefaultCanvasPickerService)) { - bind(DefaultCanvasPickerService).toSelf().inSingletonScope(); - } - if (isBound(PickerService)) { - rebind(PickerService).toService(DefaultCanvasPickerService); - } else { - bind(PickerService).toService(DefaultCanvasPickerService); - } -}); - -export function loadCanvasPicker(c: typeof container) { - c.load(canvasModule); - c.load(canvasPickerModule); -} - -// math -export const mathPickerModule = new ContainerModule((bind, unbind, isBound, rebind) => { - if (!isBound(DefaultMathPickerService)) { - bind(DefaultMathPickerService).toSelf().inSingletonScope(); - } - if (isBound(PickerService)) { - rebind(PickerService).toService(DefaultMathPickerService); - } else { - bind(PickerService).toService(DefaultMathPickerService); - } -}); - -export function loadMathPicker(c: typeof container) { - c.load(mathModule); - c.load(mathPickerModule); -} diff --git a/packages/vrender/src/index.ts b/packages/vrender/src/index.ts index 62c40af38..e4ac3f431 100644 --- a/packages/vrender/src/index.ts +++ b/packages/vrender/src/index.ts @@ -1,10 +1,14 @@ -import { container } from '@visactor/vrender-core'; -import { loadAllEnv, loadBrowserEnv } from '@visactor/vrender-kits'; +import { container, isBrowserEnv, isNodeEnv } from '@visactor/vrender-core'; +import { loadBrowserEnv, loadNodeEnv } from '@visactor/vrender-kits'; // 导出版本号 export const version = __VERSION__; -loadAllEnv(container); +if (isBrowserEnv()) { + loadBrowserEnv(container); +} else if (isNodeEnv()) { + loadNodeEnv(container); +} export * from '@visactor/vrender-core'; export * from '@visactor/vrender-kits'; From 2a63f19413faffced659c0252ee6e1d2afa4fd75 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Tue, 28 Nov 2023 12:18:18 +0800 Subject: [PATCH 40/40] feat: support add canvas id --- .../vrender-core/src/canvas/contributions/base-canvas.ts | 6 +++++- packages/vrender-core/src/core/layer-service.ts | 9 ++++++++- .../src/window/contributions/browser-contribution.ts | 9 ++++++++- packages/vrender/__tests__/browser/src/pages/text.ts | 2 +- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/packages/vrender-core/src/canvas/contributions/base-canvas.ts b/packages/vrender-core/src/canvas/contributions/base-canvas.ts index 4a1d8cbc9..bee45603e 100644 --- a/packages/vrender-core/src/canvas/contributions/base-canvas.ts +++ b/packages/vrender-core/src/canvas/contributions/base-canvas.ts @@ -103,6 +103,7 @@ export abstract class BaseCanvas implements ICanvas { dpr = DefaultConfig.DPR, x, y, + id, canvasControled = true } = params; const offsetX = 0; @@ -119,7 +120,10 @@ export abstract class BaseCanvas implements ICanvas { this._displayHeight = height; this._dpr = dpr; this._nativeCanvas = nativeCanvas; - this._id = nativeCanvas.id; + this._id = nativeCanvas.id ?? id; + if (id) { + nativeCanvas.id = id; + } this.init(params); } diff --git a/packages/vrender-core/src/core/layer-service.ts b/packages/vrender-core/src/core/layer-service.ts index 108c6da77..7b936593e 100644 --- a/packages/vrender-core/src/core/layer-service.ts +++ b/packages/vrender-core/src/core/layer-service.ts @@ -17,6 +17,13 @@ export class DefaultLayerService implements ILayerService { declare dynamicLayerCountInEnv: number; declare inited: boolean; declare global: IGlobal; + static idprefix: string = 'visactor_layer'; + static prefix_count: number = 0; + + static GenerateLayerId() { + return `${DefaultLayerService.idprefix}_${DefaultLayerService.prefix_count++}`; + } + constructor() { this.layerMap = new Map(); this.global = application.global; @@ -68,7 +75,7 @@ export class DefaultLayerService implements ILayerService { main: false, ...options, layerMode, - canvasId: options.canvasId, + canvasId: options.canvasId ?? DefaultLayerService.GenerateLayerId(), layerHandler }); const stageLayers = this.layerMap.get(stage) || []; diff --git a/packages/vrender-kits/src/window/contributions/browser-contribution.ts b/packages/vrender-kits/src/window/contributions/browser-contribution.ts index f13c2d0a0..e66fc18bb 100644 --- a/packages/vrender-kits/src/window/contributions/browser-contribution.ts +++ b/packages/vrender-kits/src/window/contributions/browser-contribution.ts @@ -41,6 +41,13 @@ export class BrowserWindowHandlerContribution return this.canvas.nativeCanvas.parentElement; } + static idprefix: string = 'visactor_window'; + static prefix_count: number = 0; + + static GenerateCanvasId() { + return `${BrowserWindowHandlerContribution.idprefix}_${BrowserWindowHandlerContribution.prefix_count++}`; + } + constructor() { super(); this._canvasIsIntersecting = true; @@ -158,7 +165,7 @@ export class BrowserWindowHandlerContribution dpr: params.dpr, nativeCanvas, container, - id: Generator.GenAutoIncrementId().toString(), + id: BrowserWindowHandlerContribution.GenerateCanvasId(), canvasControled: true }; this.canvas = new BrowserCanvas(options); diff --git a/packages/vrender/__tests__/browser/src/pages/text.ts b/packages/vrender/__tests__/browser/src/pages/text.ts index f5c8a9784..67810c2ba 100644 --- a/packages/vrender/__tests__/browser/src/pages/text.ts +++ b/packages/vrender/__tests__/browser/src/pages/text.ts @@ -127,7 +127,7 @@ export const page = () => { graphics.push(rect); const stage = createStage({ - canvas: 'main', + container: 'container', autoRender: true });