Skip to content

Commit

Permalink
feat: 拆解selector为插件
Browse files Browse the repository at this point in the history
  • Loading branch information
Yan Heng committed Aug 26, 2023
1 parent 6f4d3f5 commit 39715d8
Show file tree
Hide file tree
Showing 18 changed files with 281 additions and 73 deletions.
1 change: 1 addition & 0 deletions main/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@heroicons/vue": "^2.0.18",
"@pictode/core": "workspace:^0.0.1",
"@pictode/plugin-history": "workspace:^0.0.1",
"@pictode/plugin-selector": "workspace:^0.0.1",
"@pictode/tools": "workspace:^0.0.1",
"@pictode/utils": "workspace:^0.0.1",
"@pictode/vue-aide": "workspace:^0.0.1",
Expand Down
17 changes: 15 additions & 2 deletions main/src/hooks/usePictode.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
import { ref } from 'vue';
import { App, KonvaNode } from '@pictode/core';
import { HistoryPlugin } from '@pictode/plugin-history';
import HistoryPlugin from '@pictode/plugin-history';
import SelectorPlugin from '@pictode/plugin-selector';

import { FormConfig, FormValue } from '@/form';
import { getPanelConfigByShape, getPanelConfigByTool } from '@/panels';

const app = new App();
app.use(new HistoryPlugin());

const historyPlugin = new HistoryPlugin({
enable: true,
stackSize: 50,
});

const selectorPlugin = new SelectorPlugin({
enable: true,
multipleSelect: true,
});

app.use(historyPlugin);
app.use(selectorPlugin);

const selected = ref<Array<KonvaNode>>([]);
const panelFormConfig = ref<FormConfig>([]);
Expand Down
4 changes: 2 additions & 2 deletions main/src/view/canvas/components/Tools.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ interface ToolInfo {
const selectTool = new SelectTool({
hooks: {
onActive(app) {
app.triggerSelector(true);
app.getPlugin('selectorPlugin')?.enable?.();
},
onInactive(app) {
app.triggerSelector(false);
app.getPlugin('selectorPlugin')?.disable?.();
},
},
});
Expand Down
49 changes: 10 additions & 39 deletions packages/core/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ import Konva from 'konva';
import './polyfill';

import { Mouse } from './services/mouse';
import { Selector } from './services/selector';
import { Tooler } from './services/tooler';
import { EventArgs, KonvaMouseEvent, KonvaNode, Plugin, Tool } from './types';
import { EventArgs, KonvaNode, Plugin, Tool } from './types';
import { guid, Point } from './utils';

export class App extends BaseService<EventArgs> {
Expand All @@ -15,7 +14,6 @@ export class App extends BaseService<EventArgs> {
public containerElement: HTMLDivElement;

private mouse: Mouse;
private selector: Selector;
private tooler: Tooler;
private installedPlugins: Map<string, Plugin> = new Map();
private resizeObserver: ResizeObserver;
Expand All @@ -40,7 +38,6 @@ export class App extends BaseService<EventArgs> {
this.mainLayer.name('pictode:main:layer');
this.stage.add(this.mainLayer);

this.selector = new Selector(this);
this.tooler = new Tooler(this);
this.mouse = new Mouse(this);
this.resizeObserver = new ResizeObserver(this.onContainerResize);
Expand All @@ -58,10 +55,6 @@ export class App extends BaseService<EventArgs> {
return new Point(x, y);
}

public get selected(): KonvaNode[] {
return [...this.selector.selected.values()];
}

public get curTool(): Tool | null {
return this.tooler.currentTool;
}
Expand Down Expand Up @@ -102,7 +95,7 @@ export class App extends BaseService<EventArgs> {
}

public _remove(...nodes: KonvaNode[]): void {
this.cancelSelect(...nodes);
// this.cancelSelect(...nodes);
nodes.forEach((node) => {
node.remove();
});
Expand Down Expand Up @@ -135,29 +128,8 @@ export class App extends BaseService<EventArgs> {
return this.getNodes((node) => node.id() === id)?.[0];
}

public getNodes(selector: (node: KonvaNode) => boolean): KonvaNode[] {
return this.mainLayer.find(selector) ?? [];
}

public triggerSelector(enable?: boolean): void {
this.cancelSelect();
this.selector.triggerSelector(enable);
}

public select(...nodes: KonvaNode[]): void {
this.selector.select(...nodes);
}

public selectByEvent(event: KonvaMouseEvent): void {
if (event.target instanceof Konva.Stage) {
this.cancelSelect();
} else {
this.select(event.target);
}
}

public cancelSelect(...nodes: KonvaNode[]): void {
this.selector.cancelSelect(...nodes);
public getNodes(callback: (node: KonvaNode) => boolean): KonvaNode[] {
return this.mainLayer.find(callback) ?? [];
}

public isPointInArea(point: Point, area: { width: number; height: number; x: number; y: number }): boolean {
Expand Down Expand Up @@ -204,8 +176,8 @@ export class App extends BaseService<EventArgs> {

public clear(): void {
this.mainLayer.removeChildren();
this.selector.destroy();
this.selector = new Selector(this);
// this.selector.destroy();
// this.selector = new Selector(this);
this.render();
}

Expand All @@ -219,10 +191,10 @@ export class App extends BaseService<EventArgs> {
const { padding = 10, pixelRatio = 2, mimeType = 'image/png', quality = 1, haveBackground = false } = config ?? {};
let clientRect = this.mainLayer.getClientRect();
let objects = this.mainLayer.children?.map((object) => object.toObject());
if (this.selected.length > 0) {
clientRect = this.selector.getSelectClientRect();
objects = this.selected.map((object) => object.toObject());
}
// if (this.selected.length > 0) {
// clientRect = this.selector.getSelectClientRect();
// objects = this.selected.map((object) => object.toObject());
// }
const width = clientRect.width + padding * 2;
const height = clientRect.height + padding * 2;
const x = clientRect.x - padding;
Expand Down Expand Up @@ -337,7 +309,6 @@ export class App extends BaseService<EventArgs> {
this.resizeObserver.disconnect();
this.destroyPlugins(Array.from(this.installedPlugins.keys()));
this.mouse.destroy();
this.selector.destroy();
this.tooler.destroy();
this.stage.destroy();
this.removeAllListeners();
Expand Down
3 changes: 0 additions & 3 deletions packages/core/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,6 @@ export interface EventArgs {
'canvas:rendered': {
time: number;
};
'selected:changed': {
selected: KonvaNode[];
};
'node:added': {
nodes: KonvaNode[];
};
Expand Down
12 changes: 6 additions & 6 deletions packages/plugin-history/src/history.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ import { Options } from './types';
export class History {
public name: string = 'history';
public app: App;
public enabled: boolean;
public enable: boolean;
public stackSize: number;

private undoStack: BaseCmd[] = [];
private redoStack: BaseCmd[] = [];
private idCounter: number = 0;

constructor(app: App, options?: Options) {
const { enabled = true, stackSize = 500 } = options ?? {};
const { enable = true, stackSize = 500 } = options ?? {};
this.app = app;
this.enabled = enabled;
this.enable = enable;
this.stackSize = stackSize;
}

Expand All @@ -44,7 +44,7 @@ export class History {
}

public undo(step: number = 1): BaseCmd | undefined {
if (!this.enabled) {
if (!this.enable) {
return;
}

Expand Down Expand Up @@ -72,7 +72,7 @@ export class History {
}

public redo(step: number = 1): BaseCmd | undefined {
if (!this.enabled) {
if (!this.enable) {
return;
}
let command: BaseCmd | undefined;
Expand Down Expand Up @@ -106,7 +106,7 @@ export class History {
}

public jump(id: number): void {
if (!this.enabled) {
if (!this.enable) {
return;
}

Expand Down
6 changes: 3 additions & 3 deletions packages/plugin-history/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,18 @@ export class HistoryPlugin implements Plugin {
if (!this.history) {
return;
}
this.history.enabled = true;
this.history.enable = true;
}

public disable(): void {
if (!this.history) {
return;
}
this.history.enabled = false;
this.history.enable = false;
}

public isEnabled(): boolean {
return this.history?.enabled ?? false;
return this.history?.enable ?? false;
}

private onNodeAdded = ({ nodes }: EventArgs['node:added']) => {
Expand Down
2 changes: 1 addition & 1 deletion packages/plugin-history/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export namespace Cmd {
}

export interface Options {
enabled?: boolean;
enable?: boolean;
stackSize?: number;
}

Expand Down
30 changes: 30 additions & 0 deletions packages/plugin-selector/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "@pictode/plugin-selector",
"private": true,
"version": "0.0.1",
"main": "dist/pictode-plugin-selector.umd.js",
"module": "dist/pictode-plugin-selector.mjs",
"types": "types/index.d.ts",
"exports": {
".": {
"import": "./dist/pictode-plugin-selector.mjs",
"require": "./dist/pictode-plugin-selector.umd.js"
}
},
"scripts": {
"build": "npm run build:type && vite build",
"build:type": "npm run clear:type && tsc --declaration --emitDeclarationOnly --project tsconfig.build.json",
"clear:type": "rimraf ./types"
},
"dependencies": {
"@pictode/core": "workspace:^0.0.1",
"@pictode/utils": "workspace:^0.0.1",
"dot": "2.0.0-beta.1",
"rimraf": "^3.0.2",
"roughjs": "^4.5.2"
},
"devDependencies": {
"typescript": "^4.9.3",
"vite": "^4.1.0"
}
}
50 changes: 50 additions & 0 deletions packages/plugin-selector/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { App, Plugin } from '@pictode/core';

import './methods';

import Selector from './selector';
import { Options } from './types';

export class SelectorPlugin implements Plugin {
public name: string = 'selectorPlugin';
public selector?: Selector;
public app?: App;
public options?: Options;

constructor(options?: Options) {
this.options = options;
}

public install(app: App) {
this.app = app;
this.selector = new Selector(app, this.options);
this.selector.app = app;
this.app.emit('selector:installed', { selector: this });
}

public destroy(): void {
this.selector?.destroy();
this.app?.emit('selector:destroy', { selector: this });
}

public enable(): void {
if (!this.selector) {
return;
}
this.selector.triggerSelector(true);
}

public disable(): void {
if (!this.selector) {
return;
}
this.selector.cancelSelect();
this.selector.triggerSelector(false);
}

public isEnabled(): boolean {
return this.selector?.enable ?? false;
}
}

export default SelectorPlugin;
41 changes: 41 additions & 0 deletions packages/plugin-selector/src/methods.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { App, Konva, KonvaMouseEvent, KonvaNode } from '@pictode/core';

import { SelectorPlugin } from './index';

Object.defineProperty(App.prototype, 'selected', {
get() {
const selectorPlugin = this.getPlugin('selectorPlugin') as SelectorPlugin;
if (selectorPlugin) {
return [...(selectorPlugin.selector?.selected.values() ?? [])];
}
return [];
},
});

App.prototype.select = function (...nodes: KonvaNode[]): App {
const selectorPlugin = this.getPlugin('selectorPlugin') as SelectorPlugin;
if (selectorPlugin) {
selectorPlugin.selector?.select(...nodes);
}
return this;
};

App.prototype.cancelSelect = function (...nodes: KonvaNode[]): App {
const selectorPlugin = this.getPlugin('selectorPlugin') as SelectorPlugin;
if (selectorPlugin) {
selectorPlugin.selector?.cancelSelect(...nodes);
}
return this;
};

App.prototype.selectByEvent = function (event: KonvaMouseEvent): App {
const selectorPlugin = this.getPlugin('selectorPlugin') as SelectorPlugin;
if (selectorPlugin) {
if (event.target instanceof Konva.Stage) {
this.cancelSelect();
} else {
this.select(event.target);
}
}
return this;
};
Loading

0 comments on commit 39715d8

Please sign in to comment.