From 17e9a6242ef07edfae5f655855c7e05faca054d6 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Thu, 9 Jan 2025 15:01:43 +0800 Subject: [PATCH] feat: support image selection --- .../component/graphic/ImageComponent.ts | 4 +- packages/vstory-editor/src/register.ts | 3 +- .../src/selection/image-selection.ts | 53 +++++++++++++++++++ .../vstory/demo/src/demos/edit/components.tsx | 18 +++++++ 4 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 packages/vstory-editor/src/selection/image-selection.ts diff --git a/packages/vstory-core/src/character/component/graphic/ImageComponent.ts b/packages/vstory-core/src/character/component/graphic/ImageComponent.ts index f5632ee7..e84425eb 100644 --- a/packages/vstory-core/src/character/component/graphic/ImageComponent.ts +++ b/packages/vstory-core/src/character/component/graphic/ImageComponent.ts @@ -23,6 +23,8 @@ export class ImageComponent extends BaseComponentWithText { } }; + mainGraphic: IImage; + constructor(attributes: IImageComponentAttributes, options?: ComponentOptions) { super(options?.skipDefault ? attributes : merge({}, ImageComponent.defaultAttributes, attributes)); } @@ -47,7 +49,7 @@ export class ImageComponent extends BaseComponentWithText { if (!attrs.height) { attrs.height = height - padding.top - padding.bottom; } - this.createOrUpdateChild( + this.mainGraphic = this.createOrUpdateChild( 'image', { ...attrs, scaleX: 1, scaleY: 1, angle: 0, postMatrix: null }, 'image' diff --git a/packages/vstory-editor/src/register.ts b/packages/vstory-editor/src/register.ts index 33020089..9fdd5df9 100644 --- a/packages/vstory-editor/src/register.ts +++ b/packages/vstory-editor/src/register.ts @@ -3,6 +3,7 @@ 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'; +import { ImageSelection } from './selection/image-selection'; const editPlugin = new ContainerModule(bind => { bind(RichTextEditPlugin).toSelf(); @@ -15,7 +16,7 @@ export function registerAllSelection() { // Edit.registerEditSelection(CharacterType.TEXT, TextSelection); // Edit.registerEditSelection('richtext', RichTextSelection); Edit.registerEditSelection(CharacterType.RECT, RectSelection); - // Edit.registerEditSelection(CharacterType.IMAGE, ImageSelection); + Edit.registerEditSelection(CharacterType.IMAGE, ImageSelection); Edit.registerEditSelection(CharacterType.SHAPE, ShapeSelection); // Edit.registerEditSelection('chart', ChartSelection); // Edit.registerEditSelection('box-selection', BoxSelection); diff --git a/packages/vstory-editor/src/selection/image-selection.ts b/packages/vstory-editor/src/selection/image-selection.ts new file mode 100644 index 00000000..a3ce8ab0 --- /dev/null +++ b/packages/vstory-editor/src/selection/image-selection.ts @@ -0,0 +1,53 @@ +import { CharacterType } from '@visactor/vstory-core'; +import type { IEditActionInfo, IEditSelection } from '../interface'; +import { RichTextSelectionCommon } from './richtext-selection-common'; +import type { ITransformController } from './edit-control/transform-control'; + +export class ImageSelection extends RichTextSelectionCommon implements IEditSelection { + readonly level = 3; + readonly type: string = 'image'; + readonly editCharacterType: string = CharacterType.IMAGE; + readonly supportedCharacterType: string[] = [CharacterType.IMAGE]; + + 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(); + }; + + protected createLayoutController(): ITransformController | undefined { + const controller = super.createLayoutController(); + controller.proportionalScaling = true; + return controller; + } + + protected keyDown = (event: any) => { + if (!(this._layoutController && event)) { + return; + } + if (event.shiftKey || event.key === 'Shift') { + this._layoutController.defaultProportionalScaling = this._layoutController.proportionalScaling; + this._layoutController.proportionalScaling = false; + } + }; + protected keyUp = (event: any) => { + if (!(this._layoutController && event)) { + return; + } + if (event.shiftKey || event.key === 'Shift') { + this._layoutController.proportionalScaling = this._layoutController.defaultProportionalScaling; + } + }; +} diff --git a/packages/vstory/demo/src/demos/edit/components.tsx b/packages/vstory/demo/src/demos/edit/components.tsx index c66fb8c5..7e0d4363 100644 --- a/packages/vstory/demo/src/demos/edit/components.tsx +++ b/packages/vstory/demo/src/demos/edit/components.tsx @@ -45,6 +45,24 @@ export const ComponentsEdit = () => { } } }); + story.addCharacterWithAppear({ + type: 'Image', + id: 'image', + zIndex: 10, + position: { + top: 100, + left: 300, + width: 80, + height: 60 + }, + options: { + graphic: { + stroke: false, + image: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/vstory/screenshot-20240715-204217.png' + // size: 100 + } + } + }); story.addCharacterWithAppear({ type: 'Rect', id: 'title',