WIP: switch to vue-pinch-zoom

This commit is contained in:
mvdbeek
2023-01-09 17:15:46 +01:00
parent 770ec675bf
commit cd18ae9ef3
12 changed files with 129 additions and 120 deletions
+2
View File
@@ -23,6 +23,8 @@
},
"dependencies": {
"@fontsource/atkinson-hyperlegible": "^4.5.10",
"@braks/revue-draggable": "file:/Users/mvandenb/src/galaxy/revue-draggable/braks-revue-draggable-no-transform.tgz",
"@coddicat/vue-pinch-scroll-zoom": "^3.3.4",
"@fortawesome/fontawesome-free": "^5.15.4",
"@fortawesome/fontawesome-svg-core": "^6.2.1",
"@fortawesome/free-brands-svg-icons": "^5.15.4",
@@ -23,10 +23,6 @@ export default {
lineShift: 30,
};
},
beforeDestroy() {
console.log("Destroying connector");
// this.terminal.destroy();
},
computed: {
offsetStart() {
return 0;
@@ -343,7 +343,6 @@ export default {
}
},
steps(newSteps, oldSteps) {
console.log("steps watch triggered");
this.hasChanges = true;
this.nodeIndex = Math.max(...Object.keys(newSteps).map((k) => parseInt(k))) + 1;
},
@@ -363,11 +362,9 @@ export default {
},
methods: {
onUpdateStep(stepId, step) {
console.log("updating step");
this.steps[stepId] = step;
},
onUpdateStepPosition(stepId, position) {
console.log("updating step position");
this.steps[stepId].position = position;
},
onDisconnect(nodeId, inputName) {
@@ -634,7 +631,6 @@ export default {
this.isCanvas = true;
return;
}
console.log(this.nodeIndex);
Vue.set(this.steps, this.nodeIndex++, {
name: name,
content_id: contentId,
@@ -683,14 +679,12 @@ export default {
},
onActiveNode(nodeId) {
this.activeNode = this.nodes[nodeId];
console.log("active node");
this.$refs["right-panel"].scrollTop = 0;
},
getManager() {
return this;
},
getNode() {
console.log("getting node");
return this.activeNode;
},
onInsertedStateMessages(insertedStateMessages) {
@@ -2,8 +2,8 @@
<draggable-wrapper
ref="el"
@updatePosition="onUpdatePosition"
@mouseup.prevent="makeActive"
@move.prevent="onMove"
@mouseup="makeActive"
@move="onMove"
:id="idString"
:name="name"
:node-label="label"
@@ -249,7 +249,6 @@ export default {
return { top: this.step.position.top + "px", left: this.step.position.left + "px" };
},
defaultPosition() {
console.log("defaultPosition fires");
const p = document.getElementById("canvas-viewport");
const o = document.getElementById("canvas-container");
if (p && o) {
@@ -272,7 +271,6 @@ export default {
});
},
onStopDragging() {
console.log("onStopDragging called");
this.$emit("stopDragging");
},
onUpdatePosition(position) {
@@ -280,10 +278,8 @@ export default {
},
onMouseDown(e) {
this.mouseDown = { offsetX: e.offsetX, offsetY: e.offsetY };
console.log("mouseDownOffset", this.mouseDown);
},
onChange() {
console.log("onChange triggered");
this.$emit("onChange");
},
onAddInput(input, terminal) {
@@ -384,7 +380,6 @@ export default {
this.highlight = false;
},
makeActive() {
console.log("Clicked");
this.$emit("onActivate", this.id);
},
offsetVaryPosition(offsetRange) {
@@ -91,11 +91,6 @@ export default {
},
watch: {
terminalPosition(position) {
console.log({
stepId: this.nodeId,
inputName: this.input.name,
position,
});
this.$store.commit("workflowState/setInputTerminalPosition", {
stepId: this.nodeId,
inputName: this.input.name,
@@ -111,16 +106,11 @@ export default {
onRemove() {
this.$emit("onDisconnect", this.input.name);
},
mouseOver(e) {
console.log("mousOver");
// }
},
mouseOver(e) {},
mouseLeave() {
this.showRemove = false;
},
onDrop(e) {
console.log("onDrop", e);
},
onDrop(e) {},
},
beforeDestroy() {
this.$store.commit("workflowState/deleteInputTerminalPosition", {
@@ -145,7 +145,6 @@ export default {
},
watch: {
terminalPosition(position) {
console.log("updating position", position);
this.$store.commit("workflowState/setOutputTerminalPosition", {
stepId: this.getNode().id,
outputName: this.output.name,
@@ -153,7 +152,6 @@ export default {
});
},
dragPosition() {
console.log("dragPosition", this.endX);
if (this.isDragging) {
this.$emit("onDragConnector", this.dragPosition);
}
@@ -186,21 +184,12 @@ export default {
this.deltaY = 0;
this.$emit("stopDragging");
},
inputDragStart(e) {
console.log("inputDragStart", e);
},
inputDragEnter(e) {
console.log("inputDragEnter", e);
},
inputDragLeave(e) {
console.log("inputDragLeave", e);
},
onDrop(e) {
console.log("onDrop", e);
},
inputDragStart(e) {},
inputDragEnter(e) {},
inputDragLeave(e) {},
onDrop(e) {},
onChange() {
// this.isMultiple = this.terminal.isMappedOver();
console.log("onChange");
// this.$emit("onChange");
},
onToggle() {
@@ -1,60 +1,59 @@
<template>
<div id="workflow-canvas" class="unified-panel-body workflow-canvas">
<ZoomControl :zoom-level="zoomLevel" @onZoom="onZoomButton" />
<div class="canvas-viewport" @dragover.prevent @drop.prevent>
<div id="canvas-container" ref="el">
<Draggable style="width: 100%; height: 100%" @move="onPanContainer" :apply-scale="false">
<SvgPanZoom
style="width: 100%; height: 100%"
:minZoom="0.1"
:panEnabled="false"
:zoomEnabled="true"
:controlIconsEnabled="false"
:fit="false"
:center="false"
:on-zoom="onZoom"
:onUpdatedCTM="onUpdatedCTM"
@svgpanzoom="registerSvgPanZoom">
<svg class="canvas-svg" width="100%" height="100%" ref="svg">
<g class="zoomable">
<raw-connector v-if="draggingConnection" :position="draggingConnection"></raw-connector>
<terminal-connector
v-for="connection in connections"
:key="connection.id"
:connection="connection"></terminal-connector>
</g>
</svg>
</SvgPanZoom>
<div class="nodeArea" :style="style">
<!-- this div is only necessary so that we synchronize zoom and pan to the svg coordinates -->
<WorkflowNode
v-for="(step, key) in steps"
:id="key"
:key="key"
:name="step.name"
:type="step.type"
:content-id="step.content_id"
:step="step"
:datatypes-mapper="datatypesMapper"
:get-manager="getManager"
:activeNodeId="activeNodeId"
:root-offset="position"
@pan-by="onPan"
@stopDragging="onStopDragging"
@onDragConnector="onDragConnector"
@onActivate="onActivate"
@onRemove="onRemove"
v-on="$listeners" />
</div>
</Draggable>
</div>
<ZoomControl
:zoom-level="zoomLevel"
:pan="pan"
@onZoom="onZoomButton"
@reset-all="onResetAll"
@update:pan="onPan" />
<div ref="el" class="canvas-viewport" @drop.prevent>
<PinchScrollZoom
id="canvas-container"
ref="zoomControl"
:width="position.width"
:height="position.height"
:within="false"
minScale="0.1"
maxScale="10"
throttleDelay="16"
wheelVelocity="0.0015"
@dragging="onDrag"
@scaling="onScale">
<svg class="canvas-svg" width="100%" height="100%" ref="svg">
<g class="zoomable">
<raw-connector v-if="draggingConnection" :position="draggingConnection"></raw-connector>
<terminal-connector
v-for="connection in connections"
:key="connection.id"
:connection="connection"></terminal-connector>
</g>
</svg>
<WorkflowNode
v-for="(step, key) in steps"
:id="key"
:key="key"
:name="step.name"
:type="step.type"
:content-id="step.content_id"
:step="step"
:datatypes-mapper="datatypesMapper"
:get-manager="getManager"
:activeNodeId="activeNodeId"
:root-offset="position"
@pan-by="onPan"
@stopDragging="onStopDragging"
@onDragConnector="onDragConnector"
@onActivate="onActivate"
@onRemove="onRemove"
v-on="$listeners" />
</PinchScrollZoom>
</div>
<Minimap
:nodes="nodes"
:steps="steps"
:root-offset="position"
:scale="zoomLevel"
:pan="currentPan"
:pan="pan"
@pan-by="onPan"
@moveTo="onMoveTo" />
</div>
@@ -64,11 +63,11 @@ import ZoomControl from "./ZoomControl";
import WorkflowNode from "./Node";
import RawConnector from "./Connector";
import TerminalConnector from "./TerminalConnector";
import Draggable from "./Draggable.vue";
import Minimap from "./Minimap.vue";
import SvgPanZoom from "vue-svg-pan-zoom";
import { reactive, ref } from "vue";
import { useElementBounding } from "@vueuse/core";
import PinchScrollZoom, { PinchScrollZoomEmitData } from "@coddicat/vue-pinch-scroll-zoom";
export default {
setup() {
@@ -77,13 +76,13 @@ export default {
return { el, position };
},
components: {
Draggable,
RawConnector,
SvgPanZoom,
TerminalConnector,
WorkflowNode,
Minimap,
ZoomControl,
PinchScrollZoom,
},
data() {
return {
@@ -91,6 +90,7 @@ export default {
draggingConnection: null,
svgpanzoom: null,
transform: null,
pan: { x: 0, y: 0 },
};
},
props: {
@@ -112,11 +112,42 @@ export default {
},
},
methods: {
onWheel(e) {
console.log("wheel event", e);
onPan(pan) {
console.log("onPan", pan);
this.pan = pan;
this.$refs.zoomControl.setData({
scale: this.scale,
originX: pan.x,
originY: pan.y,
translateX: pan.x,
translateY: pan.y,
});
},
onResetAll() {
this.pan = { x: 0, y: 0 };
this.setScale(1);
this.$refs.zoomControl.setData({
scale: 1,
originX: 0,
originY: 0,
translateX: 0,
translateY: 0,
});
},
onDrag(panData) {
console.log("panData", panData);
this.pan = { x: panData.x, y: panData.y };
},
onScale(scaleData) {
console.log("scaleData", scaleData);
this.pan = {
x: scaleData.translateX * scaleData.scale,
y: scaleData.translateY * scaleData.scale,
};
console.log(this.pan);
this.setScale(scaleData.scale);
},
onMoveTo(moveTo) {
console.log("moving to", moveTo);
this.svgpanzoom.pan(moveTo);
},
onUpdatedCTM(CTM) {
@@ -142,14 +173,10 @@ export default {
registerSvgPanZoom(svgpanzoom) {
this.svgpanzoom = svgpanzoom;
},
onPan(pan) {
this.svgpanzoom.panBy(pan);
},
onPanContainer(e) {
this.svgpanzoom.panBy({ x: e.data.deltaX, y: e.data.deltaY });
},
onActivate(nodeId) {
console.log("onNodeId", nodeId);
if (this.activeNodeId != nodeId) {
this.$store.commit("workflowState/setActiveNode", nodeId);
// this.canvasManager.drawOverview();
@@ -163,18 +190,6 @@ export default {
},
},
computed: {
style() {
if (this.transform) {
return `transform: matrix(${this.transform.a}, ${this.transform.b}, ${this.transform.c}, ${this.transform.d}, ${this.transform.e}, ${this.transform.f})`;
}
},
currentPan() {
if (this.transform) {
return { x: this.transform.e, y: this.transform.f };
} else {
return { x: 0, y: 0 };
}
},
zoomLevel() {
return this.$store.getters["workflowState/getScale"]();
},
@@ -182,7 +197,6 @@ export default {
return this.$store.getters["workflowState/getActiveNode"]();
},
connections() {
console.log("connection fired");
const connections = [];
Object.entries(this.steps).forEach(([stepId, step]) => {
Object.entries(step.input_connections).forEach(([input_name, outputArray]) => {
@@ -29,6 +29,28 @@
size="sm"
aria-label="Zoom In"
@click="onZoomIn" />
<b-button
v-b-tooltip.hover
role="button"
class="fa fa-plus"
title="Reset all"
size="sm"
aria-label="Reset all"
@click="onResetAll" />
<label
>panX
<input
type="number"
:value="pan.x"
@change="$emit('update:pan', { x: parseInt($event.target.value), y: pan.x })" />
</label>
<label
>panY
<input
type="number"
:value="pan.y"
@change="$emit('update:pan', { x: pan.x, y: parseInt($event.target.value) })" />
</label>
</span>
</template>
@@ -44,6 +66,9 @@ export default {
type: Number,
default: 1,
},
pan: {
type: Object,
},
},
data() {
return {
@@ -54,6 +79,7 @@ export default {
zoomDefault: 1,
};
},
computed: {
isMin() {
return Math.round(this.zoomLevel * 100) == Math.round(this.zoomLevels[0] * 100);
@@ -91,6 +117,9 @@ export default {
onZoomReset() {
this.$emit("onZoom", this.zoomDefault);
},
onResetAll() {
this.$emit("reset-all");
},
},
};
</script>
@@ -109,7 +109,6 @@ class Connector {
// Resize the svg
const svg = d3.select(this.canvas).select("svg");
svg.attr("class", "ribbon");
console.log(svg);
svg.style("width", `${canvas_width}px`);
svg.style("height", `${canvas_height}px`);
@@ -174,7 +173,6 @@ class Connector {
{ x: end_x - cp_shift, y: end_y + offset_end },
{ x: end_x, y: end_y + offset_end },
];
console.log("lineData", lineData);
const lineFunction = d3.svg
.line()
.x(function (d) {
@@ -18,12 +18,10 @@ export async function fromSimple(workflow, data, appendData = false) {
step.uuid = null;
}
});
console.log("setting workflow steps");
workflow.steps = data.steps;
}
export function toSimple(workflow) {
console.log("to Simple");
const steps = {};
_rectifyOutputs(workflow);
Object.values(workflow.nodes).forEach((node) => {
@@ -126,7 +126,6 @@ class Terminal extends EventEmitter {
this.emit("change");
}
redraw() {
console.log("redraw");
this.connectors.forEach((c) => {
c.redraw();
});
+5
View File
@@ -1112,6 +1112,11 @@
"@citation-js/name" "^0.4.2"
wikidata-sdk "^8.0.0"
"@coddicat/vue-pinch-scroll-zoom@^3.3.4":
version "3.3.4"
resolved "https://registry.yarnpkg.com/@coddicat/vue-pinch-scroll-zoom/-/vue-pinch-scroll-zoom-3.3.4.tgz#48f5a2a4ac09c950799e6c2ecf62bde6c6f500c1"
integrity sha512-qGBK7TKg5Ii39u/2JnbfoBfQVaQfuVY865KR+X1vWbtaa8LWfwS+q4HgBHlV7JV1729a9zp3c9XDKIJoBVnAmA==
"@colors/colors@1.5.0":
version "1.5.0"
resolved "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz"