v3
by dapo
HTML
<script src="https://gistcdn.githack.com/dasDaniel/f3cebc1274339055729c6e887ca8d2ad/raw/6862a35fe666dc53fe72f20e3277d1de408e0c5a/vue.global.js"></script>
<div id="app"></div>
<template id="appTemplate">
<my-div>
<svg width="100%" height="400px" class="draggable">
<my-svg-rect></my-svg-rect>
<g transform="matrix(1 0 0 1 50 150)">
<svg-group>
<text fill="#aaddff" stroke="#06131d" font-size="38">
HI THERE
</text>
>
</svg-group>
</g>
</svg>
</my-div>
</template>
<template id="myDiv">
<div ref="el" class="dragbox dragable" :style="style">
<slot></slot>
</div>
</template>
<template id="mySvgRect">
<rect ref="el" v-bind="svgProps.attr" width="300" height="200" fill="#6daad8">
<slot></slot>
</rect>
</template>
<template id="svgGroup">
<g ref="el" v-bind="svgProps.attr">
<slot></slot>
</g>
</template>
CSS
.dragable {
touch-action: none;
user-select: none;
}
.dragbox {
font-family: "Lucida Sans", Geneva, Verdana, sans-serif;
width: 40%;
max-width: 90%;
min-width: 320px;
min-height: 6.5em;
margin: 0;
color: rgb(109, 170, 216);
background-color: rgb(187, 195, 209);
border-radius: 16px;
padding: 16px;
-webkit-transform: translate(0px, 0px);
transform: translate(0px, 0px);
transition: transform 0.1s ease-in, box-shadow 0.1s ease-out;
}
JavaScript
const {
reactive,
computed,
ref,
onMounted,
watch
} = Vue;
const makeDragable = element => {
const position = reactive({
init: false,
x: 0,
y: 0,
width: 0,
height: 0,
isDraging: false,
dragStartX: null,
dragStartY: null
});
const onMouseDown = e => {
e.stopPropagation();
let {
clientX,
clientY
} = e;
position.dragStartX = clientX - position.x;
position.dragStartY = clientY - position.y;
position.isDraging = true;
window.addEventListener("mouseup", onMouseUp);
window.addEventListener("mousemove", onMouseMove);
};
const onMouseMove = e => {
e.stopPropagation();
let {
clientX,
clientY
} = e;
position.x = clientX - position.dragStartX;
position.y = clientY - position.dragStartY;
};
const onMouseUp = e => {
e.stopPropagation();
let {
clientX,
clientY
} = e;
position.isDraging = false;
position.dragStartX = null;
position.dragStartY = null;
window.removeEventListener("mouseup", onMouseUp);
window.removeEventListener("mousemove", onMouseMove);
};
watch(element, (element, prevElement, onCleanup) => {
let rect;
if (element instanceof HTMLElement) {
rect = element.getBoundingClientRect(element);
} else if (element instanceof SVGGraphicsElement) {
rect = element.getBBox(element);
}
if (rect === undefined) return {
position: {}
};
position.init = true;
position.x = Math.round(rect.x);
position.y = Math.round(rect.y);
position.width = Math.round(rect.width);
position.height = Math.round(rect.height);
element.addEventListener("mousedown", onMouseDown);
onCleanup(() => {
document.removeEventListener("mouseup", onMouseUp);
document.removeEventListener("mousemove", onMouseMove);
if (element instanceof HTMLElement) {
element.removeEventListener("mousedown", onMouseDown);
}
})
});
...