feat(editor): 去掉画布根据视窗大小自动调整缩放比例,加上缩放到实际大小/缩放以适应菜单按钮

This commit is contained in:
roymondchen 2022-08-25 16:23:56 +08:00 committed by jia000
parent 4872e5352b
commit dd3075be56
4 changed files with 54 additions and 27 deletions

View File

@ -2,7 +2,7 @@
<div
v-if="display"
class="menu-item"
:class="`${data.type} ${data.className}`"
:class="`${data.type} ${data.className || ''}`"
@click="clickHandler(data, $event)"
@mousedown="mousedownHandler(data, $event)"
@mouseup="mouseupHandler(data, $event)"

View File

@ -8,7 +8,7 @@
<script lang="ts" setup>
import { computed, inject, markRaw } from 'vue';
import { Back, Delete, Grid, Memo, Right, ZoomIn, ZoomOut } from '@element-plus/icons-vue';
import { Back, Delete, FullScreen, Grid, Memo, Right, ScaleToOriginal, ZoomIn, ZoomOut } from '@element-plus/icons-vue';
import { NodeType } from '@tmagic/schema';
@ -36,6 +36,9 @@ const showGuides = computed((): boolean => uiService?.get<boolean>('showGuides')
const showRule = computed((): boolean => uiService?.get<boolean>('showRule') ?? true);
const zoom = computed((): number => uiService?.get<number>('zoom') ?? 1);
const isMac = /mac os x/.test(navigator.userAgent.toLowerCase());
const ctrl = isMac ? 'Command' : 'Ctrl';
const getConfig = (item: MenuItem): (MenuButton | MenuComponent)[] => {
if (typeof item !== 'string') {
return [item];
@ -53,6 +56,8 @@ const getConfig = (item: MenuItem): (MenuButton | MenuComponent)[] => {
...getConfig('zoom-out'),
...getConfig(`${parseInt(`${zoom.value * 100}`, 10)}%`),
...getConfig('zoom-in'),
...getConfig('scale-to-original'),
...getConfig('scale-to-fit'),
);
break;
case 'delete':
@ -60,7 +65,7 @@ const getConfig = (item: MenuItem): (MenuButton | MenuComponent)[] => {
type: 'button',
className: 'delete',
icon: markRaw(Delete),
tooltip: '刪除',
tooltip: `刪除(Delete)`,
disabled: () => services?.editorService.get('node')?.type === NodeType.PAGE,
handler: () => services?.editorService.remove(services?.editorService.get('node')),
});
@ -70,7 +75,7 @@ const getConfig = (item: MenuItem): (MenuButton | MenuComponent)[] => {
type: 'button',
className: 'undo',
icon: markRaw(Back),
tooltip: '后退',
tooltip: `后退(${ctrl}+z)`,
disabled: () => !services?.historyService.state.canUndo,
handler: () => services?.editorService.undo(),
});
@ -80,7 +85,7 @@ const getConfig = (item: MenuItem): (MenuButton | MenuComponent)[] => {
type: 'button',
className: 'redo',
icon: markRaw(Right),
tooltip: '前进',
tooltip: `前进(${ctrl}+Shift+z)`,
disabled: () => !services?.historyService.state.canRedo,
handler: () => services?.editorService.redo(),
});
@ -90,7 +95,7 @@ const getConfig = (item: MenuItem): (MenuButton | MenuComponent)[] => {
type: 'button',
className: 'zoom-in',
icon: markRaw(ZoomIn),
tooltip: '放大',
tooltip: `放大(${ctrl}+=)`,
handler: () => uiService?.zoom(0.1),
});
break;
@ -99,10 +104,28 @@ const getConfig = (item: MenuItem): (MenuButton | MenuComponent)[] => {
type: 'button',
className: 'zoom-out',
icon: markRaw(ZoomOut),
tooltip: '縮小',
tooltip: `縮小(${ctrl}+-)`,
handler: () => uiService?.zoom(-0.1),
});
break;
case 'scale-to-original':
config.push({
type: 'button',
className: 'scale-to-original',
icon: markRaw(ScaleToOriginal),
tooltip: `缩放到实际大小(${ctrl}+1)`,
handler: () => uiService?.set('zoom', 1),
});
break;
case 'scale-to-fit':
config.push({
type: 'button',
className: 'scale-to-fit',
icon: markRaw(FullScreen),
tooltip: `缩放以适应(${ctrl}+0)`,
handler: () => uiService?.set('zoom', uiService.calcZoom()),
});
break;
case 'rule':
config.push({
type: 'button',

View File

@ -145,6 +145,14 @@ export default defineComponent({
.keydown([ctrl, 'numpad-'], (e) => {
e.inputEvent.preventDefault();
services?.uiService.zoom(-0.1);
})
.keydown([ctrl, '0'], (e) => {
e.inputEvent.preventDefault();
services?.uiService.set('zoom', services.uiService.calcZoom());
})
.keydown([ctrl, '1'], (e) => {
e.inputEvent.preventDefault();
services?.uiService.set('zoom', 1);
});
});

View File

@ -98,10 +98,6 @@ class Ui extends BaseService {
}
(state as any)[name] = value;
if (name === 'stageContainerRect') {
state.zoom = this.calcZoom();
}
}
public get<T>(name: keyof typeof state): T {
@ -113,6 +109,22 @@ class Ui extends BaseService {
if (this.get<number>('zoom') < 0.1) this.set('zoom', 0.1);
}
public calcZoom() {
const { stageRect, stageContainerRect } = state;
const { height, width } = stageContainerRect;
if (!width || !height) return 1;
// 30为标尺的大小
const stageWidth = stageRect.width + 30;
const stageHeight = stageRect.height + 30;
if (width > stageWidth && height > stageHeight) {
return 1;
}
// 60/80是为了不要让画布太过去贴住四周这样好看些
return Math.min((width - 60) / stageWidth || 1, (height - 80) / stageHeight || 1);
}
private setColumnWidth({ left, center, right }: SetColumnWidth) {
const columnWidth = {
...toRaw(this.get<GetColumnWidth>('columnWidth')),
@ -150,22 +162,6 @@ class Ui extends BaseService {
};
state.zoom = this.calcZoom();
}
private calcZoom() {
const { stageRect, stageContainerRect } = state;
const { height, width } = stageContainerRect;
if (!width || !height) return 1;
// 30为标尺的大小
const stageWidth = stageRect.width + 30;
const stageHeight = stageRect.height + 30;
if (width > stageWidth && height > stageHeight) {
return 1;
}
// 60/80是为了不要让画布太过去贴住四周这样好看些
return Math.min((width - 60) / stageWidth || 1, (height - 80) / stageHeight || 1);
}
}
export type UiService = Ui;