feat(stage,editor): 增肌删除快捷按钮

This commit is contained in:
roymondchen 2023-03-02 16:47:20 +08:00
parent b4bee9eb82
commit c9bacb96cd
8 changed files with 152 additions and 83 deletions

View File

@ -1,6 +1,6 @@
import { computed } from 'vue';
import StageCore, { GuidesType, SortEventData, UpdateEventData } from '@tmagic/stage';
import StageCore, { GuidesType, RemoveEventData, SortEventData, UpdateEventData } from '@tmagic/stage';
import editorService from '../services/editor';
import uiService from '../services/ui';
@ -73,6 +73,14 @@ export const useStage = (stageOptions: StageOptions) => {
editorService.sort(ev.src, ev.dist);
});
stage.on('remove', (ev: RemoveEventData) => {
editorService.remove(
ev.data.map(({ el }) => ({
id: el.id,
})),
);
});
stage.on('select-parent', () => {
const parent = editorService.get('parent');
if (!parent) throw new Error('父节点为空');

View File

@ -39,6 +39,7 @@ import {
GetTargetElement,
IsContainer,
Point,
RemoveEventData,
SelectStatus,
StageDragStatus,
UpdateEventData,
@ -454,6 +455,14 @@ export default class ActionManager extends EventEmitter {
})
.on('select-parent', () => {
this.emit('select-parent');
})
.on('remove', () => {
const drTarget = this.dr.getTarget();
if (!drTarget) return;
const data: RemoveEventData = {
data: [{ el: drTarget }],
};
this.emit('remove', data);
});
this.multiDr

View File

@ -0,0 +1,109 @@
import { MoveableManagerInterface, Renderer } from 'moveable';
import { AbleActionEventType } from './types';
export default (handler: (type: AbleActionEventType) => void) => ({
name: 'actions',
props: {
selectParent: Boolean,
},
events: {},
render(moveable: MoveableManagerInterface<any, any>, React: Renderer) {
const rect = moveable.getRect();
const { pos2 } = moveable.state;
// use css for able
const editableViewer = moveable.useCSS(
'div',
`
{
position: absolute;
left: 0px;
top: 0px;
will-change: transform;
transform-origin: 0px 0px;
display: flex;
}
.moveable-button {
width: 20px;
height: 20px;
background: #4af;
border-radius: 4px;
appearance: none;
border: 0;
color: white;
font-size: 12px;
font-weight: bold;
margin-left: 2px;
position: relative;
}
.moveable-remove-button:before, .moveable-remove-button:after {
content: "";
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%) rotate(45deg);
width: 14px;
height: 2px;
background: #fff;
border-radius: 1px;
cursor: pointer;
}
.moveable-remove-button:after {
transform: translate(-50%, -50%) rotate(-45deg);
}
`,
);
// Add key (required)
// Add class prefix moveable-(required)
return React.createElement(
editableViewer,
{
className: 'moveable-editable',
style: {
transform: `translate(${pos2[0] - 48}px, ${pos2[1] - 28}px) rotate(${rect.rotation}deg) translate(10px)`,
},
},
[
React.createElement(
'button',
{
className: 'moveable-button',
title: '选中父组件',
onClick: () => {
handler(AbleActionEventType.SELECT_PARENT);
},
},
React.createElement(
'svg',
{
width: '20px',
height: '20px',
viewBox: '0 0 16 16',
fill: 'none',
xmlns: 'http://www.w3.org/2000/svg',
style: {
transform: 'rotate(90deg)',
position: 'absolute',
left: 0,
top: 0,
},
},
React.createElement('path', {
d: 'M13.0001 4V10H4.20718L5.85363 8.35355L5.14652 7.64645L2.64652 10.1464C2.45126 10.3417 2.45126 10.6583 2.64652 10.8536L5.14652 13.3536L5.85363 12.6464L4.20718 11H13.0001C13.5524 11 14.0001 10.5523 14.0001 10V4H13.0001Z',
fill: 'currentColor',
fillOpacity: '0.9',
}),
),
),
React.createElement('button', {
className: 'moveable-button moveable-remove-button',
title: '删除',
onClick: () => {
handler(AbleActionEventType.REMOVE);
},
}),
],
);
},
});

View File

@ -22,8 +22,8 @@ import { merge } from 'lodash-es';
import { MoveableOptions } from 'moveable';
import { GuidesType, Mode } from './const';
import selectParentAbles from './MoveableSelectParentAble';
import { GetRootContainer, MoveableOptionsManagerConfig } from './types';
import MoveableActionsAble from './MoveableActionsAble';
import { AbleActionEventType, GetRootContainer, MoveableOptionsManagerConfig } from './types';
import { getOffset } from './util';
/**
@ -173,10 +173,10 @@ export default class MoveableOptionsManager extends EventEmitter {
isDisplayInnerSnapDigit: true,
props: {
selectParent: true,
actions: true,
},
ables: [selectParentAbles(this.selectParentHandler.bind(this))],
ables: [MoveableActionsAble(this.actionHandler.bind(this))],
};
}
@ -208,8 +208,8 @@ export default class MoveableOptionsManager extends EventEmitter {
/**
* selectParentAbles的回调函数
*/
private selectParentHandler(): void {
this.emit('select-parent');
private actionHandler(type: AbleActionEventType): void {
this.emit(type);
}
/**

View File

@ -1,76 +0,0 @@
import { MoveableManagerInterface, Renderer } from 'moveable';
export default (selectParentHandler: () => void) => ({
name: 'selectParent',
props: {},
events: {},
render(moveable: MoveableManagerInterface<any, any>, React: Renderer) {
const rect = moveable.getRect();
const { pos2 } = moveable.state;
// use css for able
const editableViewer = moveable.useCSS(
'div',
`
{
position: absolute;
left: 0px;
top: 0px;
will-change: transform;
transform-origin: 0px 0px;
display: flex;
}
.moveable-button {
width: 20px;
height: 20px;
background: #4af;
border-radius: 4px;
appearance: none;
border: 0;
color: white;
font-size: 12px;
font-weight: bold;
}
`,
);
// Add key (required)
// Add class prefix moveable-(required)
return React.createElement(
editableViewer,
{
className: 'moveable-editable',
style: {
transform: `translate(${pos2[0] - 25}px, ${pos2[1] - 30}px) rotate(${rect.rotation}deg) translate(10px)`,
},
},
React.createElement(
'button',
{
className: 'moveable-button',
title: '选中父组件',
onClick: () => {
selectParentHandler();
},
},
React.createElement(
'svg',
{
width: '1em',
height: '1em',
viewBox: '0 0 16 16',
fill: 'none',
xmlns: 'http://www.w3.org/2000/svg',
style: {
transform: 'rotate(90deg)',
},
},
React.createElement('path', {
d: 'M13.0001 4V10H4.20718L5.85363 8.35355L5.14652 7.64645L2.64652 10.1464C2.45126 10.3417 2.45126 10.6583 2.64652 10.8536L5.14652 13.3536L5.85363 12.6464L4.20718 11H13.0001C13.5524 11 14.0001 10.5523 14.0001 10V4H13.0001Z',
fill: 'currentColor',
fillOpacity: '0.9',
}),
),
),
);
},
});

View File

@ -30,6 +30,7 @@ import {
GuidesEventData,
Point,
RemoveData,
RemoveEventData,
Runtime,
StageCoreConfig,
UpdateData,
@ -313,6 +314,9 @@ export default class StageCore extends EventEmitter {
})
.on('select-parent', () => {
this.emit('select-parent');
})
.on('remove', (data: RemoveEventData) => {
this.emit('remove', data);
});
}

View File

@ -63,6 +63,10 @@ export default class StageDragResize extends MoveableOptionsManager {
});
}
public getTarget() {
return this.target;
}
/**
* Dom节点上方
* absolute时

View File

@ -190,6 +190,12 @@ export interface UpdateEventData {
parentEl: HTMLElement | null;
}
export interface RemoveEventData {
data: {
el: HTMLElement;
}[];
}
export interface SortEventData {
src: Id;
dist: Id;
@ -244,3 +250,8 @@ export interface TargetShadowConfig {
updateDragEl?: UpdateDragEl;
idPrefix?: string;
}
export enum AbleActionEventType {
SELECT_PARENT = 'select-parent',
REMOVE = 'remove',
}