From 7dd06cdf1b71560de83ec789bc224afc70679866 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Fri, 2 Feb 2024 16:38:52 +0800 Subject: [PATCH 1/7] Revert "Merge pull request #954 from VisActor/feat/render-keepMatrix" This reverts commit 5898de2705d55b1d8ba482af81671b7ad167637f, reversing changes made to b4f555e70362548a0dfa3de90431c0c09eb99edc. --- packages/vrender-core/src/core/stage.ts | 4 ++-- packages/vrender-core/src/interface/picker.ts | 2 -- packages/vrender-core/src/interface/render.ts | 2 -- packages/vrender-core/src/interface/stage.ts | 4 ---- .../vrender-core/src/picker/picker-service.ts | 13 +++------- .../contributions/render/draw-contribution.ts | 24 +++++++------------ .../render/incremental-draw-contribution.ts | 17 ++++--------- .../__tests__/browser/src/pages/stage.ts | 11 ++++----- 8 files changed, 22 insertions(+), 55 deletions(-) diff --git a/packages/vrender-core/src/core/stage.ts b/packages/vrender-core/src/core/stage.ts index 429fbd6a0..922387196 100644 --- a/packages/vrender-core/src/core/stage.ts +++ b/packages/vrender-core/src/core/stage.ts @@ -642,7 +642,7 @@ export class Stage extends Group implements IStage { if (!this._skipRender) { this.lastRenderparams = params; this.hooks.beforeRender.call(this); - this.renderLayerList(this.children as ILayer[], params); + this.renderLayerList(this.children as ILayer[]); this.combineLayersToWindow(); this.nextFrameRenderLayerSet.clear(); this.hooks.afterRender.call(this); @@ -729,7 +729,7 @@ export class Stage extends Group implements IStage { background: layer === this.defaultLayer ? this.background : undefined, updateBounds: !!(this.dirtyBounds && !this.dirtyBounds.empty()) }, - { renderStyle: this.renderStyle, keepMatrix: this.params.renderKeepMatrix, ...params } + { renderStyle: this.renderStyle, ...params } ); }); diff --git a/packages/vrender-core/src/interface/picker.ts b/packages/vrender-core/src/interface/picker.ts index 019a53aeb..d229e28a3 100644 --- a/packages/vrender-core/src/interface/picker.ts +++ b/packages/vrender-core/src/interface/picker.ts @@ -24,8 +24,6 @@ export interface IPickParams { group?: boolean; graphic?: boolean; bounds?: IBounds; - // 是否使用当前的Matrix,不用重新初始化matrix - keepMatrix?: boolean; pickContext?: IContext2d; pickerService?: IPickerService; // 内部设置 diff --git a/packages/vrender-core/src/interface/render.ts b/packages/vrender-core/src/interface/render.ts index 663d8788b..a2fef5f4f 100644 --- a/packages/vrender-core/src/interface/render.ts +++ b/packages/vrender-core/src/interface/render.ts @@ -21,8 +21,6 @@ export interface IRenderServiceDrawParams { height: number; x: number; y: number; - // 是否使用当前的Matrix,不用重新初始化matrix - keepMatrix?: boolean; stage: IStage; layer: ILayer; renderService: IRenderService; diff --git a/packages/vrender-core/src/interface/stage.ts b/packages/vrender-core/src/interface/stage.ts index ea7f574b3..34de7a441 100644 --- a/packages/vrender-core/src/interface/stage.ts +++ b/packages/vrender-core/src/interface/stage.ts @@ -76,10 +76,6 @@ export interface IStageParams { * 是否支持pointer事件,不支持就监听mouse事件 */ supportsPointerEvents?: boolean; - /** - * Render的时候使用原来的矩阵,不清除 - */ - renderKeepMatrix?: boolean; } export type EventConfig = { diff --git a/packages/vrender-core/src/picker/picker-service.ts b/packages/vrender-core/src/picker/picker-service.ts index 08ecd45e5..5a07b5b5b 100644 --- a/packages/vrender-core/src/picker/picker-service.ts +++ b/packages/vrender-core/src/picker/picker-service.ts @@ -65,17 +65,10 @@ export abstract class DefaultPickService implements IPickerService { offsetY = params.bounds.y1; } if (this.pickContext) { - if (params.keepMatrix) { - if (this.pickContext.nativeContext && this.pickContext.nativeContext.getTransform) { - const t = this.pickContext.nativeContext.getTransform(); - this.pickContext.setTransformFromMatrix(t, true, 1); - } - } else { - this.pickContext.inuse = true; - this.pickContext.clearMatrix(true, 1); - } + this.pickContext.inuse = true; } params.pickContext = this.pickContext; + this.pickContext && this.pickContext.clearMatrix(true, 1); const parentMatrix = new Matrix(1, 0, 0, 1, offsetX, offsetY); let group: IGroup; @@ -95,7 +88,7 @@ export abstract class DefaultPickService implements IPickerService { if (!result.graphic) { result.group = group; } - if (this.pickContext && !params.keepMatrix) { + if (this.pickContext) { this.pickContext.inuse = false; } 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 8fc7983b0..8a9aaec67 100644 --- a/packages/vrender-core/src/render/contributions/render/draw-contribution.ts +++ b/packages/vrender-core/src/render/contributions/render/draw-contribution.ts @@ -106,19 +106,9 @@ export class DefaultDrawContribution implements IDrawContribution { if (!context) { return; } - // 设置context的transform - if (drawContext.keepMatrix) { - if (context.nativeContext && context.nativeContext.getTransform) { - const t = context.nativeContext.getTransform(); - context.setTransformFromMatrix(t, true, 1); - } - } else { - context.inuse = true; - // 初始化context - context.clearMatrix(); - context.setTransformForCurrent(true); - } - + // if (context.drawPromise) { + // return; + // } const dirtyBounds: IBounds | undefined = this.dirtyBounds.setValue(0, 0, width, height); if (stage.dirtyBounds && !stage.dirtyBounds.empty()) { const b = getRectIntersect(dirtyBounds, stage.dirtyBounds, false); @@ -136,6 +126,10 @@ export class DefaultDrawContribution implements IDrawContribution { dirtyBounds.y2 = Math.ceil(dirtyBounds.y2 * context.dpr) / context.dpr; } this.backupDirtyBounds.copy(dirtyBounds); + context.inuse = true; + // 初始化context + context.clearMatrix(); + context.setTransformForCurrent(true); const drawInArea = dirtyBounds.width() * context.dpr < context.canvas.width || @@ -179,9 +173,7 @@ export class DefaultDrawContribution implements IDrawContribution { context.restore(); context.draw(); // this.break = false; - if (!drawContext.keepMatrix) { - context.inuse = false; - } + context.inuse = false; } doRegister() { 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 2c7b926ef..3469916fe 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 @@ -100,16 +100,9 @@ export class DefaultIncrementalDrawContribution extends DefaultDrawContribution // dirtyBounds.x2 = Math.ceil(b.x2); // dirtyBounds.y2 = Math.ceil(b.y2); // } - if (drawContext.keepMatrix) { - if (context.nativeContext && context.nativeContext.getTransform) { - const t = context.nativeContext.getTransform(); - context.setTransformFromMatrix(t, true, 1); - } - } else { - context.inuse = true; - // 初始化context - context.clearMatrix(); - } + context.inuse = true; + // 初始化context + context.clearMatrix(); context.setTransformForCurrent(true); // const drawInArea = @@ -143,9 +136,7 @@ export class DefaultIncrementalDrawContribution extends DefaultDrawContribution context.restore(); context.restore(); context.draw(); - if (!drawContext.keepMatrix) { - context.inuse = false; - } + context.inuse = false; this.rendering = false; }); } diff --git a/packages/vrender/__tests__/browser/src/pages/stage.ts b/packages/vrender/__tests__/browser/src/pages/stage.ts index 49ef1f7a4..16eec59cf 100644 --- a/packages/vrender/__tests__/browser/src/pages/stage.ts +++ b/packages/vrender/__tests__/browser/src/pages/stage.ts @@ -214,14 +214,15 @@ export const page = () => { const canvas = document.createElement('canvas'); canvas.width = 1200; canvas.height = 600; - canvas.getContext('2d')!.setTransform(1, 0, 0, 1, 100, 100); document.getElementById('container')?.appendChild(canvas); const stage1 = createStage({ canvas, width: 1200, height: 600, - autoRender: false, + viewWidth: 1200, + viewHeight: 600, + autoRender: true, canvasControled: false }); const stage2 = createStage({ @@ -242,7 +243,7 @@ export const page = () => { }); stage1.defaultLayer.add(group as any); shapes.forEach(item => { - item.addEventListener('mouseenter', () => { + item.addEventListener('click', () => { console.log(item.globalAABBBounds); }); group.add(item as any); @@ -252,9 +253,7 @@ export const page = () => { stage2.defaultLayer.add(item as any); }); - stage1.render(null, { - keepMatrix: true - }); + stage1.render(); stage2.render(); // setTimeout(() => { From 207af3b67efbe5c8b18f8792f208332382c2596e Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Fri, 2 Feb 2024 18:21:33 +0800 Subject: [PATCH 2/7] feat: complete part of window-event refactor --- .../vrender-core/src/canvas/empty-context.ts | 49 ++++++---- .../layerHandler/canvas2d-contribution.ts | 4 + .../layerHandler/empty-contribution.ts | 2 + .../layerHandler/offscreen2d-contribution.ts | 4 +- .../contributions/window/base-contribution.ts | 21 +++- packages/vrender-core/src/core/layer.ts | 14 +-- packages/vrender-core/src/core/stage.ts | 79 +++++++-------- packages/vrender-core/src/core/window.ts | 50 +++++++++- .../vrender-core/src/event/event-manager.ts | 2 +- .../vrender-core/src/event/event-system.ts | 42 +++++--- .../vrender-core/src/interface/context.ts | 1 + packages/vrender-core/src/interface/event.ts | 13 +-- packages/vrender-core/src/interface/layer.ts | 4 - packages/vrender-core/src/interface/render.ts | 8 +- packages/vrender-core/src/interface/window.ts | 17 +++- .../vrender-core/src/picker/picker-service.ts | 19 ++-- .../incremental-auto-render-plugin.ts | 6 +- .../contributions/render/draw-contribution.ts | 35 +++---- .../render/incremental-draw-contribution.ts | 4 +- .../canvas/contributions/browser/context.ts | 11 ++- .../contributions/browser-contribution.ts | 12 ++- .../contributions/feishu-contribution.ts | 3 +- .../window/contributions/lynx-contribution.ts | 3 +- .../window/contributions/node-contribution.ts | 2 +- .../window/contributions/taro-contribution.ts | 3 +- .../window/contributions/wx-contribution.ts | 3 +- .../__tests__/browser/src/pages/clip.ts | 3 +- .../__tests__/browser/src/pages/index.ts | 4 + .../browser/src/pages/window-event.ts | 95 +++++++++++++++++++ 29 files changed, 345 insertions(+), 168 deletions(-) create mode 100644 packages/vrender/__tests__/browser/src/pages/window-event.ts diff --git a/packages/vrender-core/src/canvas/empty-context.ts b/packages/vrender-core/src/canvas/empty-context.ts index f8b1fea2d..c64eee7bd 100644 --- a/packages/vrender-core/src/canvas/empty-context.ts +++ b/packages/vrender-core/src/canvas/empty-context.ts @@ -1,3 +1,4 @@ +import type { IMatrix } from '@visactor/vutils'; import { Matrix } from '@visactor/vutils'; import { injectable } from '../common/inversify-lite'; import type { @@ -46,31 +47,32 @@ const globalPoint = { x: 0, y: 0 }; @injectable() export class EmptyContext2d implements IContext2d { - path: CustomPath2D; - canvas: null; - stack: Matrix[]; - protected matrix: Matrix; - protected applyedMatrix?: Matrix; // 被应用的matrix + declare path: CustomPath2D; + declare canvas: null; + declare stack: Matrix[]; + protected declare matrix: Matrix; + protected declare applyedMatrix?: Matrix; // 被应用的matrix // 属性代理 - fillStyle: string | CanvasGradient | CanvasPattern; + declare fillStyle: string | CanvasGradient | CanvasPattern; /** * @deprecated font方法不建议使用,请使用setTextStyle */ - font: string; - globalAlpha: number; - lineCap: string; - lineDashOffset: number; - lineJoin: string; - lineWidth: number; - miterLimit: number; - shadowBlur: number; - shadowColor: string; - shadowOffsetX: number; - shadowOffsetY: number; - strokeStyle: string | CanvasGradient | CanvasPattern; - textAlign: string; - textBaseline: string; - dpr: number; + declare font: string; + declare globalAlpha: number; + declare lineCap: string; + declare lineDashOffset: number; + declare lineJoin: string; + declare lineWidth: number; + declare miterLimit: number; + declare shadowBlur: number; + declare shadowColor: string; + declare shadowOffsetX: number; + declare shadowOffsetY: number; + declare strokeStyle: string | CanvasGradient | CanvasPattern; + declare textAlign: string; + declare textBaseline: string; + declare dpr: number; + declare _clearMatrix: IMatrix; get nativeContext(): any { return this.path; @@ -82,6 +84,7 @@ export class EmptyContext2d implements IContext2d { this.dpr = dpr; this.applyedMatrix = new Matrix(1, 0, 0, 1, 0, 0); this.path = new CustomPath2D(); + this._clearMatrix = new Matrix(1, 0, 0, 1, 0, 0); } getCanvas(): ICanvas { @@ -542,6 +545,10 @@ export class EmptyContext2d implements IContext2d { this.setTransformFromMatrix(initMatrix, setTransform, dpr); } + setClearMatrix(a: number, b: number, c: number, d: number, e: number, f: number) { + this._clearMatrix.setValue(a, b, c, d, e, f); + } + onlyTranslate(dpr: number = this.dpr): boolean { return this.matrix.a === dpr && this.matrix.b === 0 && this.matrix.c === 0 && this.matrix.d === dpr; } 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 8fc8a6fc5..62d5c77ba 100644 --- a/packages/vrender-core/src/core/contributions/layerHandler/canvas2d-contribution.ts +++ b/packages/vrender-core/src/core/contributions/layerHandler/canvas2d-contribution.ts @@ -105,6 +105,8 @@ export class CanvasLayerHandlerContribution implements ILayerHandlerContribution params.renderService.render(group, { context: this.context, clear: params.background ?? '#ffffff', + viewBox: params.stage.window.getViewBox(), + transMatrix: params.stage.window.getViewBoxTransform(), ...params, ...userParams }); @@ -126,6 +128,8 @@ export class CanvasLayerHandlerContribution implements ILayerHandlerContribution const context = target.getContext(); params.renderService.render(group, { context, + viewBox: params.stage.window.getViewBox(), + transMatrix: params.stage.window.getViewBoxTransform(), ...params, clear: params.clear ? params.background ?? '#fff' : undefined }); 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 ad1f55fc2..3b3e6fcd3 100644 --- a/packages/vrender-core/src/core/contributions/layerHandler/empty-contribution.ts +++ b/packages/vrender-core/src/core/contributions/layerHandler/empty-contribution.ts @@ -72,6 +72,8 @@ export class EmptyLayerHandlerContribution implements ILayerHandlerContribution const context = target.getContext(); params.renderService.render(group, { context, + viewBox: params.stage.window.getViewBox(), + transMatrix: params.stage.window.getViewBoxTransform(), ...params, clear: params.clear ? params.background ?? '#fff' : undefined }); 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 16bf1ebce..464c811dd 100644 --- a/packages/vrender-core/src/core/contributions/layerHandler/offscreen2d-contribution.ts +++ b/packages/vrender-core/src/core/contributions/layerHandler/offscreen2d-contribution.ts @@ -69,9 +69,9 @@ export class OffscreenLayerHandlerContribution implements ILayerHandlerContribut render(group: IGroup[], params: ILayerHandlerDrawParams): void { params.renderService.render(group, { context: this.context, + viewBox: params.stage.window.getViewBox(), + transMatrix: params.stage.window.getViewBoxTransform(), ...params, - x: 0, - y: 0, clear: params.background ?? '#ffffff' }); } diff --git a/packages/vrender-core/src/core/contributions/window/base-contribution.ts b/packages/vrender-core/src/core/contributions/window/base-contribution.ts index b067d76ca..c3e3846d7 100644 --- a/packages/vrender-core/src/core/contributions/window/base-contribution.ts +++ b/packages/vrender-core/src/core/contributions/window/base-contribution.ts @@ -10,7 +10,7 @@ import type { IWindow, IWindowParams } from '../../../interface'; -import type { IBoundsLike } from '@visactor/vutils'; +import { AABBBounds, Matrix, type IBounds, type IBoundsLike, type IMatrix } from '@visactor/vutils'; type OnchangeCbType = (params?: { x?: number; y?: number; width?: number; height?: number }) => void; @@ -19,9 +19,13 @@ export abstract class BaseWindowHandlerContribution implements IWindowHandlerCon declare type: EnvType; declare _uid: number; + protected viewBox: IBounds; + protected modelMatrix: IMatrix; constructor() { this._uid = Generator.GenAutoIncrementId(); + this.viewBox = new AABBBounds(); + this.modelMatrix = new Matrix(1, 0, 0, 1, 0, 0); } protected declare _onChangeCb?: OnchangeCbType; @@ -48,7 +52,7 @@ export abstract class BaseWindowHandlerContribution implements IWindowHandlerCon abstract getXY(): { x: number; y: number }; abstract getNativeHandler(): ICanvas | any; abstract getDpr(): number; - abstract clearViewBox(vb: IBoundsLike, color?: string): void; + abstract clearViewBox(color?: string): void; abstract addEventListener( type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, @@ -89,4 +93,17 @@ export abstract class BaseWindowHandlerContribution implements IWindowHandlerCon left: 0 }; } + + setViewBox(vb: IBoundsLike) { + this.viewBox.setValue(vb.x1, vb.y1, vb.x2, vb.y2); + } + getViewBox() { + return this.viewBox; + } + setViewBoxTransform(a: number, b: number, c: number, d: number, e: number, f: number) { + this.modelMatrix.setValue(a, b, c, d, e, f); + } + getViewBoxTransform(): IMatrix { + return this.modelMatrix; + } } diff --git a/packages/vrender-core/src/core/layer.ts b/packages/vrender-core/src/core/layer.ts index dde93ff9c..d1c3989f2 100644 --- a/packages/vrender-core/src/core/layer.ts +++ b/packages/vrender-core/src/core/layer.ts @@ -167,15 +167,10 @@ export class Layer extends Group implements ILayer { } // 绘制图层 render(params: ILayerDrawParams, userParams?: Partial) { - const stage = this.stage; this.layerHandler.render( [this], { renderService: params.renderService, - x: stage.x, - y: stage.y, - width: this.viewWidth, - height: this.viewHeight, stage: this.stage, layer: this, // TODO: 多图层时不应该再用默认background @@ -220,10 +215,6 @@ export class Layer extends Group implements ILayer { // TODO: 多图层时不应该再用默认background background: params.background ?? this.background, renderService: params.renderService, - x: params.x ?? this.stage.x, - y: params.y ?? this.stage.y, - width: this.viewWidth, - height: this.viewHeight, stage: this.stage, layer: this, ...params @@ -248,10 +239,7 @@ export class Layer extends Group implements ILayer { // TODO: 多图层时不应该再用默认background background: params.background ?? this.background, renderService: params.renderService, - x: params.x ?? this.stage.x, - y: params.y ?? this.stage.y, - width: this.viewWidth, - height: this.viewHeight, + stage: this.stage, layer: this, ...params diff --git a/packages/vrender-core/src/core/stage.ts b/packages/vrender-core/src/core/stage.ts index 922387196..a3dd3b023 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 type { IAABBBounds, IBounds, IBoundsLike, IMatrix, AABBBounds } from '@visactor/vutils'; +import { Bounds, Point, isString } from '@visactor/vutils'; import type { IGraphic, IExportType, @@ -75,9 +75,7 @@ export class Stage extends Group implements IStage { declare state: IStageState; - protected _viewBox: AABBBounds; private _background: string | IColor; - private _subView: boolean; // 是否是存在子视图 protected nextFrameRenderLayerSet: Set; protected willNextFrameRender: boolean; protected _cursor: string; @@ -94,23 +92,39 @@ export class Stage extends Group implements IStage { }; set viewBox(b: IBoundsLike) { - this._viewBox.setValue(b.x1, b.y1, b.x2, b.y2); + this.window.setViewBox(b); } - get viewBox(): AABBBounds { - return this._viewBox; + get viewBox(): IAABBBounds { + return this.window.getViewBox(); } + /** + * @deprecated 不建议使用 + */ get x(): number { - return this._viewBox.x1; + return this.window.getViewBox().x1; } + /** + * @deprecated 不建议使用 + */ set x(x: number) { - this._viewBox.translate(x - this._viewBox.x1, 0); + const b = this.window.getViewBox(); + b.translate(x - b.x1, 0); + this.window.setViewBox(b); } + /** + * @deprecated 不建议使用 + */ get y(): number { - return this._viewBox.y1; + return this.window.getViewBox().y1; } + /** + * @deprecated 不建议使用 + */ set y(y: number) { - this._viewBox.translate(0, y - this._viewBox.y1); + const b = this.window.getViewBox(); + b.translate(0, y - b.y1); + this.window.setViewBox(b); } get width(): number { return this.window.width; @@ -119,13 +133,13 @@ export class Stage extends Group implements IStage { this.resize(w, this.height); } get viewWidth(): number { - return this._viewBox.width(); + return this.window.getViewBox().width(); } set viewWidth(w: number) { this.resizeView(w, this.viewHeight); } get viewHeight(): number { - return this._viewBox.height(); + return this.window.getViewBox().height(); } set viewHeight(h: number) { this.resizeView(this.viewWidth, h); @@ -212,6 +226,7 @@ export class Stage extends Group implements IStage { this.window.create({ width: params.width, height: params.height, + viewBox: params.viewBox, container: params.container, dpr: params.dpr || this.global.devicePixelRatio, canvasControled: params.canvasControled !== false, @@ -219,13 +234,6 @@ export class Stage extends Group implements IStage { canvas: params.canvas }); - this._viewBox = new AABBBounds(); - if (params.viewBox) { - this._viewBox.setValue(params.viewBox.x1, params.viewBox.y1, params.viewBox.x2, params.viewBox.y2); - } else { - this._viewBox.setValue(0, 0, this.width, this.height); - } - this.state = 'normal'; this.renderCount = 0; this.tryInitEventSystem(); @@ -235,7 +243,6 @@ export class Stage extends Group implements IStage { // // 没有传入view的宽高则默认为window的宽高 // this._viewWidth = params.viewWidth ?? this.window.width; // this._viewHeight = params.viewHeight ?? this.window.height; - this._subView = !(this._viewBox.width() === this.width && this._viewBox.height() === this.height); // this._AABBBounds.set(this._x, this._y, this._viewWidth + this._x, this._viewHeight + this._y); // 背景色默认为纯白色 this._background = params.background ?? DefaultConfig.BACKGROUND; @@ -291,21 +298,6 @@ export class Stage extends Group implements IStage { global: this.global, supportsPointerEvents: this.params.supportsPointerEvents, supportsTouchEvents: this.params.supportsTouchEvents, - 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.params.event }); } @@ -346,7 +338,8 @@ export class Stage extends Group implements IStage { } if (visible) { if (this.dirtyBounds) { - this.dirtyBounds.setValue(0, 0, this._viewBox.width(), this._viewBox.height()); + const b = this.window.getViewBox(); + this.dirtyBounds.setValue(b.x1, b.y1, b.width(), b.height()); } if (this._skipRender > 1) { this.renderNextFrame(); @@ -578,7 +571,7 @@ export class Stage extends Group implements IStage { // } protected tryUpdateAABBBounds(): AABBBounds { - const viewBox = this._viewBox; + const viewBox = this.window.getViewBox(); this._AABBBounds.setValue(viewBox.x1, viewBox.y1, viewBox.x2, viewBox.y2); return this._AABBBounds; } @@ -630,7 +623,7 @@ export class Stage extends Group implements IStage { } clearViewBox(color?: string) { - this.window.clearViewBox(this._viewBox, color); + this.window.clearViewBox(color); } render(layers?: ILayer[], params?: Partial): void { @@ -757,14 +750,14 @@ export class Stage extends Group implements IStage { * @param rerender */ resize(w: number, h: number, rerender: boolean = true): void { + // 如果不是子图的stage,那么认为用户也想要resize view + if (!this.window.hasSubView()) { + this.viewBox.setValue(this.viewBox.x1, this.viewBox.y1, this.viewBox.x1 + w, this.viewBox.y1 + h); + } this.window.resize(w, h); this.forEachChildren(c => { c.resize(w, h); }); - // 如果不是子图的stage,那么认为用户也想要resize view - if (!this._subView) { - this.viewBox.setValue(this.viewBox.x1, this.viewBox.y1, this.viewBox.x1 + w, this.viewBox.y1 + h); - } // 设置camera // this.camera && (this.camera.params = { ...this.camera.params, right: this.width, bottom: this.height }); this.camera && this.option3d && this.set3dOptions(this.option3d); diff --git a/packages/vrender-core/src/core/window.ts b/packages/vrender-core/src/core/window.ts index 9dc0d41ca..7ff2dfdde 100644 --- a/packages/vrender-core/src/core/window.ts +++ b/packages/vrender-core/src/core/window.ts @@ -1,5 +1,6 @@ import { inject, injectable } from '../common/inversify-lite'; -import type { IBoundsLike } from '@visactor/vutils'; +import type { IPointLike } from '@visactor/vutils'; +import { Matrix, type IBoundsLike, type IMatrix, IBounds, Point } from '@visactor/vutils'; import { Generator } from '../common/generator'; import type { ICanvas, @@ -116,6 +117,18 @@ export class DefaultWindow implements IWindow { const windowWH = this._handler.getWH(); this._width = windowWH.width; this._height = windowWH.height; + + // 设置viewBox + if (params.viewBox) { + this.setViewBox(params.viewBox); + } else { + if (params.canvasControled !== false) { + this.setViewBox({ x1: 0, y1: 0, x2: this._width, y2: this._height }); + } else { + this.setViewBox({ x1: 0, y1: 0, x2: params.width ?? this._width, y2: params.height ?? this._height }); + } + } + // 使用window的xy // const windowXY = this._handler.getXY(); // this.x = windowXY.x; @@ -191,8 +204,39 @@ export class DefaultWindow implements IWindow { return this._handler.container; } - clearViewBox(viewBox: IBoundsLike, color?: string) { - this._handler.clearViewBox(viewBox, color); + clearViewBox(color?: string) { + this._handler.clearViewBox(color); + } + setViewBox(viewBox: IBoundsLike) { + this._handler.setViewBox(viewBox); + } + setViewBoxTransform(a: number, b: number, c: number, d: number, e: number, f: number) { + this._handler.setViewBoxTransform(a, b, c, d, e, f); + } + getViewBox() { + return this._handler.getViewBox(); + } + getViewBoxTransform() { + return this._handler.getViewBoxTransform(); + } + pointTransform(x: number, y: number): IPointLike { + const vb = this._handler.getViewBox(); + const m = this._handler.getViewBoxTransform(); + const nextP = { x, y }; + m.transformPoint({ x, y }, nextP); + nextP.x -= vb.x1; + nextP.y -= vb.y1; + return nextP; + } + + hasSubView() { + const viewBox = this._handler.getViewBox(); + return !( + viewBox.x1 === 0 && + viewBox.y1 === 0 && + this.width === viewBox.width() && + this.height === viewBox.height() + ); } isVisible(bbox?: IBoundsLike): boolean { diff --git a/packages/vrender-core/src/event/event-manager.ts b/packages/vrender-core/src/event/event-manager.ts index 2a8bc002c..c21916909 100644 --- a/packages/vrender-core/src/event/event-manager.ts +++ b/packages/vrender-core/src/event/event-manager.ts @@ -145,7 +145,7 @@ export class EventManager { ) { target = this._prePointTargetCache[cacheKey]; } else { - target = this.pickTarget(e.canvasX, e.canvasY, e); + target = this.pickTarget(e.viewX, e.viewY, e); // 缓存上一个坐标点的拾取结果,减少拾取的次数,如 pointermove pointerdown 和 pointerup 在同一个点触发 // 如果存在params,那么就不缓存 if (!(e as any).pickParams) { diff --git a/packages/vrender-core/src/event/event-system.ts b/packages/vrender-core/src/event/event-system.ts index bbb699462..09b63fcf1 100644 --- a/packages/vrender-core/src/event/event-system.ts +++ b/packages/vrender-core/src/event/event-system.ts @@ -1,5 +1,6 @@ +import type { IPointLike } from '@visactor/vutils'; import { isUndefined, has, isString } from '@visactor/vutils'; -import type { IGlobal } from '../interface'; +import type { IGlobal, IWindow } from '../interface'; import { EventManager } from './event-manager'; import { FederatedPointerEvent, FederatedWheelEvent } from './federated-event'; import type { FederatedMouseEvent } from './federated-event/mouse-event'; @@ -59,8 +60,6 @@ export class EventSystem { readonly applyStyles: boolean; - readonly viewport: RenderConfig['viewport']; - /** * Should default browser actions automatically be prevented. * Does not apply to pointer events for backwards compatibility @@ -82,7 +81,7 @@ export class EventSystem { /** * The DOM element to which the root event listeners are bound. This is automatically set to */ - domElement: IElementLike | null; + domElement: IElementLike | IWindow | null; /** The resolution used to convert between the DOM client space into world space. */ resolution = 1; @@ -94,11 +93,10 @@ export class EventSystem { constructor(params: RenderConfig) { const { - targetElement, + targetElement, // 别名,避免和浏览器window重名 resolution, rootNode, global, - viewport, autoPreventDefault = false, clickInterval, supportsTouchEvents = global.supportsTouchEvents, @@ -116,7 +114,6 @@ export class EventSystem { this.autoPreventDefault = autoPreventDefault; this.eventsAdded = false; - this.viewport = viewport; this.rootPointerEvent = new FederatedPointerEvent(); this.rootWheelEvent = new FederatedWheelEvent(); @@ -211,7 +208,7 @@ export class EventSystem { return; } - const outside = this.isEventOutsideOfTargetElement(nativeEvent) ? 'outside' : ''; + const outside = this.isEventOutsideOfTargetViewPort(nativeEvent) ? 'outside' : ''; const normalizedEvents = this.normalizeToPointerData(nativeEvent); for (let i = 0, j = normalizedEvents.length; i < j; i++) { @@ -338,13 +335,11 @@ export class EventSystem { this.eventsAdded = false; } - private mapToViewportPoint(event: FederatedMouseEvent): EventPoint { - const viewport = this.viewport; - const { x, y } = event; - return { - x: x - viewport.x, - y: y - viewport.y - }; + private mapToViewportPoint(event: IPointLike): EventPoint { + if ((this.domElement as IWindow).pointTransform) { + return (this.domElement as IWindow).pointTransform(event.x, event.y); + } + return event; } private mapToCanvasPoint(nativeEvent: PointerEvent | WheelEvent): EventPoint { @@ -576,6 +571,23 @@ export class EventSystem { event.relatedTarget = null; } + private isEventOutsideOfTargetViewPort(nativeEvent: NativeEvent) { + if (this.isEventOutsideOfTargetElement(nativeEvent)) { + return true; + } + + // 判断点是否在区间内 + if ((this.domElement as IWindow).getViewBox) { + const p = this.mapToViewportPoint(this.mapToCanvasPoint(nativeEvent as any)); + const b = (this.domElement as IWindow).getViewBox(); + const w = b.width(); + const h = b.height(); + const contain = p.x < w && p.y < h && p.x > 0 && p.y > 0; + return !contain; + } + return false; + } + private isEventOutsideOfTargetElement(nativeEvent: NativeEvent) { let target = nativeEvent.target; diff --git a/packages/vrender-core/src/interface/context.ts b/packages/vrender-core/src/interface/context.ts index 0b9cb6a4e..4bb019226 100644 --- a/packages/vrender-core/src/interface/context.ts +++ b/packages/vrender-core/src/interface/context.ts @@ -316,6 +316,7 @@ export interface IContext2d extends Releaseable { draw: (...params: any) => void; clearMatrix: (setTransform?: boolean, dpr?: number) => void; + setClearMatrix: (a: number, b: number, c: number, d: number, e: number, f: number) => void; onlyTranslate: (dpr?: number) => boolean; } diff --git a/packages/vrender-core/src/interface/event.ts b/packages/vrender-core/src/interface/event.ts index 4b78776bd..71ea4f2bc 100644 --- a/packages/vrender-core/src/interface/event.ts +++ b/packages/vrender-core/src/interface/event.ts @@ -4,6 +4,7 @@ import type { Cursor, IGraphicAttribute } from './graphic'; import type { IDomRectLike, IEventElement } from './common'; import type { ICanvas } from './canvas'; import type { IGlobal } from './global'; +import type { IWindow } from './window'; export type EventPoint = { x: number; @@ -221,9 +222,9 @@ export type IElementLike = Omit HTMLElement | any; getImageBuffer: (type?: string) => any; - clearViewBox: (viewBox: IBoundsLike, color?: string) => void; + clearViewBox: (color?: string) => void; + setViewBox: (vb: IBoundsLike) => void; + getViewBox: () => IBounds; + setViewBoxTransform: (a: number, b: number, c: number, d: number, e: number, f: number) => void; + getViewBoxTransform: () => IMatrix; + hasSubView: () => boolean; + pointTransform: (x: number, y: number) => IPointLike; getBoundingClientRect: () => IDomRectLike; @@ -94,7 +101,11 @@ export interface IWindowHandlerContribution setStyle: (s: CSSStyleDeclaration | Record) => void; getBoundingClientRect: () => IDomRectLike; - clearViewBox: (vb: IBoundsLike, color?: string) => void; + clearViewBox: (color?: string) => void; + setViewBox: (vb: IBoundsLike) => void; + getViewBox: () => IBounds; + setViewBoxTransform: (a: number, b: number, c: number, d: number, e: number, f: number) => void; + getViewBoxTransform: () => IMatrix; isVisible: (bbox?: IBoundsLike) => boolean; onVisibleChange: (cb: (currentVisible: boolean) => void) => void; diff --git a/packages/vrender-core/src/picker/picker-service.ts b/packages/vrender-core/src/picker/picker-service.ts index 5a07b5b5b..1f66c7c4e 100644 --- a/packages/vrender-core/src/picker/picker-service.ts +++ b/packages/vrender-core/src/picker/picker-service.ts @@ -1,5 +1,5 @@ import type { IMatrix, IPoint, IPointLike } from '@visactor/vutils'; -import { Matrix, Point } from '@visactor/vutils'; +import { AABBBounds, Matrix, Point } from '@visactor/vutils'; import { inject, injectable, named } from '../common/inversify-lite'; import { foreach } from '../common/sort'; // eslint-disable-next-line @typescript-eslint/consistent-type-imports @@ -32,6 +32,7 @@ export abstract class DefaultPickService implements IPickerService { constructor( // 拦截器 + // @ts-ignore @inject(ContributionProvider) @named(PickItemInterceptor) protected readonly pickItemInterceptorContributions: IContributionProvider @@ -54,15 +55,13 @@ export abstract class DefaultPickService implements IPickerService { graphic: null, group: null }; + // point变换 params.pickerService = this; - let offsetX = 0; - let offsetY = 0; - if (params && params.bounds) { - if (!params.bounds.contains(point.x, point.y)) { - return result; - } - offsetX = params.bounds.x1; - offsetY = params.bounds.y1; + + const w = params.bounds.width(); + const h = params.bounds.height(); + if (!new AABBBounds().setValue(0, 0, w, h).containsPoint(point)) { + return result; } if (this.pickContext) { this.pickContext.inuse = true; @@ -70,7 +69,7 @@ export abstract class DefaultPickService implements IPickerService { params.pickContext = this.pickContext; this.pickContext && this.pickContext.clearMatrix(true, 1); - const parentMatrix = new Matrix(1, 0, 0, 1, offsetX, offsetY); + const parentMatrix = new Matrix(1, 0, 0, 1, 0, 0); let group: IGroup; for (let i = graphics.length - 1; i >= 0; i--) { if (graphics[i].isContainer) { diff --git a/packages/vrender-core/src/plugins/builtin-plugin/incremental-auto-render-plugin.ts b/packages/vrender-core/src/plugins/builtin-plugin/incremental-auto-render-plugin.ts index 1af5a2206..aa0c8af05 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/incremental-auto-render-plugin.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/incremental-auto-render-plugin.ts @@ -66,12 +66,10 @@ export class IncrementalAutoRenderPlugin implements IPlugin { return; } subLayer.drawContribution.draw(stage.renderService, { - x: stage.x, - y: stage.y, - width: layer.viewWidth, - height: layer.viewHeight, stage, layer, + viewBox: stage.window.getViewBox(), + transMatrix: stage.window.getViewBoxTransform(), // TODO: 多图层时不应该再用默认background clear: 'transparent', renderService: stage.renderService, 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 8a9aaec67..365b10573 100644 --- a/packages/vrender-core/src/render/contributions/render/draw-contribution.ts +++ b/packages/vrender-core/src/render/contributions/render/draw-contribution.ts @@ -101,7 +101,7 @@ export class DefaultDrawContribution implements IDrawContribution { // this.startAtId = drawParams.startAtId; this.currentRenderService = renderService; // this.drawParams = drawParams; - const { context, stage, x = 0, y = 0, width, height } = drawContext; + const { context, stage, viewBox, transMatrix } = drawContext; if (!context) { return; @@ -109,7 +109,7 @@ export class DefaultDrawContribution implements IDrawContribution { // if (context.drawPromise) { // return; // } - const dirtyBounds: IBounds | undefined = this.dirtyBounds.setValue(0, 0, width, height); + const dirtyBounds: IBounds | undefined = this.dirtyBounds.setValue(0, 0, viewBox.width(), viewBox.height()); if (stage.dirtyBounds && !stage.dirtyBounds.empty()) { const b = getRectIntersect(dirtyBounds, stage.dirtyBounds, false); dirtyBounds.x1 = Math.floor(b.x1); @@ -127,22 +127,21 @@ export class DefaultDrawContribution implements IDrawContribution { } this.backupDirtyBounds.copy(dirtyBounds); context.inuse = true; + context.setClearMatrix(transMatrix.a, transMatrix.b, transMatrix.c, transMatrix.d, transMatrix.e, transMatrix.f); // 初始化context context.clearMatrix(); context.setTransformForCurrent(true); - const drawInArea = - dirtyBounds.width() * context.dpr < context.canvas.width || - dirtyBounds.height() * context.dpr < context.canvas.height; - context.save(); + // const drawInArea = + // dirtyBounds.width() * context.dpr < context.canvas.width || + // dirtyBounds.height() * context.dpr < context.canvas.height; + // context.save(); // 设置translate - context.translate(x, y, true); - if (drawInArea) { - context.beginPath(); - context.rect(dirtyBounds.x1, dirtyBounds.y1, dirtyBounds.width(), dirtyBounds.height()); - context.clip(); - } + context.translate(viewBox.x1, viewBox.y1, true); + context.beginPath(); + context.rect(dirtyBounds.x1, dirtyBounds.y1, dirtyBounds.width(), dirtyBounds.height()); + context.clip(); // 如果存在3d视角,那么不使用dirtyBounds if (stage.camera) { @@ -172,6 +171,7 @@ export class DefaultDrawContribution implements IDrawContribution { context.restore(); context.restore(); context.draw(); + context.setClearMatrix(1, 0, 0, 1, 0, 0); // this.break = false; context.inuse = false; } @@ -406,12 +406,13 @@ export class DefaultDrawContribution implements IDrawContribution { } protected clearScreen(renderService: IRenderService, context: IContext2d, drawContext: IDrawContext) { - const { clear } = drawContext; + const { clear, viewBox } = drawContext; + // 已经translate过了 + const x = 0; + const y = 0; + const width = viewBox.width(); + const height = viewBox.height(); if (clear) { - const canvas = context.getCanvas(); - const { width = canvas.width, height = canvas.height } = drawContext; - const x = 0; - const y = 0; context.clearRect(x, y, width, height); const stage = renderService.drawParams?.stage; stage && (context.globalAlpha = (stage as any).attribute.opacity ?? 1); 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 3469916fe..0355e9b5d 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 @@ -86,7 +86,7 @@ export class DefaultIncrementalDrawContribution extends DefaultDrawContribution } this.currentRenderService = renderService; - const { context, x = 0, y = 0 } = drawContext; + const { context, viewBox } = drawContext; if (!context) { return; @@ -121,7 +121,7 @@ export class DefaultIncrementalDrawContribution extends DefaultDrawContribution // 绘制之前需要清空画布 drawContext.restartIncremental && this.clearScreen(this.currentRenderService, context, drawContext); // 设置translate - context.translate(x, y, true); + context.translate(viewBox.x1, viewBox.y1, true); context.save(); renderService.renderTreeRoots diff --git a/packages/vrender-kits/src/canvas/contributions/browser/context.ts b/packages/vrender-kits/src/canvas/contributions/browser/context.ts index 4b7bddaf7..d2c06b3a8 100644 --- a/packages/vrender-kits/src/canvas/contributions/browser/context.ts +++ b/packages/vrender-kits/src/canvas/contributions/browser/context.ts @@ -23,7 +23,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import type { IPointLike, TextMeasure, ITextMeasureSpec } from '@visactor/vutils'; +import type { IPointLike, TextMeasure, ITextMeasureSpec, IMatrix } from '@visactor/vutils'; import { Matrix, pi, pi2, Logger } from '@visactor/vutils'; import { injectable, @@ -56,7 +56,6 @@ import type { const outP: [number, number, number] = [0, 0, 0]; // https://github.com/konvajs/konva/blob/master/src/Context.ts -const initMatrix = new Matrix(1, 0, 0, 1, 0, 0); const addArcToBezierPath = ( bezierPath: Array, @@ -125,6 +124,7 @@ export class BrowserContext2d implements IContext2d { protected applyedMatrix?: Matrix; // 被应用的matrix declare fontFamily: string; declare fontSize: number; + declare _clearMatrix: IMatrix; // 属性代理 set fillStyle(d: string | CanvasGradient | CanvasPattern) { this.nativeContext.fillStyle = d; @@ -247,6 +247,7 @@ export class BrowserContext2d implements IContext2d { this.stack = []; this.dpr = dpr; this.applyedMatrix = new Matrix(1, 0, 0, 1, 0, 0); + this._clearMatrix = new Matrix(1, 0, 0, 1, 0, 0); } reset() { @@ -1182,7 +1183,11 @@ export class BrowserContext2d implements IContext2d { } clearMatrix(setTransform: boolean = true, dpr: number = this.dpr) { - this.setTransformFromMatrix(initMatrix, setTransform, dpr); + this.setTransformFromMatrix(this._clearMatrix, setTransform, dpr); + } + + setClearMatrix(a: number, b: number, c: number, d: number, e: number, f: number) { + this._clearMatrix.setValue(a, b, c, d, e, f); } onlyTranslate(dpr: number = this.dpr): boolean { diff --git a/packages/vrender-kits/src/window/contributions/browser-contribution.ts b/packages/vrender-kits/src/window/contributions/browser-contribution.ts index e66fc18bb..7ba4902cb 100644 --- a/packages/vrender-kits/src/window/contributions/browser-contribution.ts +++ b/packages/vrender-kits/src/window/contributions/browser-contribution.ts @@ -16,7 +16,8 @@ import type { IWindowHandlerContribution, IWindowParams } from '@visactor/vrender-core'; -import type { IBoundsLike } from '@visactor/vutils'; +import type { IBoundsLike, IMatrix, IBounds } from '@visactor/vutils'; +import { Matrix, AABBBounds } from '@visactor/vutils'; import { BrowserCanvas } from '../../canvas/contributions/browser'; @injectable() @@ -28,9 +29,9 @@ export class BrowserWindowHandlerContribution type: EnvType = 'browser'; - canvas: ICanvas; + declare canvas: ICanvas; - observer?: MutationObserver; + declare observer?: MutationObserver; protected _canvasIsIntersecting: boolean; protected _onVisibleChangeCb: (currentVisible: boolean) => void; @@ -52,6 +53,8 @@ export class BrowserWindowHandlerContribution super(); this._canvasIsIntersecting = true; this.global = application.global; + this.viewBox = new AABBBounds(); + this.modelMatrix = new Matrix(1, 0, 0, 1, 0, 0); } getTitle(): string { @@ -298,7 +301,8 @@ export class BrowserWindowHandlerContribution return this.canvas.nativeCanvas.getBoundingClientRect(); } - clearViewBox(vb: IBoundsLike, color?: string): void { + clearViewBox(color?: string): void { + const vb = this.viewBox; const context = this.getContext(); const dpr = this.getDpr(); context.nativeContext.save(); diff --git a/packages/vrender-kits/src/window/contributions/feishu-contribution.ts b/packages/vrender-kits/src/window/contributions/feishu-contribution.ts index c0ae2e949..beaa50ce0 100644 --- a/packages/vrender-kits/src/window/contributions/feishu-contribution.ts +++ b/packages/vrender-kits/src/window/contributions/feishu-contribution.ts @@ -226,7 +226,8 @@ export class FeishuWindowHandlerContribution }; } - clearViewBox(vb: IBoundsLike, color?: string): void { + clearViewBox(color?: string): void { + const vb = this.viewBox; const context = this.getContext(); const dpr = this.getDpr(); context.nativeContext.save(); diff --git a/packages/vrender-kits/src/window/contributions/lynx-contribution.ts b/packages/vrender-kits/src/window/contributions/lynx-contribution.ts index ee48b1817..41a4317c8 100644 --- a/packages/vrender-kits/src/window/contributions/lynx-contribution.ts +++ b/packages/vrender-kits/src/window/contributions/lynx-contribution.ts @@ -223,7 +223,8 @@ export class LynxWindowHandlerContribution extends BaseWindowHandlerContribution }; } - clearViewBox(vb: IBoundsLike, color?: string): void { + clearViewBox(color?: string): void { + const vb = this.viewBox; const context = this.getContext(); const dpr = this.getDpr(); context.nativeContext.save(); diff --git a/packages/vrender-kits/src/window/contributions/node-contribution.ts b/packages/vrender-kits/src/window/contributions/node-contribution.ts index 169256839..d548e22a4 100644 --- a/packages/vrender-kits/src/window/contributions/node-contribution.ts +++ b/packages/vrender-kits/src/window/contributions/node-contribution.ts @@ -159,7 +159,7 @@ export class NodeWindowHandlerContribution extends BaseWindowHandlerContribution return null; } - clearViewBox(vb: IBoundsLike, color?: string): void { + clearViewBox(color?: string): void { return; } } diff --git a/packages/vrender-kits/src/window/contributions/taro-contribution.ts b/packages/vrender-kits/src/window/contributions/taro-contribution.ts index 05dcde8de..cea900f37 100644 --- a/packages/vrender-kits/src/window/contributions/taro-contribution.ts +++ b/packages/vrender-kits/src/window/contributions/taro-contribution.ts @@ -240,7 +240,8 @@ export class TaroWindowHandlerContribution extends BaseWindowHandlerContribution }; } - clearViewBox(vb: IBoundsLike, color?: string): void { + clearViewBox(color?: string): void { + const vb = this.viewBox; const context = this.getContext(); const dpr = this.getDpr(); context.nativeContext.save(); diff --git a/packages/vrender-kits/src/window/contributions/wx-contribution.ts b/packages/vrender-kits/src/window/contributions/wx-contribution.ts index 92600f227..2b573c0cd 100644 --- a/packages/vrender-kits/src/window/contributions/wx-contribution.ts +++ b/packages/vrender-kits/src/window/contributions/wx-contribution.ts @@ -223,7 +223,8 @@ export class WxWindowHandlerContribution extends BaseWindowHandlerContribution i }; } - clearViewBox(vb: IBoundsLike, color?: string): void { + clearViewBox(color?: string): void { + const vb = this.viewBox; const context = this.getContext(); const dpr = this.getDpr(); context.nativeContext.save(); diff --git a/packages/vrender/__tests__/browser/src/pages/clip.ts b/packages/vrender/__tests__/browser/src/pages/clip.ts index 153d9bde5..89aa26387 100644 --- a/packages/vrender/__tests__/browser/src/pages/clip.ts +++ b/packages/vrender/__tests__/browser/src/pages/clip.ts @@ -65,7 +65,8 @@ export const page = () => { const stage = createStage({ canvas: 'main', width: 1200, - height: 600 + height: 600, + autoRender: true // ticker: new ManualTicker([defaultTimeline]) }); diff --git a/packages/vrender/__tests__/browser/src/pages/index.ts b/packages/vrender/__tests__/browser/src/pages/index.ts index 327c301df..2b89a0a98 100644 --- a/packages/vrender/__tests__/browser/src/pages/index.ts +++ b/packages/vrender/__tests__/browser/src/pages/index.ts @@ -87,6 +87,10 @@ export const pages = [ name: '动画', path: 'animate' }, + { + name: 'window-event', + path: 'window-event' + }, { name: 'state测试', path: 'state' diff --git a/packages/vrender/__tests__/browser/src/pages/window-event.ts b/packages/vrender/__tests__/browser/src/pages/window-event.ts new file mode 100644 index 000000000..3324b8fcd --- /dev/null +++ b/packages/vrender/__tests__/browser/src/pages/window-event.ts @@ -0,0 +1,95 @@ +import { createStage, createCircle, IGraphic, vglobal, createSymbol } from '@visactor/vrender'; +import { colorPools } from '../utils'; +import { createGroup } from '@visactor/vrender'; +import { Matrix } from '@visactor/vutils'; + +export const page = () => { + function addSymbol(num: number, type: string, stage: any) { + for (let i = 0; i < num; i++) { + const symbol = createSymbol({ + x: Math.random() * 200, + y: Math.random() * 200, + size: 16, + fill: `rgb(${Math.floor(Math.random() * 255)},${Math.floor(Math.random() * 255)},${Math.floor( + Math.random() * 255 + )})`, + symbolType: type + }); + stage.defaultLayer.add(symbol); + symbol.addEventListener('mouseenter', () => { + symbol.setAttribute('fill', 'red'); + }); + symbol.addEventListener('mouseleave', () => { + symbol.setAttribute( + 'fill', + `rgb(${Math.floor(Math.random() * 255)},${Math.floor(Math.random() * 255)},${Math.floor( + Math.random() * 255 + )})` + ); + }); + } + } + + const stage1 = createStage({ + canvas: 'main', + viewBox: { + x1: 100, + y1: 100, + x2: 200, + y2: 200 + }, + background: 'rgba(255, 128, 36, 0.2)', + autoRender: true + }); + + addSymbol(100, 'circle', stage1); + + const stage2 = createStage({ + canvas: 'main', + width: 100, + height: 100, + canvasControled: false, + background: 'rgba(36, 128, 36, 0.2)', + autoRender: true + }); + + addSymbol(100, 'star', stage2); + + const stage3 = createStage({ + canvas: 'main', + width: 100, + height: 100, + canvasControled: false, + background: 'rgba(36, 128, 36, 0.2)', + autoRender: true + }); + + const matrix = new Matrix(); + matrix.translate(200, 200); + matrix.rotate(Math.PI / 3); + + stage3.window.setViewBoxTransform(matrix.a, matrix.b, matrix.c, matrix.d, matrix.e, matrix.f); + + stage3.addEventListener('mouseenter', () => { + console.log('abcdefg'); + }); + + addSymbol(100, 'square', stage3); + + const stage = createStage({ + width: 100, + height: 300 + }); + stage.resize(200, 200); + console.log(); + // expect(stage.width).toEqual(300); + // expect(stage.height).toEqual(300); + // expect(stage.viewWidth).toEqual(60); + // expect(stage.viewHeight).toEqual(60); + // stage.resizeView(200, 200); + console.log(stage.viewWidth); + // expect(stage.width).toEqual(300); + // expect(stage.height).toEqual(300); + // expect(stage.viewWidth).toEqual(200); + // expect(stage.viewHeight).toEqual(200); +}; From 67ba727737f5d8a22bec568d69ffc66efd81b66c Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Mon, 5 Feb 2024 17:08:37 +0800 Subject: [PATCH 3/7] fix: fix issue with toCanvas --- .../layerHandler/canvas2d-contribution.ts | 4 -- .../layerHandler/empty-contribution.ts | 2 - .../layerHandler/offscreen2d-contribution.ts | 6 ++- .../vrender-core/src/core/graphic-utils.ts | 12 +++--- packages/vrender-core/src/core/layer.ts | 33 +++++++++-------- packages/vrender-core/src/core/stage.ts | 37 +++++++++++-------- packages/vrender-core/src/interface/layer.ts | 12 +++--- packages/vrender-core/src/interface/render.ts | 2 +- .../__tests__/browser/src/pages/chart.ts | 2 +- .../__tests__/browser/src/pages/symbol.ts | 2 +- .../vrender/__tests__/browser/vite.config.ts | 19 +++++++++- 11 files changed, 77 insertions(+), 54 deletions(-) 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 62d5c77ba..8fc8a6fc5 100644 --- a/packages/vrender-core/src/core/contributions/layerHandler/canvas2d-contribution.ts +++ b/packages/vrender-core/src/core/contributions/layerHandler/canvas2d-contribution.ts @@ -105,8 +105,6 @@ export class CanvasLayerHandlerContribution implements ILayerHandlerContribution params.renderService.render(group, { context: this.context, clear: params.background ?? '#ffffff', - viewBox: params.stage.window.getViewBox(), - transMatrix: params.stage.window.getViewBoxTransform(), ...params, ...userParams }); @@ -128,8 +126,6 @@ export class CanvasLayerHandlerContribution implements ILayerHandlerContribution const context = target.getContext(); params.renderService.render(group, { context, - viewBox: params.stage.window.getViewBox(), - transMatrix: params.stage.window.getViewBoxTransform(), ...params, clear: params.clear ? params.background ?? '#fff' : undefined }); 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 3b3e6fcd3..ad1f55fc2 100644 --- a/packages/vrender-core/src/core/contributions/layerHandler/empty-contribution.ts +++ b/packages/vrender-core/src/core/contributions/layerHandler/empty-contribution.ts @@ -72,8 +72,6 @@ export class EmptyLayerHandlerContribution implements ILayerHandlerContribution const context = target.getContext(); params.renderService.render(group, { context, - viewBox: params.stage.window.getViewBox(), - transMatrix: params.stage.window.getViewBoxTransform(), ...params, clear: params.clear ? params.background ?? '#fff' : undefined }); 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 464c811dd..c3613934c 100644 --- a/packages/vrender-core/src/core/contributions/layerHandler/offscreen2d-contribution.ts +++ b/packages/vrender-core/src/core/contributions/layerHandler/offscreen2d-contribution.ts @@ -92,7 +92,11 @@ export class OffscreenLayerHandlerContribution implements ILayerHandlerContribut const context = target.getContext(); const targetDpr = target.dpr; - const { x = 0, y = 0, width = this.layer.viewWidth, height = this.layer.viewHeight } = params; + const { viewBox } = params; + const x = viewBox.x1; + const y = viewBox.y1; + const width = viewBox.width(); + const height = viewBox.height(); // 这个context可能是外部的,不要使用内置的状态,直接用原生的context context.nativeContext.save(); context.nativeContext.setTransform(targetDpr, 0, 0, targetDpr, 0, 0); diff --git a/packages/vrender-core/src/core/graphic-utils.ts b/packages/vrender-core/src/core/graphic-utils.ts index 92c65bab4..5afbaa4a4 100644 --- a/packages/vrender-core/src/core/graphic-utils.ts +++ b/packages/vrender-core/src/core/graphic-utils.ts @@ -24,6 +24,7 @@ import { application } from '../application'; import { container } from '../container'; import { VWindow } from './window'; import { graphicCreator } from '../graphic'; +import { matrixAllocate } from '../allocator/matrix-allocate'; @injectable() export class DefaultGraphicUtil implements IGraphicUtil { @@ -132,7 +133,10 @@ export class DefaultGraphicUtil implements IGraphicUtil { const bounds = graphic.AABBBounds; const width = bounds.width(); const height = bounds.height(); + const x1 = -bounds.x1; + const y1 = -bounds.y1; window.create({ + viewBox: { x1, y1, x2: bounds.x2, y2: bounds.y2 }, width, height, canvas, @@ -142,16 +146,12 @@ export class DefaultGraphicUtil implements IGraphicUtil { title: '' }); - const x = -bounds.x1; - const y = -bounds.y1; const disableCheckGraphicWidthOutRange = stage.params.optimize.disableCheckGraphicWidthOutRange; // 关掉dirtyBounds检测 stage.params.optimize.disableCheckGraphicWidthOutRange = true; stage.defaultLayer.getNativeHandler().drawTo(window, [graphic as any], { - x, - y, - width, - height, + transMatrix: window.getViewBoxTransform(), + viewBox: window.getViewBox(), stage, layer: stage.defaultLayer, renderService: stage.renderService, diff --git a/packages/vrender-core/src/core/layer.ts b/packages/vrender-core/src/core/layer.ts index d1c3989f2..39db24ea5 100644 --- a/packages/vrender-core/src/core/layer.ts +++ b/packages/vrender-core/src/core/layer.ts @@ -173,6 +173,8 @@ export class Layer extends Group implements ILayer { renderService: params.renderService, stage: this.stage, layer: this, + viewBox: params.viewBox, + transMatrix: params.transMatrix, // TODO: 多图层时不应该再用默认background background: params.background ?? this.background, updateBounds: params.updateBounds @@ -208,20 +210,20 @@ export class Layer extends Group implements ILayer { return; } - // 合并到某个target上 - combineTo(target: IWindow, params: IDrawToParams) { - if (this.offscreen) { - this.layerHandler.drawTo(target, [this], { - // TODO: 多图层时不应该再用默认background - background: params.background ?? this.background, - renderService: params.renderService, - stage: this.stage, - layer: this, - ...params - }); - this.afterDrawCbs.forEach(c => c(this)); - } - } + // // 合并到某个target上 + // combineTo(target: IWindow, params: IDrawToParams) { + // if (this.offscreen) { + // this.layerHandler.drawTo(target, [this], { + // // TODO: 多图层时不应该再用默认background + // background: params.background ?? this.background, + // renderService: params.renderService, + // stage: this.stage, + // layer: this, + // ...params + // }); + // this.afterDrawCbs.forEach(c => c(this)); + // } + // } release(): void { super.release(); @@ -239,7 +241,8 @@ export class Layer extends Group implements ILayer { // TODO: 多图层时不应该再用默认background background: params.background ?? this.background, renderService: params.renderService, - + viewBox: params.viewBox, + transMatrix: params.transMatrix, stage: this.stage, layer: this, ...params diff --git a/packages/vrender-core/src/core/stage.ts b/packages/vrender-core/src/core/stage.ts index a3dd3b023..d49c6e968 100644 --- a/packages/vrender-core/src/core/stage.ts +++ b/packages/vrender-core/src/core/stage.ts @@ -720,7 +720,9 @@ export class Stage extends Group implements IStage { { renderService: this.renderService, background: layer === this.defaultLayer ? this.background : undefined, - updateBounds: !!(this.dirtyBounds && !this.dirtyBounds.empty()) + updateBounds: !!(this.dirtyBounds && !this.dirtyBounds.empty()), + viewBox: this.window.getViewBox(), + transMatrix: this.window.getViewBoxTransform() }, { renderStyle: this.renderStyle, ...params } ); @@ -731,7 +733,9 @@ export class Stage extends Group implements IStage { this.interactiveLayer.render( { renderService: this.renderService, - updateBounds: !!(this.dirtyBounds && !this.dirtyBounds.empty()) + updateBounds: !!(this.dirtyBounds && !this.dirtyBounds.empty()), + viewBox: this.window.getViewBox(), + transMatrix: this.window.getViewBoxTransform() }, { renderStyle: this.renderStyle, ...params } ); @@ -870,11 +874,13 @@ export class Stage extends Group implements IStage { return layer[0] as ILayer; } - renderTo(window: IWindow, params: { x: number; y: number; width: number; height: number }) { + renderTo(window: IWindow) { this.forEachChildren((layer, i) => { layer.drawTo(window, { - ...params, + // ...params, renderService: this.renderService, + viewBox: window.getViewBox(), + transMatrix: window.getViewBoxTransform(), background: layer === this.defaultLayer ? this.background : undefined, clear: i === 0, // 第一个layer需要clear updateBounds: !!(this.dirtyBounds && !this.dirtyBounds.empty()) @@ -889,19 +895,25 @@ export class Stage extends Group implements IStage { */ renderToNewWindow(fullImage: boolean = true, viewBox?: IAABBBounds): IWindow { const window = container.get(VWindow); + const x1 = viewBox ? -viewBox.x1 : 0; + const y1 = viewBox ? -viewBox.y1 : 0; + const x2 = viewBox ? viewBox.x2 : this.viewWidth; + const y2 = viewBox ? viewBox.y2 : this.viewHeight; + const width = viewBox ? viewBox.width() : this.viewWidth; + const height = viewBox ? viewBox.height() : this.viewHeight; if (fullImage) { window.create({ - width: this.viewWidth, - height: this.viewHeight, + viewBox: { x1, y1, x2, y2 }, + width, + height, dpr: this.window.dpr, canvasControled: true, offscreen: true, title: '' }); } else { - const width = viewBox ? viewBox.width() : Math.min(this.viewWidth, this.window.width - this.x); - const height = viewBox ? viewBox.height() : Math.min(this.viewHeight, this.window.height - this.y); window.create({ + viewBox: { x1, y1, x2, y2 }, width, height, dpr: this.window.dpr, @@ -911,14 +923,7 @@ export class Stage extends Group implements IStage { }); } - const x = viewBox ? -viewBox.x1 : 0; - const y = viewBox ? -viewBox.y1 : 0; - this.renderTo(window, { - x, - y, - width: viewBox ? viewBox.x2 : window.width, - height: viewBox ? viewBox.y2 : window.height - }); + this.renderTo(window); return window; } diff --git a/packages/vrender-core/src/interface/layer.ts b/packages/vrender-core/src/interface/layer.ts index db6fd57c1..48e44d1f9 100644 --- a/packages/vrender-core/src/interface/layer.ts +++ b/packages/vrender-core/src/interface/layer.ts @@ -1,4 +1,4 @@ -import type { IAABBBounds, IBounds, IBoundsLike } from '@visactor/vutils'; +import type { IAABBBounds, IBounds, IBoundsLike, IMatrix } from '@visactor/vutils'; import type { IGraphic } from './graphic'; import type { IGroup } from './graphic/group'; import type { IColor } from './color'; @@ -22,13 +22,13 @@ export interface ILayerDrawParams { renderService: IRenderService; background?: string | IColor; updateBounds: boolean; + viewBox: IAABBBounds; + transMatrix: IMatrix; } export interface IDrawToParams { - x?: number; - y?: number; - width?: number; - height?: number; + viewBox: IAABBBounds; + transMatrix: IMatrix; clear?: boolean; renderService: IRenderService; background?: string | IColor; @@ -76,7 +76,7 @@ export interface ILayer extends IGroup { setToFrame: (t: number) => void; prepare: (dirtyBounds: IBounds, params: ILayerHandlerDrawParams) => void; drawTo: (target: IWindow, params: IDrawToParams) => void; - combineTo: (target: IWindow, params: IDrawToParams) => void; + // combineTo: (target: IWindow, params: IDrawToParams) => void; // 考虑操作回放 } diff --git a/packages/vrender-core/src/interface/render.ts b/packages/vrender-core/src/interface/render.ts index e4573ad35..8a2da061a 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, IBoundsLike, IMatrixLike } from '@visactor/vutils'; +import type { IAABBBounds, IBounds, IMatrix, IMatrixLike } from '@visactor/vutils'; import type { IColor } from './color'; import type { IContext2d } from './context'; import type { IGraphic, IGraphicAttribute } from './graphic'; diff --git a/packages/vrender/__tests__/browser/src/pages/chart.ts b/packages/vrender/__tests__/browser/src/pages/chart.ts index 3c0b72d0f..ccde6efb0 100644 --- a/packages/vrender/__tests__/browser/src/pages/chart.ts +++ b/packages/vrender/__tests__/browser/src/pages/chart.ts @@ -1823,7 +1823,7 @@ export const page = () => { tlist.reverse().forEach(t => { const c = graphicUtil.drawGraphicToCanvas(t, stage); console.log(c, t.attribute.text); - // document.body.appendChild(c); + document.body.appendChild(c); }); // const t = performance.now(); diff --git a/packages/vrender/__tests__/browser/src/pages/symbol.ts b/packages/vrender/__tests__/browser/src/pages/symbol.ts index 480f355de..573a696ea 100644 --- a/packages/vrender/__tests__/browser/src/pages/symbol.ts +++ b/packages/vrender/__tests__/browser/src/pages/symbol.ts @@ -125,5 +125,5 @@ export const page = () => { console.log(stage); const c = stage.toCanvas(false, new AABBBounds().set(100, 100, 300, 360)); - // document.body.appendChild(c); + document.body.appendChild(c); }; diff --git a/packages/vrender/__tests__/browser/vite.config.ts b/packages/vrender/__tests__/browser/vite.config.ts index 2d7ff256a..e048c718b 100644 --- a/packages/vrender/__tests__/browser/vite.config.ts +++ b/packages/vrender/__tests__/browser/vite.config.ts @@ -7,7 +7,24 @@ export default defineConfig({ open: true, port: 3012 }, - plugins: [react()], + plugins: [ + react({ + babel: { + parserOpts: { + plugins: ['decorators-legacy', 'classProperties'] + }, + plugins: [ + [ + '@babel/plugin-transform-react-jsx', + { + pragma: 'jsx', + pragmaFrag: 'Fragment' + } + ] + ] + } + }) + ], resolve: { alias: { '@visactor/vrender': path.resolve(__dirname, '../../../vrender/src/index.ts'), From f956238fd2c6988f6ff6c25ff109e041c741d52c Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Mon, 5 Feb 2024 17:09:07 +0800 Subject: [PATCH 4/7] fix: fix issue with restore in draw-contribution --- .../src/render/contributions/render/draw-contribution.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 365b10573..040643612 100644 --- a/packages/vrender-core/src/render/contributions/render/draw-contribution.ts +++ b/packages/vrender-core/src/render/contributions/render/draw-contribution.ts @@ -168,7 +168,7 @@ export class DefaultDrawContribution implements IDrawContribution { : this.renderItem(group as IGraphic, drawContext); }); - context.restore(); + // context.restore(); context.restore(); context.draw(); context.setClearMatrix(1, 0, 0, 1, 0, 0); From 9a7a0a976a3766c0e73d8a69a8abcca2355c4c5b Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Tue, 6 Feb 2024 17:37:45 +0800 Subject: [PATCH 5/7] feat: support pauseRender and resumeRender --- packages/vrender-core/src/core/stage.ts | 24 +++++++++++++++----- packages/vrender-core/src/interface/stage.ts | 3 +++ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/packages/vrender-core/src/core/stage.ts b/packages/vrender-core/src/core/stage.ts index d49c6e968..b1194ffbb 100644 --- a/packages/vrender-core/src/core/stage.ts +++ b/packages/vrender-core/src/core/stage.ts @@ -289,6 +289,14 @@ export class Stage extends Group implements IStage { } } + pauseRender() { + this._skipRender = -1; + } + + resumeRender() { + this._skipRender = 0; + } + protected tryInitEventSystem() { if (this.global.supportEvent && !this._eventSystem) { this._eventSystem = new EventSystem({ @@ -635,9 +643,11 @@ export class Stage extends Group implements IStage { if (!this._skipRender) { this.lastRenderparams = params; this.hooks.beforeRender.call(this); - this.renderLayerList(this.children as ILayer[]); - this.combineLayersToWindow(); - this.nextFrameRenderLayerSet.clear(); + if (!this._skipRender) { + this.renderLayerList(this.children as ILayer[]); + this.combineLayersToWindow(); + this.nextFrameRenderLayerSet.clear(); + } this.hooks.afterRender.call(this); } this.state = state; @@ -688,10 +698,12 @@ export class Stage extends Group implements IStage { this.layerService.prepareStageLayer(this); if (this.nextFrameRenderLayerSet.size && !this._skipRender) { this.hooks.beforeRender.call(this); - this.renderLayerList(Array.from(this.nextFrameRenderLayerSet.values()), this.lastRenderparams || {}); - this.combineLayersToWindow(); + if (!this._skipRender) { + this.renderLayerList(Array.from(this.nextFrameRenderLayerSet.values()), this.lastRenderparams || {}); + this.combineLayersToWindow(); + this.nextFrameRenderLayerSet.clear(); + } this.hooks.afterRender.call(this); - this.nextFrameRenderLayerSet.clear(); } this.state = state; this._skipRender && this._skipRender++; diff --git a/packages/vrender-core/src/interface/stage.ts b/packages/vrender-core/src/interface/stage.ts index 34de7a441..58d22069a 100644 --- a/packages/vrender-core/src/interface/stage.ts +++ b/packages/vrender-core/src/interface/stage.ts @@ -220,6 +220,9 @@ export interface IStage extends INode { release: () => void; setStage: (stage?: IStage) => void; + pauseRender: () => void; + resumeRender: () => void; + setCursor: (mode?: string) => void; getTheme: () => IFullThemeSpec; From 33df78c9ca3e12bfcaa0ae6e989fb1246825eca7 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Sun, 18 Feb 2024 13:11:08 +0800 Subject: [PATCH 6/7] fix: fix issue with event pick caused by globalXY --- packages/vrender-core/src/event/event-manager.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/vrender-core/src/event/event-manager.ts b/packages/vrender-core/src/event/event-manager.ts index c21916909..ac6ab9e1d 100644 --- a/packages/vrender-core/src/event/event-manager.ts +++ b/packages/vrender-core/src/event/event-manager.ts @@ -633,7 +633,7 @@ export class EventManager { if (target) { event.target = target; } else { - event.target = this.pickTarget(event.global.x, event.global.y, event); + event.target = this.pickTarget(event.viewX ?? event.global.x, event.viewY ?? event.global.y, event); } if (typeof type === 'string') { @@ -652,7 +652,7 @@ export class EventManager { event.nativeEvent = from.nativeEvent; event.originalEvent = from; - event.target = target || this.pickTarget(event.global.x, event.global.y, event); + event.target = target || this.pickTarget(event.viewX ?? event.global.x, event.viewY ?? event.global.y, event); return event; } From fe040524f491d5671173839cceacb7d0fcd8aca2 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Tue, 20 Feb 2024 10:27:01 +0800 Subject: [PATCH 7/7] fix: fix issue while canvas is offscreencanvas --- packages/vrender-core/src/core/window.ts | 2 +- .../contributions/browser-contribution.ts | 2 +- .../__tests__/browser/src/pages/index.ts | 4 ++ .../__tests__/browser/src/pages/offscreen.ts | 37 +++++++++++++++++++ 4 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 packages/vrender/__tests__/browser/src/pages/offscreen.ts diff --git a/packages/vrender-core/src/core/window.ts b/packages/vrender-core/src/core/window.ts index 7ff2dfdde..7a60739ce 100644 --- a/packages/vrender-core/src/core/window.ts +++ b/packages/vrender-core/src/core/window.ts @@ -102,7 +102,7 @@ export class DefaultWindow implements IWindow { } get style(): CSSStyleDeclaration | Record { - return this._handler.getStyle(); + return this._handler.getStyle() ?? {}; } set style(style: CSSStyleDeclaration | Record) { diff --git a/packages/vrender-kits/src/window/contributions/browser-contribution.ts b/packages/vrender-kits/src/window/contributions/browser-contribution.ts index 7ba4902cb..99545bd17 100644 --- a/packages/vrender-kits/src/window/contributions/browser-contribution.ts +++ b/packages/vrender-kits/src/window/contributions/browser-contribution.ts @@ -58,7 +58,7 @@ export class BrowserWindowHandlerContribution } getTitle(): string { - return this.canvas.id.toString(); + return this.canvas.id && this.canvas.id.toString(); } getWH(): { width: number; height: number } { diff --git a/packages/vrender/__tests__/browser/src/pages/index.ts b/packages/vrender/__tests__/browser/src/pages/index.ts index 2b89a0a98..dce28018e 100644 --- a/packages/vrender/__tests__/browser/src/pages/index.ts +++ b/packages/vrender/__tests__/browser/src/pages/index.ts @@ -99,6 +99,10 @@ export const pages = [ name: '图形测试', path: 'graphic' }, + { + name: '离屏渲染', + path: 'offscreen' + }, { name: '主题测试', path: 'theme' diff --git a/packages/vrender/__tests__/browser/src/pages/offscreen.ts b/packages/vrender/__tests__/browser/src/pages/offscreen.ts new file mode 100644 index 000000000..96f8197fc --- /dev/null +++ b/packages/vrender/__tests__/browser/src/pages/offscreen.ts @@ -0,0 +1,37 @@ +import { createStage, createRect, IGraphic, createPath } from '@visactor/vrender'; +import { roughModule } from '@visactor/vrender-kits'; +import { addShapesToStage, colorPools } from '../utils'; + +// container.load(roughModule); +export const page = () => { + const graphics: IGraphic[] = []; + graphics.push( + createPath({ + x: 100, + y: 100, + path: 'M -2 2 L 4 -5 L 7 -6 L 6 -3 L -1 3 C 0 4 0 5 1 4 C 1 5 2 6 1 6 A 1.42 1.42 0 0 1 0 7 A 5 5 0 0 0 -2 4 Q -2.5 3.9 -2.5 4.5 T -4 5.8 T -4.8 5 T -3.5 3.5 T -3 3 A 5 5 90 0 0 -6 1 A 1.42 1.42 0 0 1 -5 0 C -5 -1 -4 0 -3 0 C -4 1 -3 1 -2 2 M 4 -5 L 4 -3 L 6 -3 L 5 -4 L 4 -5', + fill: '#ccc', + stroke: 'grey', + scaleX: 10, + scaleY: 10 + }) + ); + + const canvas = new OffscreenCanvas(100, 100); + + const stage = createStage({ + canvas: canvas, + width: 200, + height: 200, + autoRender: true + }); + + setTimeout(() => { + const ctx = document.getElementById('main').getContext('2d'); + ctx.drawImage(canvas, 0, 0); + }, 1000); + + graphics.forEach(g => { + stage.defaultLayer.add(g); + }); +};