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

View File

@ -8,7 +8,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import { computed, inject, markRaw } from 'vue'; 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'; 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 showRule = computed((): boolean => uiService?.get<boolean>('showRule') ?? true);
const zoom = computed((): number => uiService?.get<number>('zoom') ?? 1); 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)[] => { const getConfig = (item: MenuItem): (MenuButton | MenuComponent)[] => {
if (typeof item !== 'string') { if (typeof item !== 'string') {
return [item]; return [item];
@ -53,6 +56,8 @@ const getConfig = (item: MenuItem): (MenuButton | MenuComponent)[] => {
...getConfig('zoom-out'), ...getConfig('zoom-out'),
...getConfig(`${parseInt(`${zoom.value * 100}`, 10)}%`), ...getConfig(`${parseInt(`${zoom.value * 100}`, 10)}%`),
...getConfig('zoom-in'), ...getConfig('zoom-in'),
...getConfig('scale-to-original'),
...getConfig('scale-to-fit'),
); );
break; break;
case 'delete': case 'delete':
@ -60,7 +65,7 @@ const getConfig = (item: MenuItem): (MenuButton | MenuComponent)[] => {
type: 'button', type: 'button',
className: 'delete', className: 'delete',
icon: markRaw(Delete), icon: markRaw(Delete),
tooltip: '刪除', tooltip: `刪除(Delete)`,
disabled: () => services?.editorService.get('node')?.type === NodeType.PAGE, disabled: () => services?.editorService.get('node')?.type === NodeType.PAGE,
handler: () => services?.editorService.remove(services?.editorService.get('node')), handler: () => services?.editorService.remove(services?.editorService.get('node')),
}); });
@ -70,7 +75,7 @@ const getConfig = (item: MenuItem): (MenuButton | MenuComponent)[] => {
type: 'button', type: 'button',
className: 'undo', className: 'undo',
icon: markRaw(Back), icon: markRaw(Back),
tooltip: '后退', tooltip: `后退(${ctrl}+z)`,
disabled: () => !services?.historyService.state.canUndo, disabled: () => !services?.historyService.state.canUndo,
handler: () => services?.editorService.undo(), handler: () => services?.editorService.undo(),
}); });
@ -80,7 +85,7 @@ const getConfig = (item: MenuItem): (MenuButton | MenuComponent)[] => {
type: 'button', type: 'button',
className: 'redo', className: 'redo',
icon: markRaw(Right), icon: markRaw(Right),
tooltip: '前进', tooltip: `前进(${ctrl}+Shift+z)`,
disabled: () => !services?.historyService.state.canRedo, disabled: () => !services?.historyService.state.canRedo,
handler: () => services?.editorService.redo(), handler: () => services?.editorService.redo(),
}); });
@ -90,7 +95,7 @@ const getConfig = (item: MenuItem): (MenuButton | MenuComponent)[] => {
type: 'button', type: 'button',
className: 'zoom-in', className: 'zoom-in',
icon: markRaw(ZoomIn), icon: markRaw(ZoomIn),
tooltip: '放大', tooltip: `放大(${ctrl}+=)`,
handler: () => uiService?.zoom(0.1), handler: () => uiService?.zoom(0.1),
}); });
break; break;
@ -99,10 +104,28 @@ const getConfig = (item: MenuItem): (MenuButton | MenuComponent)[] => {
type: 'button', type: 'button',
className: 'zoom-out', className: 'zoom-out',
icon: markRaw(ZoomOut), icon: markRaw(ZoomOut),
tooltip: '縮小', tooltip: `縮小(${ctrl}+-)`,
handler: () => uiService?.zoom(-0.1), handler: () => uiService?.zoom(-0.1),
}); });
break; 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': case 'rule':
config.push({ config.push({
type: 'button', type: 'button',

View File

@ -145,6 +145,14 @@ export default defineComponent({
.keydown([ctrl, 'numpad-'], (e) => { .keydown([ctrl, 'numpad-'], (e) => {
e.inputEvent.preventDefault(); e.inputEvent.preventDefault();
services?.uiService.zoom(-0.1); 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; (state as any)[name] = value;
if (name === 'stageContainerRect') {
state.zoom = this.calcZoom();
}
} }
public get<T>(name: keyof typeof state): T { 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); 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) { private setColumnWidth({ left, center, right }: SetColumnWidth) {
const columnWidth = { const columnWidth = {
...toRaw(this.get<GetColumnWidth>('columnWidth')), ...toRaw(this.get<GetColumnWidth>('columnWidth')),
@ -150,22 +162,6 @@ class Ui extends BaseService {
}; };
state.zoom = this.calcZoom(); 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; export type UiService = Ui;