Weird scrolling behavior on dragging Foreign object.
so i want to build a moodboard application in vue. Sort of like https://mydraft.cc/ where a user can have a board where he can drag certain parts of the page. I see that many applications use SVG for this. In the board users will have specific micro applications that needs extensive reactivty. There for i am using foreign objects inside of the svg.
Now its all working great except for one weird scroll behavior. as included in the added video when i drag the element down at first its working perfectly. But when i scroll down and then i drag the red square the svg scrolls down instead of only dragging the box itself down. How do i prevent the browser from scrolling and only move the box down.
if you want to see the weird behavior i recorded it here. https://www.loom.com/share/f5c7f473d0c841d692fa759c62ba4203?sid=89fedaa6-0b07-4561-a0bd-b1ef1d1f737c
At the top and bottom of the pages its behaving normally.
the code is as follows
app.vue
<script setup lang="ts">
import CanvasComponent from "@/components/CanvasComponent.vue";
const width = 3000;
const height = 3000;
window.addEventListener('wheel', (e) => {
e.preventDefault();
})
</script>
<template>
<div :style="`width:${(width+80)}px; height:${(height+80)}px`" class="overflow-auto p-10">
<svg viewBox="0 0 3000 3000" style="background-color:blue" :width="width + 'px'" :height="height + 'px'" xmlns="http://www.w3.org/2000/svg" version="1.1">
<CanvasComponent :initial-x="300" :initial-y="400" initial-width="200px" initial-height="300px"></CanvasComponent>
</svg>
</div>
</template>
CanvasComponent.Vue
<script setup lang='ts'>
import {nextTick, ref} from "vue";
const {initialX, initialY, initialWidth, initialHeight} = defineProps<{
initialX: number,
initialY: number,
initialWidth: string,
initialHeight: string
}>();
const x = ref(initialX)
const y = ref(initialY);
const width = ref(initialWidth)
const height = ref(initialHeight)
const isDragging = ref(false);
const offsetX = ref(0);
const offsetY = ref(0);
const dragStart = (e: MouseEvent) => {
e.stopPropagation();
e.preventDefault()
isDragging.value = true;
offsetX.value = e.clientX - x.value;
offsetY.value = e.clientY - y.value;
document.body.style.overflow = 'hidden'; // Prevent scrolling
nextTick(() => {
document.addEventListener('mousemove', drag);
document.addEventListener('mouseup', dragEnd);
});
}
const drag = (e: MouseEvent) => {
e.stopPropagation();
e.preventDefault();
if(!isDragging.value) return;
x.value = e.clientX - offsetX.value;
y.value = e.clientY - offsetY.value;
}
const dragEnd = (e: MouseEvent) => {
e.preventDefault();
isDragging.value = false;
document.removeEventListener('mousemove', drag);
document.removeEventListener('mouseup', dragEnd);
}
</script>
<template>
<foreignObject class="drag-handle-class"
:x="x"
:y="y"
:width="width"
:height="height"
@mousedown="dragStart"
>
<div class="w-full h-full bg-red-500 overflow-scroll drag-handle-class"></div>
</foreignObject>
</template>
I tried preventing the scolling itself but that didnt work. as you can see in the video it works perfectly in firefox its just the chromium browsers that are being weird.