mirror of
https://github.com/n8n-io/n8n.git
synced 2024-11-14 08:34:07 -08:00
fix(editor): Add touch event handlers to new canvas
This commit is contained in:
parent
679fa4a10a
commit
e2f0d2a553
|
@ -18,7 +18,17 @@ import { Background } from '@vue-flow/background';
|
||||||
import { MiniMap } from '@vue-flow/minimap';
|
import { MiniMap } from '@vue-flow/minimap';
|
||||||
import Node from './elements/nodes/CanvasNode.vue';
|
import Node from './elements/nodes/CanvasNode.vue';
|
||||||
import Edge from './elements/edges/CanvasEdge.vue';
|
import Edge from './elements/edges/CanvasEdge.vue';
|
||||||
import { computed, onMounted, onUnmounted, provide, ref, toRef, useCssModule, watch } from 'vue';
|
import {
|
||||||
|
computed,
|
||||||
|
onBeforeUnmount,
|
||||||
|
onMounted,
|
||||||
|
onUnmounted,
|
||||||
|
provide,
|
||||||
|
ref,
|
||||||
|
toRef,
|
||||||
|
useCssModule,
|
||||||
|
watch,
|
||||||
|
} from 'vue';
|
||||||
import type { EventBus } from 'n8n-design-system';
|
import type { EventBus } from 'n8n-design-system';
|
||||||
import { createEventBus } from 'n8n-design-system';
|
import { createEventBus } from 'n8n-design-system';
|
||||||
import { useContextMenu, type ContextMenuAction } from '@/composables/useContextMenu';
|
import { useContextMenu, type ContextMenuAction } from '@/composables/useContextMenu';
|
||||||
|
@ -33,6 +43,7 @@ import { onKeyDown, onKeyUp, useDebounceFn } from '@vueuse/core';
|
||||||
import CanvasArrowHeadMarker from './elements/edges/CanvasArrowHeadMarker.vue';
|
import CanvasArrowHeadMarker from './elements/edges/CanvasArrowHeadMarker.vue';
|
||||||
import { CanvasNodeRenderType } from '@/types';
|
import { CanvasNodeRenderType } from '@/types';
|
||||||
import CanvasBackgroundStripedPattern from './elements/CanvasBackgroundStripedPattern.vue';
|
import CanvasBackgroundStripedPattern from './elements/CanvasBackgroundStripedPattern.vue';
|
||||||
|
import { useTouchEventsInVueFlow } from '@/composables/useTouchEventsInVueFlow';
|
||||||
|
|
||||||
const $style = useCssModule();
|
const $style = useCssModule();
|
||||||
|
|
||||||
|
@ -95,6 +106,7 @@ const props = withDefaults(
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const vueFlowStore = useVueFlow({ id: props.id, deleteKeyCode: null });
|
||||||
const {
|
const {
|
||||||
getSelectedNodes: selectedNodes,
|
getSelectedNodes: selectedNodes,
|
||||||
addSelectedNodes,
|
addSelectedNodes,
|
||||||
|
@ -112,9 +124,11 @@ const {
|
||||||
findNode,
|
findNode,
|
||||||
onNodesInitialized,
|
onNodesInitialized,
|
||||||
viewport,
|
viewport,
|
||||||
} = useVueFlow({ id: props.id, deleteKeyCode: null });
|
onInit,
|
||||||
|
} = vueFlowStore;
|
||||||
|
|
||||||
const isPaneReady = ref(false);
|
const isPaneReady = ref(false);
|
||||||
|
const { addTouchListeners, removeTouchListeners } = useTouchEventsInVueFlow(vueFlowStore);
|
||||||
|
|
||||||
const classes = computed(() => ({
|
const classes = computed(() => ({
|
||||||
[$style.canvas]: true,
|
[$style.canvas]: true,
|
||||||
|
@ -488,6 +502,14 @@ onNodesInitialized((nodes) => {
|
||||||
void onFitView();
|
void onFitView();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
onInit(() => {
|
||||||
|
addTouchListeners();
|
||||||
|
});
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
removeTouchListeners();
|
||||||
|
});
|
||||||
|
|
||||||
watch(() => props.readOnly, setReadonly, {
|
watch(() => props.readOnly, setReadonly, {
|
||||||
immediate: true,
|
immediate: true,
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import type { VueFlowStore } from '@vue-flow/core';
|
||||||
|
|
||||||
|
export const useTouchEventsInVueFlow = (vueFlowStore: VueFlowStore) => {
|
||||||
|
const isPanning = ref(false);
|
||||||
|
const startX = ref(0);
|
||||||
|
const startY = ref(0);
|
||||||
|
|
||||||
|
const handleTouchStart = (event: TouchEvent) => {
|
||||||
|
const touch = event.touches[0];
|
||||||
|
startX.value = touch.clientX;
|
||||||
|
startY.value = touch.clientY;
|
||||||
|
|
||||||
|
if (event.touches.length > 1) {
|
||||||
|
isPanning.value = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleTouchMove = (event: TouchEvent) => {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
if (isPanning.value && vueFlowStore.vueFlowRef.value) {
|
||||||
|
const touch = event.touches[0];
|
||||||
|
const x = touch.clientX - startX.value;
|
||||||
|
const y = touch.clientY - startY.value;
|
||||||
|
|
||||||
|
vueFlowStore.panBy({ x, y });
|
||||||
|
|
||||||
|
startX.value = touch.clientX;
|
||||||
|
startY.value = touch.clientY;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleTouchEnd = () => {
|
||||||
|
isPanning.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const addTouchListeners = () => {
|
||||||
|
const canvas = vueFlowStore.vueFlowRef.value;
|
||||||
|
if (canvas) {
|
||||||
|
canvas.addEventListener('touchstart', handleTouchStart);
|
||||||
|
canvas.addEventListener('touchmove', handleTouchMove);
|
||||||
|
canvas.addEventListener('touchend', handleTouchEnd);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const removeTouchListeners = () => {
|
||||||
|
const canvas = vueFlowStore.vueFlowRef.value;
|
||||||
|
if (canvas) {
|
||||||
|
canvas.removeEventListener('touchstart', handleTouchStart);
|
||||||
|
canvas.removeEventListener('touchmove', handleTouchMove);
|
||||||
|
canvas.removeEventListener('touchend', handleTouchEnd);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
addTouchListeners,
|
||||||
|
removeTouchListeners,
|
||||||
|
};
|
||||||
|
};
|
Loading…
Reference in a new issue