Skip to content

Commit

Permalink
add zoom to Patient Editor
Browse files Browse the repository at this point in the history
  • Loading branch information
JoshuaRiewesell committed Sep 9, 2024
1 parent 5f5fa5b commit 9f5e7ab
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 2 deletions.
6 changes: 6 additions & 0 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@formkit/vue": "^1.6.5",
"@rushstack/eslint-patch": "^1.7.2",
"@types/three": "^0.156.0",
"animejs": "^3.2.2",
"ant-design-vue": "^4.2.3",
"antd": "5.3.2",
"elkjs": "^0.8.2",
Expand Down
56 changes: 56 additions & 0 deletions frontend/src/components/widgets/ZoomControl.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<template>
<div class="zoom-control">
<button @click="zoomIn">
+
</button>
<button @click="zoomOut">
-
</button>
<button @click="resetZoom">
Reset
</button>
</div>
</template>

<script setup lang="ts">
import { defineComponent, inject } from 'vue'
const zoomPlugin = inject('zoomPlugin')
const zoomIn = () => {
zoomPlugin?.wheel({ deltaY: -1 } as WheelEvent)
}
const zoomOut = () => {
zoomPlugin?.wheel({ deltaY: 1 } as WheelEvent)
}
const resetZoom = () => {
zoomPlugin?.wheel({ deltaY: 0 } as WheelEvent) // Customize this based on actual reset logic
}
</script>

<style scoped>
.zoom-control {
position: absolute;
top: 20px;
right: 20px;
display: flex;
flex-direction: column;
}
.zoom-control button {
margin: 5px 0;
padding: 10px;
border: none;
background-color: var(--green);
color: white;
font-size: 16px;
cursor: pointer;
}
.zoom-control button:hover {
background-color: var(--dark-green);
}
</style>

7 changes: 5 additions & 2 deletions frontend/src/rete/editor.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ref, watch } from 'vue'
import { ClassicPreset as Classic, NodeEditor } from 'rete'
import { AreaExtensions, AreaPlugin } from 'rete-area-plugin'
import { AreaExtensions, AreaPlugin, Zoom } from 'rete-area-plugin'
import { ConnectionPlugin } from 'rete-connection-plugin'
import { VuePlugin, Presets as VuePresets } from 'rete-vue-plugin'
import {
Expand All @@ -18,6 +18,7 @@ import CustomDropdown from './customization/CustomDropdown.vue'
import { DropdownControl } from './dropdown'
import { StateNode, InitialStateNode, InputNode, OutputNode } from './nodes/index'
import CircleNode from './customization/CircleNode.vue'
import { SmoothZoom } from './zoom'

export const editorMode = ref<string>("patient")

Expand Down Expand Up @@ -83,7 +84,9 @@ export async function createEditor(container: HTMLElement, data: any) {
area.use(connection)
area.use(contextMenu)

area.area.setZoomHandler(null)
area.area.setZoomHandler(
new SmoothZoom(0.5, 200, "cubicBezier(.45,.91,.49,.98)", area)
)

area.addPipe(context => {
if (context.type === 'nodepicked') {
Expand Down
78 changes: 78 additions & 0 deletions frontend/src/rete/zoom.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { AreaPlugin, Zoom } from "rete-area-plugin"
import anime from "animejs/lib/anime.es.js"

function screenToArea(x: number, y: number, t: any) {
const { x: tx, y: ty, k } = t

return { x: (x - tx) / k, y: (y - ty) / k }
}

function areaToScreen(x: number, y: number, t: any) {
const { x: tx, y: ty, k } = t

return { x: x * k + tx, y: y * k + ty }
}

export class SmoothZoom extends Zoom {
animation?: any

constructor(
intensity: number,
private duration: number,
private easing: string,
private area: AreaPlugin<any>
) {
super(intensity)
}

wheel = (e: WheelEvent) => {
e.preventDefault()

const isNegative = e.deltaY < 0
const delta = isNegative ? this.intensity : -this.intensity
const { left, top } = this.container.getBoundingClientRect()
const ox = e.clientX - left
const oy = e.clientY - top

const coords = screenToArea(ox, oy, this.area.area.transform)

const { k } = this.area.area.transform
const targets = {
zoom: k
}
const { duration, easing } = this

if (this.animation) {
this.animation.reset()
}
this.animation = anime({
targets,
x: coords.x,
y: coords.y,
zoom: k * (1 + delta),
duration,
easing,
update: () => {
const currentTransform = this.area.area.transform

const coordinates = areaToScreen(coords.x, coords.y, currentTransform)

const nextX = coordinates.x - coords.x * targets.zoom
const nextY = coordinates.y - coords.y * targets.zoom

this.area.area.zoom(
targets.zoom,
nextX - currentTransform.x,
nextY - currentTransform.y
)
}
})
}

destroy() {
super.destroy()
if (this.animation) {
this.animation.reset()
}
}
}

0 comments on commit 9f5e7ab

Please sign in to comment.