3
I’m making a component where I can drag other components vertically. When one component passes the other they must change places (on the X axis).
What happens is that the element I’m dragging respects the CSS transition, slides to the next position, but the other one doesn’t. He jumps directly into the new position.
What is the reason for this and how to correct?
Vue.component('dragable', {
props: ['config', 'leftPosition'],
template: '#dragable',
data() {
return {
elementStartCoords: null,
pointerTouchDown: null,
pointerUpHandler: this.onPointerUp.bind(this),
pointerMoveHandler: this.onPointerMove.bind(this)
}
},
computed: {
style() {
return {
top: this.config.top + 'px',
left: this.leftPosition * 150 + 'px'
}
}
},
methods: {
getPointerCoordinates(e) {
return {
y: e.pageY || e.originalEvent.touches[0].pageY
};
},
getElementPosition(el) {
const coords = el.getBoundingClientRect();
return {
y: coords.top
};
},
onPointerDown(e) {
this.elementStartCoords = this.getElementPosition(this.$el);
this.pointerTouchDown = this.getPointerCoordinates(e);
window.addEventListener('mouseup', this.pointerUpHandler);
window.addEventListener('mousemove', this.pointerMoveHandler);
},
onPointerMove(e) {
e.stopPropagation();
if (!this.pointerTouchDown) return;
const pointerPosition = this.getPointerCoordinates(e);
const yDiff = pointerPosition.y - this.pointerTouchDown.y;
this.$emit('dragevent', {
name: this.config.name,
top: this.elementStartCoords.y + yDiff
});
},
onPointerUp() {
window.removeEventListener('mouseup', this.pointerUpHandler);
window.removeEventListener('mousemove', this.pointerMoveHandler);
// reset used variables
this.pointerTouchDown = null;
this.elementStartCoords = null;
},
}
})
new Vue({
el: '#app',
data() {
return {
draggables: [{
name: 'A',
top: 70
}, {
name: 'B',
top: 0
}]
}
},
methods: {
handleDrag(config) {
const draggable = this.draggables.find(drg => drg.name == config.name);
draggable.top = config.top;
this.draggables = this.draggables.sort((a, b) => b.top - a.top);
}
}
})
.dragable {
user-select: none;
position: absolute;
background-color: #dde;
border: 2px solid #88A;
border-radius: 5px;
padding: 30px;
cursor: pointer;
transition: left 1s;
}
<script src="https://vuejs.org/js/vue.min.js"></script>
<div id="app">
<p>Dragable test</p>
<template v-for="(draggable, i) in draggables">
<dragable :key="draggable.name" :config="draggable" :left-position="i" @dragevent="handleDrag"></dragable>
</template>
</div>
<template lang="html" id="dragable">
<div class="dragable" :style="style" @mousedown="onPointerDown" draggable="false">{{'Draggable ' + config.name}}</div>
</template>