Skip to content

Commit

Permalink
Merge pull request #353 from clayzenx/zoom-key
Browse files Browse the repository at this point in the history
change zoom key
  • Loading branch information
rpiontik authored Aug 11, 2023
2 parents c9f10d7 + 6aa3e57 commit 58610ad
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 80 deletions.
15 changes: 11 additions & 4 deletions src/frontend/components/Schema/DHSchema/DHSchema.vue
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
<template>
<svg
<svg
ref="zoomAndPan"
class="dochub-schema"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
contentstyletype="text/css"
preserveAspectRatio="none"
version="1.1"
v-bind:viewBox="viewBox"
zoomAndPan="magnify"
encoding="UTF-8"
stroke="transparent"
v-bind:style="style"
v-on:mousedown="onClickSpace">
v-on:wheel="zoomAndPanWheelHandler"
v-on:mousedown.prevent="(e) => zoomAndPanMouseDown(e) && onClickSpace(e)"
v-on:mousemove.prevent="zoomAndPanMouseMove"
v-on:mouseup.prevent="zoomAndPanMouseUp"
v-on:mouseleave.prevent="zoomAndPanMouseUp">
<template v-if="isFirefox">
<g class="symbols">
<g v-for="symbol in symbols" v-bind:id="symbol.id" v-bind:key="symbol.id" v-html="symbol.content" />
Expand Down Expand Up @@ -97,6 +101,8 @@
import SchemaTrack from './DHSchemaTrack.vue';
import SchemaDebugNode from './DHSchemaDebugNode.vue';
import ZoomAndPan from '@front/mixins/zoomAndPan';
// require(process.env.VUE_APP_DOCHUB_SMART_ANTS_SOURCE);
Expand Down Expand Up @@ -157,7 +163,7 @@
SchemaInfo,
SchemaDebugNode
},
mixins: [ DHSchemaAnimationMixin, DHSchemaExcalidrawMixin],
mixins: [ DHSchemaAnimationMixin, DHSchemaExcalidrawMixin, ZoomAndPan],
props: {
// Дистанция между объектами на диаграмме
distance: {
Expand Down Expand Up @@ -409,6 +415,7 @@
},
// Обработка клика на свободной области
onClickSpace(event) {
if(event.shiftKey) return;
event = event || window.event;
if (event.which === 1) {
this.cleanSelectedTracks();
Expand Down
99 changes: 23 additions & 76 deletions src/frontend/components/Schema/PlantUML.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,11 @@
v-else-if="render"
class="plantuml-schema"
v-bind:style="{cursor: cursor}"
v-on:mousedown.prevent="onMouseDown"
v-on:mousemove.prevent="onMouseMove"
v-on:mouseup.prevent="onMouseUp"
v-on:mouseleave.prevent="onMouseUp"
v-on:wheel="proxyScrollEvent"
v-on:mousedown.prevent="zoomAndPanMouseDown"
v-on:mousemove.prevent="zoomAndPanMouseMove"
v-on:mouseup.prevent="zoomAndPanMouseUp"
v-on:mouseleave.prevent="zoomAndPanMouseUp"
v-on:wheel="zoomAndPanWheelHandler"
v-html="svg" />
</error-boundary>
<v-menu
Expand Down Expand Up @@ -57,13 +57,16 @@
import copyToClipboard from '@front/helpers/clipboard';
import download from '@front/helpers/download';
import ZoomAndPan from '@front/mixins/zoomAndPan';
const EVENT_COPY_SOURCE_TO_CLIPBOARD = 'copysource';
export default {
name: 'PlantUML',
components: {
ErrorBoundary
},
mixins: [ZoomAndPan],
props: {
uml: { type: String, default: '' }, // PlantUML диаграмма
// eslint-disable-next-line @typescript-eslint/no-empty-function
Expand Down Expand Up @@ -93,31 +96,12 @@
rerenderTimer: null,
svg: '',
isLoading: true,
svgEl: null,
isShiftSens: false, // Признак, что пользователь нажал шифт
isMove: false, // Признак перемещения схемы
moveX: 0,
moveY: 0,
zoom: {
value: 1, // Текущий зум
step: 0.1 // Шаг зума
},
cacheViewBox: null
svgEl: null
};
},
computed: {
menuItems() {
const result = [].concat(this.contextMenu);
result.length && result.push(null);
if (!this.error) {
result.push(
{ id:'save-svg', title: 'Сохранить на диск SVG', on: () => download.downloadSVG(this.svg)}
);
result.push(
{ id: 'save-png', title: 'Сохранить на диск PNG', on: () => download.downloadSVGAsPNG(this.svg) }
);
}
return result.concat(this.menu.items);
zoomAndPanElement() {
return this.svgEl;
},
viewBox() {
if (!this.svgEl) {
Expand All @@ -133,13 +117,18 @@
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
: this.cacheViewBox = this.svgEl.viewBox.baseVal;
},
// Коэффициент преобразования реальных точек во внутренние по ширине
koofScreenX() {
return this.svgEl ? this.viewBox.width / this.svgEl.clientWidth : 1;
},
// Коэффициент преобразования реальных точек во внутренние по высоте
koofScreenY() {
return this.svgEl ? this.viewBox.height / this.svgEl.clientHeight : 1;
menuItems() {
const result = [].concat(this.contextMenu);
result.length && result.push(null);
if (!this.error) {
result.push(
{ id:'save-svg', title: 'Сохранить на диск SVG', on: () => download.downloadSVG(this.svg)}
);
result.push(
{ id: 'save-png', title: 'Сохранить на диск PNG', on: () => download.downloadSVGAsPNG(this.svg) }
);
}
return result.concat(this.menu.items);
},
cursor() {
return this.isShiftSens ? 'move' : undefined;
Expand Down Expand Up @@ -177,47 +166,6 @@
});
}, 300);
},
onMouseDown(event) {
if (!event.shiftKey) return;
this.isMove = true;
this.moveX = event.clientX;
this.moveY = event.clientY;
},
onMouseMove(event) {
this.isShiftSens = event.shiftKey;
if (!this.isMove) return;
this.viewBox.x += (this.moveX - event.clientX) * (this.koofScreenX || 0);
this.viewBox.y += (this.moveY - event.clientY) * (this.koofScreenY || 0);
this.moveX = event.clientX;
this.moveY = event.clientY;
},
onMouseUp() {
this.isMove = false;
},
doZoom(value, x, y) {
const kX = x / (this.svgEl.clientWidth || x);
const kY = y / (this.svgEl.clientHeight || y);
let resizeWidth = value * this.viewBox.width;
let resizeHeight = value * this.viewBox.height;
this.viewBox.x -= resizeWidth * kX;
this.viewBox.width += resizeWidth;
this.viewBox.y -= resizeHeight * kY;
this.viewBox.height += resizeHeight;
this.cacheViewBox = null;
},
proxyScrollEvent(event) {
if (!event.shiftKey) return;
let e = window.event || event;
switch (Math.max(-1, Math.min(1, (e.deltaY || -e.detail)))) {
case 1:
this.doZoom(this.zoom.step, event.offsetX, event.offsetY);
break;
case -1:
this.doZoom(-this.zoom.step, event.offsetX, event.offsetY);
break;
}
event.stopPropagation();
},
doResize() {
if (!this.svgEl || !this.svgEl.clientWidth || !this.svgEl.clientHeight) return;
Expand Down Expand Up @@ -253,7 +201,6 @@
},
reloadSVG() {
// Сбрасываем параметры зума
this.zoom.value = 1;
if (!this.uml) {
this.svg = '';
Expand Down
86 changes: 86 additions & 0 deletions src/frontend/mixins/zoomAndPan.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
export default {
data: () => ({
zoomAndPan: {
zoomKey: 'ctrlKey', // Кнопка для зума
panKey: 'shiftKey',
isMove: false, // Признак перемещения схемы
isShiftSens: false, // Признак, что пользователь нажал шифт
cacheViewBox: null,
moveX: 0,
moveY: 0,
zoom: {
value: 1, // Текущий зум
step: 0.1 // Шаг зума
}
}
}),
computed: {
koofScreenX() {
return this.zoomAndPanElement ? this.ZoomAndPanViewBox.width / this.zoomAndPanElement.clientWidth : 1;
},
// Коэффициент преобразования реальных точек во внутренние по высоте
koofScreenY() {
return this.zoomAndPanElement ? this.ZoomAndPanViewBox.height / this.zoomAndPanElement.clientHeight : 1;
},
ZoomAndPanViewBox() {
if (!this.zoomAndPanElement) {
return {
x: 0,
y : 0,
width : 0,
height : 0
};
} else
return this.zoomAndPan.cacheViewBox ?
this.zoomAndPan.cacheViewBox
// eslint-disable-next-line vue/no-side-effects-in-computed-properties
: this.zoomAndPan.cacheViewBox = this.zoomAndPanElement.viewBox.baseVal;
},
zoomAndPanElement() {
return this.$refs.zoomAndPan;
}
},
methods: {
doZoom(value, x, y) {
const kX = x / (this.zoomAndPanElement.clientWidth || x);
const kY = y / (this.zoomAndPanElement.clientHeight || y);
let resizeWidth = value * this.ZoomAndPanViewBox.width;
let resizeHeight = value * this.ZoomAndPanViewBox.height;
this.ZoomAndPanViewBox.x -= resizeWidth * kX;
this.ZoomAndPanViewBox.width += resizeWidth;
this.ZoomAndPanViewBox.y -= resizeHeight * kY;
this.ZoomAndPanViewBox.height += resizeHeight;
this.zoomAndPan.cacheViewBox = null;
},
zoomAndPanWheelHandler(event) {
if (!event[this.zoomAndPan.zoomKey]) return;
let e = window.event || event;
switch (Math.max(-1, Math.min(1, (e.deltaY || -e.detail)))) {
case 1:
this.doZoom(this.zoomAndPan.zoom.step, event.offsetX, event.offsetY);
break;
case -1:
this.doZoom(-this.zoomAndPan.zoom.step, event.offsetX, event.offsetY);
break;
}
event.stopPropagation();
},
zoomAndPanMouseDown(event) {
if (!event[this.zoomAndPan.panKey]) return;
this.zoomAndPan.isMove = true;
this.zoomAndPan.moveX = event.clientX;
this.zoomAndPan.moveY = event.clientY;
},
zoomAndPanMouseMove(event) {
this.zoomAndPan.isShiftSens = event[this.zoomAndPan.panKey];
if (!this.zoomAndPan.isMove) return;
this.ZoomAndPanViewBox.x += (this.zoomAndPan.moveX - event.clientX) * (this.koofScreenX || 0);
this.ZoomAndPanViewBox.y += (this.zoomAndPan.moveY - event.clientY) * (this.koofScreenY || 0);
this.zoomAndPan.moveX = event.clientX;
this.zoomAndPan.moveY = event.clientY;
},
zoomAndPanMouseUp() {
this.zoomAndPan.isMove = false;
}
}
};

0 comments on commit 58610ad

Please sign in to comment.