From 0522903c8a9cdc23eac519cd169aaa7f203c716d Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Thu, 9 Jan 2025 11:22:49 +0800 Subject: [PATCH] feat: access shape selection --- .../component/graphic/ShapeComponent.ts | 4 +- packages/vstory-editor/src/register.ts | 3 +- .../src/selection/base-selection.ts | 4 +- .../src/selection/shape-selection.ts | 28 ++++++ packages/vstory/demo/src/App.tsx | 7 +- .../vstory/demo/src/demos/edit/components.tsx | 94 +++++++++++++++++++ 6 files changed, 135 insertions(+), 5 deletions(-) create mode 100644 packages/vstory-editor/src/selection/shape-selection.ts create mode 100644 packages/vstory/demo/src/demos/edit/components.tsx diff --git a/packages/vstory-core/src/character/component/graphic/ShapeComponent.ts b/packages/vstory-core/src/character/component/graphic/ShapeComponent.ts index 8b475036..da6b50b1 100644 --- a/packages/vstory-core/src/character/component/graphic/ShapeComponent.ts +++ b/packages/vstory-core/src/character/component/graphic/ShapeComponent.ts @@ -9,6 +9,8 @@ const shapeMap: any = { }; export class ShapeComponent extends BaseComponentWithText { + type: string = 'ShapeComponent'; + mainGraphic: ISymbol; static defaultAttributes: Partial = { visible: true, textStyle: {}, @@ -56,7 +58,7 @@ export class ShapeComponent extends BaseComponentWithText { dy = attrs.size / 2; } - this.createOrUpdateChild( + this.mainGraphic = this.createOrUpdateChild( 'symbol', { ...attrs, diff --git a/packages/vstory-editor/src/register.ts b/packages/vstory-editor/src/register.ts index f33d9d61..33020089 100644 --- a/packages/vstory-editor/src/register.ts +++ b/packages/vstory-editor/src/register.ts @@ -2,6 +2,7 @@ import { CharacterType } from '@visactor/vstory-core'; import { Edit } from './edit'; import { RectSelection } from './selection/rect-selection'; import { AutoEnablePlugins, container, ContainerModule, RichTextEditPlugin } from '@visactor/vrender-core'; +import { ShapeSelection } from './selection/shape-selection'; const editPlugin = new ContainerModule(bind => { bind(RichTextEditPlugin).toSelf(); @@ -15,7 +16,7 @@ export function registerAllSelection() { // Edit.registerEditSelection('richtext', RichTextSelection); Edit.registerEditSelection(CharacterType.RECT, RectSelection); // Edit.registerEditSelection(CharacterType.IMAGE, ImageSelection); - // Edit.registerEditSelection(CharacterType.SHAPE, ShapeSelection); + Edit.registerEditSelection(CharacterType.SHAPE, ShapeSelection); // Edit.registerEditSelection('chart', ChartSelection); // Edit.registerEditSelection('box-selection', BoxSelection); // Edit.registerEditSelection('series-mark-selection', SeriesMarkSelection); diff --git a/packages/vstory-editor/src/selection/base-selection.ts b/packages/vstory-editor/src/selection/base-selection.ts index 8c4409b1..fbf3c33c 100644 --- a/packages/vstory-editor/src/selection/base-selection.ts +++ b/packages/vstory-editor/src/selection/base-selection.ts @@ -113,8 +113,8 @@ export abstract class BaseSelection implements IEditSelection { return; } const component = actionInfo.character.graphic; - const rect = component.mainGraphic; - const bounds = rect.AABBBounds.clone(); + const graphic = component.mainGraphic; + const bounds = graphic.AABBBounds.clone(); const { angle, x, y } = component.attribute; bounds.translate(x, y); this._layoutController.updateBoundsAndAngle(bounds, angle); diff --git a/packages/vstory-editor/src/selection/shape-selection.ts b/packages/vstory-editor/src/selection/shape-selection.ts new file mode 100644 index 00000000..d6fc7ba3 --- /dev/null +++ b/packages/vstory-editor/src/selection/shape-selection.ts @@ -0,0 +1,28 @@ +import { CharacterType } from '@visactor/vstory-core'; +import type { IEditActionInfo, IEditSelection } from '../interface'; +import { RichTextSelectionCommon } from './richtext-selection-common'; + +export class ShapeSelection extends RichTextSelectionCommon implements IEditSelection { + readonly level = 3; + readonly type: string = 'shape'; + readonly editCharacterType: string = CharacterType.SHAPE; + readonly supportedCharacterType: string[] = [CharacterType.SHAPE]; + + startEdit(actionInfo: IEditActionInfo) { + super.startEdit(actionInfo); + // @ts-ignore; + const character = this._actionInfo.character; + character.graphic.addEventListener('pointerdown', this.handlerContentClick); + } + endEdit() { + // @ts-ignore; + const character = this._actionInfo.character; + character.graphic.removeEventListener('pointerdown', this.handlerContentClick); + super.endEdit(); + } + + handlerContentClick = (e: any) => { + this._layoutController.handleDragMouseDown(e); + // this.endRichTextEdit(); + }; +} diff --git a/packages/vstory/demo/src/App.tsx b/packages/vstory/demo/src/App.tsx index e627efe0..09ab6e30 100644 --- a/packages/vstory/demo/src/App.tsx +++ b/packages/vstory/demo/src/App.tsx @@ -62,6 +62,7 @@ import { SpecAxes } from './demos/chart/runtime/spec-axes'; import { RuntimeTotalLabel } from './demos/chart/runtime/total-label'; import { RectComponent } from './demos/component/rect'; import { TableInfographic } from './demos/infographic/infographic-table'; +import { ComponentsEdit } from './demos/edit/components'; type MenusType = ( | { @@ -309,8 +310,12 @@ const App = () => { ] }, { - name: 'VChart Editor', + name: 'Editor', subMenus: [ + { + name: 'Components', + component: ComponentsEdit + }, { name: 'Base Chart', component: BaseChart diff --git a/packages/vstory/demo/src/demos/edit/components.tsx b/packages/vstory/demo/src/demos/edit/components.tsx new file mode 100644 index 00000000..c66fb8c5 --- /dev/null +++ b/packages/vstory/demo/src/demos/edit/components.tsx @@ -0,0 +1,94 @@ +import React, { createRef, useEffect } from 'react'; +import { Player, Story } from '../../../../../vstory-core/src'; +import { registerAllSelection } from '../../../../../vstory-editor/src'; +import { Edit, registerAll } from '../../../../src'; + +registerAll(); +registerAllSelection(); + +export const ComponentsEdit = () => { + const id = 'ComponentsEdit'; + useEffect(() => { + const container = document.getElementById(id); + const canvas = document.createElement('canvas'); + container?.appendChild(canvas); + + const story = new Story(null, { + canvas, + width: 1000, + height: 600, + layerBackground: 'white', + background: 'pink', + // scaleX: 0.5, + // scaleY: 0.5, + layerViewBox: { x1: 100, y1: 100, x2: 900, y2: 500 } + }); + const player = new Player(story); + story.init(player); + + story.addCharacterWithAppear({ + type: 'Shape', + id: 'star', + zIndex: 10, + position: { + top: 100, + left: 100, + width: 80, + height: 60 + }, + options: { + graphic: { + stroke: false, + fill: 'pink', + symbolType: 'star' + // size: 100 + } + } + }); + story.addCharacterWithAppear({ + type: 'Rect', + id: 'title', + zIndex: 1, + position: { + top: 100, + left: 100, + width: 200, + height: 200 + }, + options: { + graphic: { + fill: 'red' + }, + text: { + text: 'hello world', + fontSize: 30, + fill: 'blue' + } + } + }); + + player.play(-1); + + let selectedCharacter: any = null; + const edit = new Edit(story as any); + edit.on('startEdit', msg => { + selectedCharacter = msg.actionInfo.character; + if (msg.type === 'commonEdit' && msg.actionInfo.character) { + msg.updateCharacter({ options: { graphic: { fill: 'green' } } }); + player.play(); + } + }); + edit.on('endEdit', msg => { + selectedCharacter = null; + }); + edit.on('resize', msg => { + // console.log('resize', msg); + }); + + return () => { + story.release(); + }; + }, []); + + return
; +};