Skip to content

Commit

Permalink
feat(core): workspace加入蒙层功能,已考虑layer,resize和loadjson的适配
Browse files Browse the repository at this point in the history
  • Loading branch information
momo2019 authored and Qiu-Jun committed Jul 12, 2024
1 parent 519f6d7 commit edc87d0
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 16 deletions.
16 changes: 14 additions & 2 deletions packages/core/plugin/LayerPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,24 @@ class LayerPlugin implements IPluginTempl {
constructor(public canvas: fabric.Canvas, public editor: IEditor) {}

_getWorkspace() {
return this.canvas.getObjects().find((item) => item.id === 'workspace');
const result: Record<'workspace' | 'coverMask', fabric.Object | null> = {
workspace: null,
coverMask: null,
};
this.canvas.getObjects().forEach((item) => {
if (item.id === 'workspace') {
result.workspace = item;
} else if (item.id === 'coverMask') {
result.coverMask = item;
}
});
return result;
}

_workspaceSendToBack() {
const workspace = this._getWorkspace();
workspace && workspace.sendToBack();
workspace.workspace && workspace.workspace.sendToBack();
workspace.coverMask && workspace.coverMask.bringToFront();
}

up() {
Expand Down
7 changes: 3 additions & 4 deletions packages/core/plugin/ResizePlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { fabric } from 'fabric';
import Editor from '../Editor';
import { throttle } from 'lodash-es';
import '../styles/resizePlugin.css';
import WorkspacePlugin from './WorkspacePlugin';

type IEditor = Editor;

Expand Down Expand Up @@ -203,10 +204,8 @@ class ResizePlugin implements IPluginTempl {
}

this.editor.setCenterFromObject(workspace);
workspace.clone((cloned: fabric.Rect) => {
this.canvas.clipPath = cloned;
this.canvas.requestRenderAll();
});
(this.editor.getPlugin('WorkspacePlugin') as WorkspacePlugin).setCoverMask(true);
(this.editor.getPlugin('WorkspacePlugin') as WorkspacePlugin).clipPath();
if (['left', 'right'].includes(type)) {
this.canvas.defaultCursor = 'ew-resize';
} else {
Expand Down
81 changes: 71 additions & 10 deletions packages/core/plugin/WorkspacePlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class WorkspacePlugin implements IPluginTempl {
workspaceEl!: HTMLElement;
workspace: null | fabric.Rect;
resizeObserver!: ResizeObserver;
coverMask: null | fabric.Rect = null;
option: any;
zoomRatio: number;
constructor(public canvas: fabric.Canvas, public editor: IEditor) {
Expand Down Expand Up @@ -148,6 +149,69 @@ class WorkspacePlugin implements IPluginTempl {
this.auto();
}

setCoverMask(hack = false) {
if (!this.coverMask || !this.workspace) {
return;
}
const center = this.canvas.getCenter();
const zoom = this.canvas.getZoom();
this.canvas.zoomToPoint(
new fabric.Point(center.left, center.top),
hack ? zoom - 0.0000001 : zoom // 比较hack的方法,判断为fabric内部的数据更新问题
);
if (zoom) {
const { workspaceEl } = this;
const width = workspaceEl.offsetWidth;
const height = workspaceEl.offsetHeight;
const cWidth = width / zoom;
const cHeight = height / zoom;
this.coverMask.width = cWidth;
this.coverMask.height = cHeight;
this.coverMask.left = (this.workspace.left || 0) + (this.workspace.width! - cWidth) / 2;
this.coverMask.top = (this.workspace.top || 0) + (this.workspace.height! - cHeight) / 2;
this.workspace.clone((clone: fabric.Rect) => {
clone.left = -clone.width! / 2;
clone.top = -clone.height! / 2;
clone.inverted = true;
this.coverMask!.objectCaching = false;
this.coverMask!.clipPath = clone;
this.canvas.requestRenderAll();
});
}
}

clipPath() {
if (this.coverMask) {
return;
}
// 超出画布不展示
this.workspace?.clone((cloned: fabric.Rect) => {
this.canvas.clipPath = cloned;
this.canvas.requestRenderAll();
});
}

maskEnable(needBindLoadJSON = true) {
const coverMask = new fabric.Rect({
fill: 'rgba(0,0,0,0.7)',
id: 'coverMask',
strokeWidth: 0,
});
coverMask.set('selectable', false);
coverMask.set('hasControls', false);
coverMask.set('evented', false);
coverMask.hoverCursor = 'default';
this.canvas.on('object:added', () => {
coverMask.bringToFront();
});
this.canvas.clipPath = undefined;
this.canvas.add(coverMask);
this.coverMask = coverMask;
this.setCoverMask();
// 适配模板和psd的loadjson,在加载完成后再入mask
needBindLoadJSON && this.editor.on('loadJson', () => this.maskEnable(false));
}

setZoomAuto(scale: number, cb?: (left?: number, top?: number) => void) {
const { workspaceEl } = this;
const width = workspaceEl.offsetWidth;
Expand All @@ -159,12 +223,8 @@ class WorkspacePlugin implements IPluginTempl {
this.canvas.zoomToPoint(new fabric.Point(center.left, center.top), scale);
if (!this.workspace) return;
this.setCenterFromObject(this.workspace);

// 超出画布不展示
this.workspace.clone((cloned: fabric.Rect) => {
this.canvas.clipPath = cloned;
this.canvas.requestRenderAll();
});
this.setCoverMask();
this.clipPath();
if (cb) cb(this.workspace.left, this.workspace.top);
}

Expand Down Expand Up @@ -212,14 +272,15 @@ class WorkspacePlugin implements IPluginTempl {
}

_bindWheel() {
this.canvas.on('mouse:wheel', function (this: fabric.Canvas, opt) {
this.canvas.on('mouse:wheel', (opt) => {
const delta = opt.e.deltaY;
let zoom = this.getZoom();
let zoom = this.canvas.getZoom();
zoom *= 0.999 ** delta;
if (zoom > 20) zoom = 20;
if (zoom < 0.01) zoom = 0.01;
const center = this.getCenter();
this.zoomToPoint(new fabric.Point(center.left, center.top), zoom);
const center = this.canvas.getCenter();
this.canvas.zoomToPoint(new fabric.Point(center.left, center.top), zoom);
this.setCoverMask();
opt.e.preventDefault();
opt.e.stopPropagation();
});
Expand Down
1 change: 1 addition & 0 deletions src/views/home/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@ onMounted(() => {
canvasEditor.use(ResizePlugin);
canvasEditor.use(LockPlugin);
canvasEditor.use(AddBaseTypePlugin);
canvasEditor.getPlugin('WorkspacePlugin').maskEnable();
state.show = true;
// 默认打开标尺
Expand Down

0 comments on commit edc87d0

Please sign in to comment.