Improve zooming (#1903)

* implement import

* set name, remove console log

* add validation and such

* remove monday.com package for testing

* clean up code

* await new name

* refactor api requests

* remove unnessary import

* build

* add zoom button

* update positions on loading template

* update error handling

* build

* update zoom to center

* set state to dirty upon leaving

* clean up pr

* refactor func

* refactor redir

* fix lint issue

* refactor func out

* use new endpoint

* revert error changes

* revert error changes

* update logic to find top left node

* zoom to fit when opening workflow

* revert testing change

* update zoom buttons to focus on origin

* update zoom shortcut

* update shortcuts

* update case

* remove debounce

* add secondary mappings

* fix reset

* add semicolon

* split func

* address comments

* refactor out

* refactor out

* reset zoom when opening new workflow

* move interface to common file

* remove duplicate

* fix import sort

* clean up pr

* clean up pr

*  Ignore keyboard shortcuts in select fields

Co-authored-by: Jan Oberhauser <jan.oberhauser@gmail.com>
This commit is contained in:
Mutasem Aldmour 2021-06-23 13:49:34 +03:00 committed by GitHub
parent 427f25d3d0
commit 69a013d719
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 84 additions and 23 deletions

View file

@ -611,3 +611,8 @@ export interface IRestApiContext {
baseUrl: string; baseUrl: string;
sessionId: string; sessionId: string;
} }
export interface IZoomConfig {
scale: number;
offset: XYPositon;
}

View file

@ -42,15 +42,15 @@
<button @click="zoomToFit" class="button-white" title="Zoom to Fit"> <button @click="zoomToFit" class="button-white" title="Zoom to Fit">
<font-awesome-icon icon="expand"/> <font-awesome-icon icon="expand"/>
</button> </button>
<button @click="setZoom('in')" class="button-white" title="Zoom In"> <button @click="zoomIn()" class="button-white" title="Zoom In">
<font-awesome-icon icon="search-plus"/> <font-awesome-icon icon="search-plus"/>
</button> </button>
<button @click="setZoom('out')" class="button-white" title="Zoom Out"> <button @click="zoomOut()" class="button-white" title="Zoom Out">
<font-awesome-icon icon="search-minus"/> <font-awesome-icon icon="search-minus"/>
</button> </button>
<button <button
v-if="nodeViewScale !== 1" v-if="nodeViewScale !== 1"
@click="setZoom('reset')" @click="resetZoom()"
class="button-white" class="button-white"
title="Reset Zoom" title="Reset Zoom"
> >
@ -136,7 +136,7 @@ import NodeCreator from '@/components/NodeCreator/NodeCreator.vue';
import NodeSettings from '@/components/NodeSettings.vue'; import NodeSettings from '@/components/NodeSettings.vue';
import RunData from '@/components/RunData.vue'; import RunData from '@/components/RunData.vue';
import { getLeftmostTopNode, getWorkflowCorners } from './helpers'; import { getLeftmostTopNode, getWorkflowCorners, scaleSmaller, scaleBigger, scaleReset } from './helpers';
import mixins from 'vue-typed-mixins'; import mixins from 'vue-typed-mixins';
import { v4 as uuidv4} from 'uuid'; import { v4 as uuidv4} from 'uuid';
@ -486,9 +486,9 @@ export default mixins(
//* Control + scroll zoom //* Control + scroll zoom
if (e.ctrlKey) { if (e.ctrlKey) {
if (e.deltaY > 0) { if (e.deltaY > 0) {
this.setZoom('out'); this.zoomOut();
} else { } else {
this.setZoom('in'); this.zoomIn();
} }
e.preventDefault(); e.preventDefault();
@ -509,7 +509,9 @@ export default mixins(
// else which should ignore the default keybindings // else which should ignore the default keybindings
for (let index = 0; index < path.length; index++) { for (let index = 0; index < path.length; index++) {
if (path[index].className && typeof path[index].className === 'string' && ( if (path[index].className && typeof path[index].className === 'string' && (
path[index].className.includes('el-message-box') || path[index].className.includes('ignore-key-press') path[index].className.includes('el-message-box') ||
path[index].className.includes('el-select') ||
path[index].className.includes('ignore-key-press')
)) { )) {
return; return;
} }
@ -539,12 +541,14 @@ export default mixins(
if (lastSelectedNode !== null) { if (lastSelectedNode !== null) {
this.callDebounced('renameNodePrompt', 1500, lastSelectedNode.name); this.callDebounced('renameNodePrompt', 1500, lastSelectedNode.name);
} }
} else if (e.key === '+') { } else if ((e.key === '=' || e.key === '+') && !this.isCtrlKeyPressed(e)) {
this.callDebounced('setZoom', 300, 'in'); this.zoomIn();
} else if (e.key === '-') { } else if ((e.key === '_' || e.key === '-') && !this.isCtrlKeyPressed(e)) {
this.callDebounced('setZoom', 300, 'out'); this.zoomOut();
} else if ((e.key === '0') && (this.isCtrlKeyPressed(e) === true)) { } else if ((e.key === '0') && !this.isCtrlKeyPressed(e)) {
this.callDebounced('setZoom', 300, 'reset'); this.resetZoom();
} else if ((e.key === '1') && !this.isCtrlKeyPressed(e)) {
this.zoomToFit();
} else if ((e.key === 'a') && (this.isCtrlKeyPressed(e) === true)) { } else if ((e.key === 'a') && (this.isCtrlKeyPressed(e) === true)) {
// Select all nodes // Select all nodes
e.stopPropagation(); e.stopPropagation();
@ -778,16 +782,25 @@ export default mixins(
}); });
}, },
setZoom (zoom: string) { resetZoom () {
let scale = this.nodeViewScale; const { scale, offset } = scaleReset({scale: this.nodeViewScale, offset: this.$store.getters.getNodeViewOffsetPosition});
if (zoom === 'in') {
scale *= 1.25;
} else if (zoom === 'out') {
scale /= 1.25;
} else {
scale = 1;
}
this.setZoomLevel(scale); this.setZoomLevel(scale);
this.$store.commit('setNodeViewOffsetPosition', {newOffset: offset});
},
zoomIn() {
const { scale, offset: [xOffset, yOffset] } = scaleBigger({scale: this.nodeViewScale, offset: this.$store.getters.getNodeViewOffsetPosition});
this.setZoomLevel(scale);
this.$store.commit('setNodeViewOffsetPosition', {newOffset: [xOffset, yOffset]});
},
zoomOut() {
const { scale, offset: [xOffset, yOffset] } = scaleSmaller({scale: this.nodeViewScale, offset: this.$store.getters.getNodeViewOffsetPosition});
this.setZoomLevel(scale);
this.$store.commit('setNodeViewOffsetPosition', {newOffset: [xOffset, yOffset]});
}, },
setZoomLevel (zoomLevel: number) { setZoomLevel (zoomLevel: number) {

View file

@ -1,4 +1,4 @@
import { INodeUi } from "@/Interface"; import { INodeUi, IZoomConfig } from "@/Interface";
interface ICorners { interface ICorners {
minX: number; minX: number;
@ -40,3 +40,46 @@ export const getWorkflowCorners = (nodes: INodeUi[]): ICorners => {
maxY: nodes[0].position[1], maxY: nodes[0].position[1],
}); });
}; };
export const scaleSmaller = ({scale, offset: [xOffset, yOffset]}: IZoomConfig): IZoomConfig => {
scale /= 1.25;
xOffset /= 1.25;
yOffset /= 1.25;
xOffset += window.innerWidth / 10;
yOffset += window.innerHeight / 10;
return {
scale,
offset: [xOffset, yOffset],
};
};
export const scaleBigger = ({scale, offset: [xOffset, yOffset]}: IZoomConfig): IZoomConfig => {
scale *= 1.25;
xOffset -= window.innerWidth / 10;
yOffset -= window.innerHeight / 10;
xOffset *= 1.25;
yOffset *= 1.25;
return {
scale,
offset: [xOffset, yOffset],
};
};
export const scaleReset = (config: IZoomConfig): IZoomConfig => {
if (config.scale > 1) { // zoomed in
while (config.scale > 1) {
config = scaleSmaller(config);
}
}
else {
while (config.scale < 1) {
config = scaleBigger(config);
}
}
config.scale = 1;
return config;
};