From 61669a6ee11faab48c1f07721a5375d49892383b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E8=B1=AA=E7=8F=A3?= <519367854@qq.com> Date: Sun, 31 Mar 2024 21:53:01 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0selection=E7=BB=84?= =?UTF-8?q?=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../widgets/aux-tool/aux-tool.widget.ts | 28 ++++- .../widgets/aux-tool/selection.widget.ts | 115 ++++++++++++++++++ .../component-tree/component-tree.widget.ts | 22 +++- 3 files changed, 159 insertions(+), 6 deletions(-) create mode 100644 src/app/components/widgets/aux-tool/selection.widget.ts diff --git a/src/app/components/widgets/aux-tool/aux-tool.widget.ts b/src/app/components/widgets/aux-tool/aux-tool.widget.ts index 5fd9d36..b299d0e 100644 --- a/src/app/components/widgets/aux-tool/aux-tool.widget.ts +++ b/src/app/components/widgets/aux-tool/aux-tool.widget.ts @@ -1,13 +1,35 @@ -import { ChangeDetectionStrategy, Component } from '@angular/core'; +import { AfterViewInit, ChangeDetectionStrategy, Component, ElementRef, ViewChild } from '@angular/core'; import { usePrefix } from '@/app/utils'; +import { Engine } from '@/app/core/models'; +import { SelectionWidget } from './selection.widget'; @Component({ selector: 'app-aux-tool-widget', - template: `
`, + template: ` +
+ +
+ `, styleUrls: ['./styles.less'], standalone: true, + imports: [SelectionWidget], changeDetection: ChangeDetectionStrategy.OnPush }) -export class AuxToolWidget { +export class AuxToolWidget implements AfterViewInit { prefix = usePrefix('auxtool'); + + @ViewChild('ref') ref: ElementRef; + + constructor(private engine: Engine) {} + + ngAfterViewInit(): void { + const element = this.ref.nativeElement; + const viewport = this.engine.workbench.currentWorkspace.viewport; + + this.engine.subscribeWith('viewport:scroll', () => { + if (viewport.isIframe && element) { + element.style.transform = `perspective(1px) translate3d(${-viewport.scrollX}px,${-viewport.scrollY}px,0)`; + } + }); + } } diff --git a/src/app/components/widgets/aux-tool/selection.widget.ts b/src/app/components/widgets/aux-tool/selection.widget.ts new file mode 100644 index 0000000..a6ff57c --- /dev/null +++ b/src/app/components/widgets/aux-tool/selection.widget.ts @@ -0,0 +1,115 @@ +import { + ChangeDetectionStrategy, + ChangeDetectorRef, + Component, + ElementRef, + Input, + OnChanges, + Renderer2, + SimpleChanges, + ViewChild +} from '@angular/core'; +import { usePrefix } from '@/app/utils'; +import { Engine, TreeNode } from '@/app/core/models'; +import { Selection } from '@/app/core/models/selection'; +import { Cursor } from '@/app/core/models/cursor'; +import { MoveHelper } from '@/app/core/models/move-helper'; +import { Rect } from '@/app/shared/coordinate'; + +@Component({ + selector: 'app-selection-box-widget', + template: ` +
+
+
+ `, + standalone: true, + styleUrls: [`./styles.less`], + changeDetection: ChangeDetectionStrategy.Default +}) +export class SelectionBoxWidget implements OnChanges { + @ViewChild('container') container: ElementRef; + + @Input() node: TreeNode; + + @Input() showHelpers: boolean; + + prefix = usePrefix('aux-selection-box'); + + innerPrefix = usePrefix('aux-selection-box-inner'); + + nodeRect: Rect; + + createSelectionStyle = () => { + const baseStyle = { + position: 'absolute', + top: 0, + left: 0, + boxSizing: 'border-box', + zIndex: 4 + } as any; + if (this.nodeRect) { + baseStyle.transform = `perspective(1px) translate3d(${this.nodeRect.x}px,${this.nodeRect.y}px,0)`; + baseStyle.height = `${this.nodeRect.height}px`; + baseStyle.width = `${this.nodeRect.width}px`; + } + return baseStyle; + }; + + constructor( + private designer: Engine, + private renderer2: Renderer2, + private cdr: ChangeDetectorRef + ) {} + + ngOnChanges(changes: SimpleChanges): void { + if (changes.node && changes.node.currentValue) { + setTimeout(() => { + this.nodeRect = this.designer.workbench.currentWorkspace.viewport.getValidNodeOffsetRect(this.node); + + this.renderer2.setAttribute( + this.container.nativeElement, + `${this.designer.props?.nodeSelectionIdAttrName}`, + this.node.id + ); + this.cdr.markForCheck(); + }); + } + } +} + +@Component({ + selector: 'app-selection-widget', + template: ` + @if (cursor.status === 'NORMAL' || !viewportMoveHelper.touchNode) { + @for (id of selection.selected; track id) { + @if (tree.findById(id) && !tree.findById(id).hidden) { + + } + } + } + `, + standalone: true, + imports: [SelectionBoxWidget], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class SelectionWidget { + selection: Selection; + + cursor: Cursor; + + viewportMoveHelper: MoveHelper; + + tree: TreeNode; + + constructor(private designer: Engine) { + const operation = this.designer.workbench.currentWorkspace.operation; + this.selection = operation.selection; + this.viewportMoveHelper = operation.moveHelper; + this.tree = operation.tree; + this.cursor = this.designer.cursor; + } +} diff --git a/src/app/components/widgets/component-tree/component-tree.widget.ts b/src/app/components/widgets/component-tree/component-tree.widget.ts index 63d6d34..25f9a3b 100644 --- a/src/app/components/widgets/component-tree/component-tree.widget.ts +++ b/src/app/components/widgets/component-tree/component-tree.widget.ts @@ -1,4 +1,14 @@ -import { AfterViewInit, ChangeDetectionStrategy, Component, Input, OnChanges, SimpleChanges } from '@angular/core'; +import { + AfterViewInit, + ChangeDetectionStrategy, + Component, + ElementRef, + Input, + OnChanges, + Renderer2, + SimpleChanges, + ViewChild +} from '@angular/core'; import { usePrefix } from '@/app/utils'; import { TreeNodeWidget } from '../tree-node/tree-node.widget'; import { IDesignerComponents } from '../../types'; @@ -9,7 +19,7 @@ import { Engine, TreeNode } from '@/app/core/models'; selector: 'app-component-tree-widget', standalone: true, template: ` -
+
`, @@ -18,6 +28,8 @@ import { Engine, TreeNode } from '@/app/core/models'; changeDetection: ChangeDetectionStrategy.OnPush }) export class ComponentTreeWidget implements OnChanges, AfterViewInit { + @ViewChild('container') container: ElementRef; + prefix = usePrefix('component-tree'); @Input() components: IDesignerComponents; @@ -28,7 +40,10 @@ export class ComponentTreeWidget implements OnChanges, AfterViewInit { displayName = 'ComponentTreeWidget'; - constructor(private designer: Engine) {} + constructor( + private designer: Engine, + private renderer2: Renderer2 + ) {} ngOnChanges(changes: SimpleChanges): void { if (changes.components && changes.components.currentValue) { @@ -38,6 +53,7 @@ export class ComponentTreeWidget implements OnChanges, AfterViewInit { ngAfterViewInit(): void { this.tree = this.useTree(); + this.renderer2.setAttribute(this.container.nativeElement, `${this.designer?.props?.nodeIdAttrName}`, this.tree.id); } registerDesignerBehaviors() {