Skip to content

Commit

Permalink
feat: support base vtable
Browse files Browse the repository at this point in the history
  • Loading branch information
xuefei1313 committed Dec 25, 2024
1 parent 0e79525 commit 67a8772
Show file tree
Hide file tree
Showing 32 changed files with 1,872 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export class VChartRender extends DefaultCanvasRectRender implements IGraphicRen
const vchartCtx = vchartStage.window.getContext();
vchartCtx.baseGlobalAlpha *= baseOpacity;
// @ts-ignore
vchartStage._editor_needRender = true;
vchartStage._story_needRender = true;
const matrix = chart.globalTransMatrix.clone();
// auto 模式下,需要将vchart.stage的viewBoxTransform 设置到包含偏移量的位置
matrix.translate(chart.vchartAutoTranslate.x, chart.vchartAutoTranslate.y);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,15 +119,15 @@ export class VChartGraphic extends Rect {
// 只有vstory触发的render才会真的render
beforeRender: stage => {
const chartStage = this._vchart.getStage();
if (!(chartStage as any)._editor_needRender) {
if (!(chartStage as any)._story_needRender) {
chartStage.pauseRender();
stage.dirtyBounds?.union(this.globalAABBBounds);
stage.renderNextFrame();
}
},
afterRender: stage => {
// @ts-ignore
stage._editor_needRender = false;
stage._story_needRender = false;
stage.resumeRender();
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
// const vChart = (chart as Chart).vchart;
// const chartStage = vChart.getStage();
// // @ts-ignore
// chartStage._editor_needRender = true;
// chartStage._story_needRender = true;
// const matrix = chart.globalTransMatrix.clone();
// const stageMatrix = chart.stage.window.getViewBoxTransform();
// matrix.multiply(stageMatrix.a, stageMatrix.b, stageMatrix.c, stageMatrix.d, stageMatrix.e, stageMatrix.f);
Expand Down
145 changes: 145 additions & 0 deletions packages/vstory-core/src/character/table/character-table.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
import type { ITicker, ITimeline } from '@visactor/vrender-core';
import { DefaultTimeline, ManualTicker } from '@visactor/vrender-core';
import type { ICharacterPickInfo, IStoryEvent } from '../../interface/event';
import { CharacterBase } from '../character-base';
import type { ITableGraphicAttribute, IVTable } from './graphic/vtable-graphic';
import { VTableGraphic } from './graphic/vtable-graphic';
import { getTableModelWithEvent } from './utils/vtable-pick';
import type { ICharacterConfig, ICharacterInitOption } from '../../interface/dsl/dsl';
import type { ITableCharacterConfig } from '../../interface/dsl/table';
import { getLayoutFromWidget } from '../../utils/layout';
import type { ITableCharacterRuntime, IUpdateConfigParams } from './interface/runtime';
import { TableConfigProcess } from './table-config-process';
import type { ICharacterTable } from './interface/character-table';
import { CommonSpecRuntimeInstance } from './runtime/common-spec';
import { CommonLayoutRuntimeInstance } from '../chart/runtime/common-layout';

export class CharacterTable<T extends ITableGraphicAttribute>
extends CharacterBase<ITableGraphicAttribute>
implements ICharacterTable
{
visActorType: 'table' | 'component' | 'table' | 'common' = 'table';
protected declare _graphic: VTableGraphic;
protected declare _config: ITableCharacterConfig;

// 临时记录 vtable 对象。在第一次执行 afterInitializeTable 后赋值, 在 afterVRenderDraw 中使用
// 不临时记录的话,第一次 afterVRenderDraw 时,graphic 对象还未执行完初始化,当前对象的 _graphic 为 null
protected _vtable: IVTable;

protected _ticker: ITicker;
protected _timeline: ITimeline;
protected _runtime: ITableCharacterRuntime[] = [];

constructor(config: ICharacterConfig, option: ICharacterInitOption) {
super(config, option);
this._timeline = new DefaultTimeline();
this._ticker = new ManualTicker([this._timeline]);
this.configProcess = new TableConfigProcess(this);
}

get config() {
return this._config;
}

tickTo(t: number): void {
this._graphic.vTableStage.ticker.tickAt && this._graphic.vTableStage.ticker.tickAt(t);
}

getGraphicBySelector(selector: string) {
const table = true;
// 是否包含panel, >0为包含
const includePanel = 1;

return {
table,
panel: includePanel > 0
};
}

checkEvent(event: IStoryEvent): false | ICharacterPickInfo {
if (!(event.detailPath ?? event.path).some(g => g === this._graphic)) {
return false;
}
const tablePath = event.detailPath[event.detailPath.length - 1];
const result = getTableModelWithEvent(this._graphic.vTable, event);
if (!result) {
// 点击到图表的空白区域
if (this._graphic.pointInViewBox((event as any).canvasX, (event as any).canvasY)) {
return {
part: 'null',
graphic: null,
modelInfo: null,
graphicType: 'null'
};
}
return false;
}
const graphic = tablePath?.[tablePath.length - 1];
return {
part: result.type,
modelInfo: result,
graphic,
graphicType: graphic.type
};
}

_initGraphic() {
this.applyConfigToAttribute(this._config, this._config);
const attribute = this.getAttribute();

this._graphic = new VTableGraphic(attribute);

this.canvas.addGraphic(this._graphic);
}

protected _initRuntime(): void {
this._runtime.push(CommonLayoutRuntimeInstance as any, CommonSpecRuntimeInstance);
}
protected _clearRuntime(): void {
this._runtime.length = 0;
}

protected getViewBoxFromSpec() {
const layout = getLayoutFromWidget(this._config.position);
const viewBox = {
x1: layout.x,
x2: layout.x + layout.width,
y1: layout.y,
y2: layout.y + layout.height
};
return { layout, viewBox };
}

protected applyConfigToAttribute(diffConfig: IUpdateConfigParams, config: IUpdateConfigParams): void {
this._attribute = this.getDefaultAttribute() as any;
this._runtime.forEach(r => r.applyConfigToAttribute?.(this));
}

getDefaultAttribute(): Partial<ITableGraphicAttribute> {
return {
spec: this._config.options.spec,
dpr: this._canvas.getDpr(),
autoRender: false,
width: 500,
height: 500,
interactive: false,
panel: {},
ticker: this._ticker,
zIndex: this._config.zIndex ?? 0,
chartOption: {
disableTriggerEvent: true,
disableDirtyBounds: true,
mode: 'desktop-browser'
}
};
}

protected _clearGraphic(): void {
super._clearGraphic();
this._vtable = null;
}

getRuntimeConfig() {
return this;
}
}
7 changes: 7 additions & 0 deletions packages/vstory-core/src/character/table/character/vtable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { CharacterType } from '../../../constants/character';
import { CharacterTable } from '../character-table';
import type { ITableGraphicAttribute } from '../graphic/vtable-graphic';

export class VTableCharacter extends CharacterTable<ITableGraphicAttribute> {
static type = CharacterType.VTABLE;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { injectable } from '@visactor/vrender';
import type { IGraphicPicker, IPickParams } from '@visactor/vrender';
import type { VTableGraphic } from './vtable-graphic';
import { TABLE_NUMBER_TYPE } from './vtable-graphic';

@injectable()
export class VTablePicker implements IGraphicPicker {
type = 'table';
numberType: number = TABLE_NUMBER_TYPE;

contains(table: any, point: any, params?: IPickParams): boolean | any {
// 将当前的point转化到global
const matrix = table.parent.globalTransMatrix.clone();
const stageMatrix = table.stage.window.getViewBoxTransform();
matrix.multiply(stageMatrix.a, stageMatrix.b, stageMatrix.c, stageMatrix.d, stageMatrix.e, stageMatrix.f);
const toGlobalMatrix = matrix.getInverse();
const nextP = { x: 0, y: 0 };
toGlobalMatrix.transformPoint(point, nextP);

// 得到 vtable stage
const vTable = (table as VTableGraphic).vTable;
const vtableStage = vTable.scenegraph.stage;
vtableStage.dirtyBounds?.clear();
const toTableMatrix = vtableStage.window.getViewBoxTransform();
toTableMatrix.transformPoint(nextP, nextP);
const pick = vtableStage.pick(nextP.x, nextP.y);
// @ts-ignore
if (pick.graphic === null && pick.group.name === 'root') {
return false;
}
return pick;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import type {
IContext2d,
IDrawContext,
IGraphicAttribute,
IGraphicRender,
IGraphicRenderDrawParams,
IMarkAttribute,
IRenderService,
IThemeAttribute
} from '@visactor/vrender';
import { injectable, DefaultCanvasRectRender } from '@visactor/vrender';
import type { VTableGraphic } from './vtable-graphic';
import { TABLE_NUMBER_TYPE } from './vtable-graphic';

export const TableRender = Symbol.for('VStoryTableRender');
export const TableRenderContribution = Symbol.for('VStoryTableRenderContribution');

@injectable()
export class VTableRender extends DefaultCanvasRectRender implements IGraphicRender {
type: 'table';
numberType: number = TABLE_NUMBER_TYPE;

drawShape(
table: any,
context: IContext2d,
x: number,
y: number,
drawContext: IDrawContext,
params?: IGraphicRenderDrawParams,
fillCb?: (
ctx: IContext2d,
markAttribute: Partial<IMarkAttribute & IGraphicAttribute>,
themeAttribute: IThemeAttribute
) => boolean,
strokeCb?: (
ctx: IContext2d,
markAttribute: Partial<IMarkAttribute & IGraphicAttribute>,
themeAttribute: IThemeAttribute
) => boolean
) {
const { baseOpacity = 1 } = table.attribute;
if (baseOpacity <= 0) {
return;
}
context.baseGlobalAlpha *= baseOpacity;
super.drawShape(table, context, x, y, drawContext, params, fillCb, strokeCb);
// TODO 考虑一个通用的ctx清理逻辑
if (context._clearFilterStyle && context.nativeContext) {
context.nativeContext.filter = 'blur(0px)';
context._clearFilterStyle = false;
}
context.baseGlobalAlpha /= baseOpacity;
const vTable = (table as VTableGraphic).vTable;
const vTableStage = vTable.scenegraph.stage;
const vTableCtx = vTableStage.window.getContext();
vTableCtx.baseGlobalAlpha *= baseOpacity;
// @ts-ignore
vTableStage._story_needRender = true;
const matrix = table.globalTransMatrix.clone();
// auto 模式下,需要将vTable.stage的viewBoxTransform 设置到包含偏移量的位置
matrix.translate(table.vTableAutoTranslate.x, table.vTableAutoTranslate.y);
const stageMatrix = table.stage.window.getViewBoxTransform().clone();
stageMatrix.multiply(matrix.a, matrix.b, matrix.c, matrix.d, matrix.e, matrix.f);
vTableStage.window.setViewBoxTransform(
stageMatrix.a,
stageMatrix.b,
stageMatrix.c,
stageMatrix.d,
stageMatrix.e,
stageMatrix.f
);
vTableStage.dirtyBounds?.clear();
vTableStage.render();
vTableCtx.baseGlobalAlpha /= baseOpacity;
}

draw(table: any, renderService: IRenderService, drawContext: IDrawContext, params?: IGraphicRenderDrawParams) {
// const tableAttribute = getTheme(table, params?.theme).circle;
this._draw(table, {} as any, false, drawContext, params);
}
}
Loading

0 comments on commit 67a8772

Please sign in to comment.