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-component>
<my-component></my-component>
</my-component>
</template>
<template id="myComponent">
<div ref="el" class="dragable" :style="style">
<h3>DRAG ME</h3>
<pre>{{ position }}</pre>
<pre>{{ style }}</pre>
<slot></slot>
</div>
</template>
CSS
.dragable {
font-family: "Lucida Sans", Geneva, Verdana, sans-serif;
width: 40%;
max-width: 90%;
min-width: 320px;
min-height: 6.5em;
margin: 0;
color: rgb(6, 19, 29);
background-color: rgb(187, 195, 209);
border-radius: 16px;
padding: 16px;
touch-action: none;
user-select: none;
-webkit-transform: translate(0px, 0px);
transform: translate(0px, 0px);
transition: transform 0.1s ease-in, box-shadow 0.1s ease-out;
border: 1px solid rgb(6, 19, 29);
}
pre {
width: 48%;
display: inline-block;
overflow: hidden;
font-size: 10px;
}
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 style = computed(() => {
if (position.init) {
return {
position: "absolute",
left: position.x + "px",
top: position.y + "px",
width: position.width + "px",
height: position.height + "px",
"box-shadow": position.isDraging ? "3px 6px 16px rgba(0, 0, 0, 0.15)" : "",
"transform": position.isDraging ? "translate(-3px, -6px)" : "",
"cursor": position.isDraging ? "grab" : "pointer",
};
}
return {};
});
const onMouseDown = e => {
e.stopPropagation();
let {
clientX,
clientY
} = e;
position.dragStartX = clientX - position.x;
position.dragStartY = clientY - position.y;
position.isDraging = true;
document.addEventListener("mouseup", onMouseUp);
document.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;
document.removeEventListener("mouseup", onMouseUp);
document.removeEventListener("mousemove", onMouseMove);
};
watch(element, element => {
if (!element instanceof HTMLElement) return;
let rect = element.getBoundingClientRect(element);
position.init = true;
position.x = Math.round(rect.x);
...