mirror of
https://github.com/Tencent/tmagic-editor.git
synced 2025-06-04 15:19:18 +08:00
feat(editor): 去掉画布根据视窗大小自动调整缩放比例,加上缩放到实际大小/缩放以适应菜单按钮
This commit is contained in:
parent
4872e5352b
commit
dd3075be56
@ -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)"
|
||||||
|
@ -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',
|
||||||
|
@ -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);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user