0đź‘Ť
I’ve never tried it using draggable="true"
, instead I’d use mouse up, down, move (and the touch counterparts if needed for touch devices)
this gives you more control, and then you don’t have that overlapping item being shown.
the idea is that…
- in data, track postion, startdrag position (x,y) and whether item is being dragged
- on mouse down set isDragging to true and store start drag position x,y coordinates
- on mouse move, if
isDragging === true
update the position based on difference between startdrag and current clientXY - on mouse up, set isDragging to false
you can also improve this by adding and removing the listeners mousemove and mouseup dynamically. Because you want to have the mouse move listener on document (instead of the element anyway, this is a better way to go)
I’ve done a writeup on this recently for the new vue3 composition api at https://dev.to/dasdaniel/vue3-compisition-api-craeting-a-draggable-element-fo6
Because it’s for vue3, it’s not copy-paste friendly, but the important part is here:
const onMouseDown = e => {
let { clientX, clientY } = e;
position.dragStartX = clientX - position.x;
position.dragStartY = clientY - position.y;
position.isDragging = true;
document.addEventListener("mouseup", onMouseUp);
document.addEventListener("mousemove", onMouseMove);
};
const onMouseMove = e => {
let { clientX, clientY } = e;
position.x = clientX - position.dragStartX;
position.y = clientY - position.dragStartY;
};
const onMouseUp = e => {
let { clientX, clientY } = e;
position.isDragging = false;
position.dragStartX = null;
position.dragStartY = null;
document.removeEventListener("mouseup", onMouseUp);
document.removeEventListener("mousemove", onMouseMove);
};
0đź‘Ť
The HTML attribute “draggable” is used to indicate whether if an element is draggable. Note that this is a native browser behavior, you can read more about it here (https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/draggable). This is browser behavior is the reason why you are seeing a “ghost image” when attempting to drag the bubble.
I reckon that you use a much simpler approach to make the element draggable. Refer to this sample that I’ve prepared on JSFiddle (https://jsfiddle.net/r8emga0u/1/).
<div id="app" @mouseup="up" @mousemove="move">
{{x}}/{{y}} ....... {{coordinates}}
<div class="bubbleMenuContainer" :style="coordinates" @mousedown="down">
Test
</div>
</div>
down(e) {
this.bubbleMenuClickState = true;
this.offset = [
e.target.offsetLeft - e.clientX,
e.target.offsetTop - e.clientY
];
},
up(e) {
this.bubbleMenuClickState = false;
},
move(e) {
if (this.bubbleMenuClickState) {
this.coordinates.left = (e.clientX + this.offset[0]) + "px";
this.coordinates.top = (e.clientY + this.offset[1]) + "px";
}
}
Steps:
- Attach the “mousedown” listener to the element, you can calculate the offset of the bubble relative to it’s parent. Without this, the initial click on the bubble would probably set it’s position to 0,0 since no mousemove event has been triggered yet.
- Attach a “mouseup” listener to the bubble’s parent (in this case the #app), to detect when the user releases the click. Thus preventing the mousemove event from moving the bubble.
- Attach “mousemove” listener to update the bubble’s position if the user clicks and hold and drag the bubble.