Javascript Drag, Drop and bump other elements away - javascript

I have built out basic drag and drop feature that allows us to drag randomly placed absolute positioned elements within a container. Ideally I would want to push other elements that possibly intersect the dragged elements boundaries away, but I am presently unable find a solution.
I have this for the Drag and Drop Solution:
var draggableElements = document.getElementsByClassName("team_member");
for(var i = 0; i < draggableElements.length; i++){
dragElement(draggableElements[i]);
}
function dragElement(elmnt) {
var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
if (document.getElementById(elmnt.id + "header")) {
document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown;
} else {
elmnt.onmousedown = dragMouseDown;
}
function dragMouseDown(e) {
e = e || window.event;
pos3 = parseInt(e.clientX);
pos4 = parseInt(e.clientY);
document.onmouseup = closeDragElement;
document.onmousemove = elementDrag;
return false;
}
function elementDrag(e) {
e = e || window.event;
pos1 = pos3 - parseInt(e.clientX);
pos2 = pos4 - parseInt(e.clientY);
pos3 = parseInt(e.clientX);
pos4 = parseInt(e.clientY);
elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
elmnt.classList.add("drag");
}
function closeDragElement() {
document.onmouseup = null;
document.onmousemove = null;
elmnt.classList.remove("drag");
}
}

This is a cool task to implement, I played a bit and came up with something like this, but for some reason it's a big buggy, my idea was to use the API : document.elementFromPoint() to get the intersecting element during the drag. It seems to work but it's a bit clumsy and sometimes it fails.
Probably it would work better with an IntersectionObserver, that could also make sure to handle multiple boundary drag ( for example if you have 3+ objects, object one will push object 2 that will push object 3, object 3 has to react ).
const draggableElements = document.querySelectorAll(".team_member");
draggableElements.forEach((el, i) => makeDraggable(el, i))
function makeDraggable(elem, idx) {
elem.onmousedown = dragMouseDown;
elem.position = {
x: 0,
y: 0,
prevX: 0,
prevY: 0
}
elem.style.left = `calc(35% + ${(idx* 60) + "px"})`
}
// ----- //
function dragMouseDown(e) {
e = e || window.event;
this.position.prevX = +(e.clientX);
this.position.prevY = +(e.clientY);
document.onmouseup = closeDragElement;
document.onmousemove = (e) => elementDrag(e, this);
return false;
}
function elementDrag(e, t) {
t.position.x = t.position.prevX - +(e.clientX);
t.position.y = t.position.prevY - +(e.clientY);
t.position.prevX = +(e.clientX);
t.position.prevY = +(e.clientY);
t.style.top = (t.offsetTop - t.position.y) + "px";
t.style.left = (t.offsetLeft - t.position.x) + "px";
t.classList.add("drag");
// Check intersection
const width = t.getBoundingClientRect().width
const height = t.getBoundingClientRect().height
const intersectionElemTop = document.elementFromPoint(e.clientX, e.clientY - height / 2)
const intersectionElemRight = document.elementFromPoint(e.clientX + width / 2, e.clientY)
const intersectionElemBottom = document.elementFromPoint(e.clientX, e.clientY + height / 2)
const intersectionElemLeft = document.elementFromPoint(e.clientX - width / 2, e.clientY)
const intersections = [{
type: "top",
node: intersectionElemTop
}, {
type: "right",
node: intersectionElemRight
}, {
type: "bottom",
node: intersectionElemBottom
}, {
type: "left",
node: intersectionElemLeft
}].filter(i => [...draggableElements].some(d => i.node === d && d !== t))
if (intersections[0]) {
const i = intersections[0]
switch (i.type) {
case "top":
{
i.node.style.top = t.getBoundingClientRect().y - height + "px";
}
break;
case "right":
{
i.node.style.left = t.getBoundingClientRect().x + width + "px";
}
break;
case "bottom":
{
i.node.style.top = t.getBoundingClientRect().y + height + "px";
}
break;
case "left":
{
i.node.style.left = t.getBoundingClientRect().x - width + "px";
}
break;
}
i.node.classList.add("dragged");
clearTimeout(i.timeout)
i.timeout = setTimeout(() => i.node.classList.remove("dragged"), 500);
}
}
function closeDragElement(e) {
document.onmouseup = null;
document.onmousemove = null;
e.target.classList.remove("drag");
}
.team_member {
position: fixed;
width: 50px;
height: 50px;
border: 2px solid red;
display: flex;
justify-content: center;
align-items: center;
cursor: grab;
top: calc(50% - 25px);
}
.drag {
background: blue;
}
.dragged {
background: red;
}
<div class="team_member">
One
</div>
<div class="team_member">
Two
</div>

Related

Constraints problem with HTML element drag

I made script for dragging element around my react application in the way that limits are parent container. I achieved what I want but not in the way I want. I want when I reach limits to block that axis from trying to go further to avoid this annoying effect of script calculating and returning div in position.
const drag = (id) => {
const element = document.getElementById(id);
const parent = element.parentNode;
let newState = { x: 0, y: 0 };
let oldState = { x: 0, y: 0 };
const dragElement = (e) => {
e = e || window.event;
e.preventDefault();
oldState.x = e.clientX;
oldState.y = e.clientY;
document.onmouseup = stopDrag;
document.onmousemove = startDrag;
};
const startDrag = (e) => {
e = e || window.event;
e.preventDefault();
newState.x = oldState.x - e.clientX;
newState.y = oldState.y - e.clientY;
oldState.x = e.clientX;
oldState.y = e.clientY;
const handleX = () => {
let x = 0;
if (element.offsetLeft < 0) {
x = 0;
} else if (element.offsetLeft + element.offsetWidth > parent.offsetWidth) {
x = parent.offsetWidth - element.offsetWidth;
} else {
x = element.offsetLeft - newState.x;
}
return `${x}px`;
};
const handleY = () => {
let y = 0;
if (element.offsetTop < 0) {
y = 0;
} else if (element.offsetTop + element.offsetHeight > parent.offsetHeight) {
y = parent.offsetHeight - element.offsetHeight;
} else {
y = element.offsetTop - newState.y;
}
return `${y}px`;
};
element.style.top = handleY();
element.style.left = handleX();
};
const stopDrag = () => {
document.onmouseup = null;
document.onmousemove = null;
};
if (document.getElementById(element.id + "Header")) {
document.getElementById(element.id + "Header").onmousedown = dragElement;
} else {
element.onmousedown = dragElement;
}
};
drag("test");
.parent {
display: flex;
justify-content: center;
align-items: center;
position: absolute;
inset: 16px;
background: red;
}
.draggable {
position: absolute;
width: 50px;
height: 50px;
background: green;
}
<div class="parent">
<div class="draggable" id="test"></div>
</div>

Create an image every time I click a button JS

I want to create one image each time I click on a button and I will need to be able to drag this each image to move it where I want.
At this moment my code works only for one image.
I think I need to create my div in JS but this doesn't work..
const CreerPerso = document.getElementById('createPerso');
CreerPerso.onclick = CreationPersonnage;
async function CreationPersonnage() {
/*var divImg = document.createElement('div');
divImg.setAttribute("id", "imgPerso");
document.getElementById('body').appendChild(divImg);*/
document.getElementById("imgPerso").innerHTML = "<img src='images/circle.png' />";
//drag images Personnage
dragElement(document.getElementById("imgPerso"));
function dragElement(elmnt) {
var pos1 = 0,
pos2 = 0,
pos3 = 0,
pos4 = 0;
if (document.getElementById(elmnt.id)) {
// if present, the header is where you move the DIV from:
document.getElementById(elmnt.id).onmousedown = dragMouseDown;
} else {
// otherwise, move the DIV from anywhere inside the DIV:
elmnt.onmousedown = dragMouseDown;
}
function dragMouseDown(e) {
e = e || window.event;
e.preventDefault();
// get the mouse cursor position at startup:
pos3 = e.clientX;
pos4 = e.clientY;
document.onmouseup = closeDragElement;
// call a function whenever the cursor moves:
document.onmousemove = elementDrag;
}
function elementDrag(e) {
e = e || window.event;
e.preventDefault();
// calculate the new cursor position:
pos1 = pos3 - e.clientX;
pos2 = pos4 - e.clientY;
pos3 = e.clientX;
pos4 = e.clientY;
// set the element's new position:
elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
}
function closeDragElement() {
// stop moving when mouse button is released:
document.onmouseup = null;
document.onmousemove = null;
}
}
}
<body id="body">
<button id="createPerso" class="btn btn-primary">Créer Personnage</button>
<div id="imgPerso">
</div>
</body>
Id's in HTML need to be unique, so you should add a counter or something to the div you create and keep that id for future reference.
var personImageIdCount = 0;
async function CreationPersonnage() {
var personImageId = "imgPerso_" + (personImageIdCount++).toString();
var divImg = document.createElement('div');
divImg.setAttribute("id", personImageId);
document.getElementById('body').appendChild(divImg);
No need for async
No need to give body an ID
You pass the element, no need to get the ID to get the element
IDs need to be unique
This is simpler
function dragElement(elmnt) {
elmnt.dataset.pos1 = 0,
elmnt.dataset.pos2 = 0,
elmnt.dataset.pos3 = 0,
elmnt.dataset.pos4 = 0;
// if present, the header is where you move the DIV from:
elmnt.addEventListener("mousedown", dragMouseDown);
}
function dragMouseDown(e) {
e.preventDefault();
const elemt = e.target;
// get the mouse cursor position at startup:
elemt.dataset.pos3 = e.clientX;
elemt.dataset.pos4 = e.clientY;
}
function elementDrag(e) {
e.preventDefault();
const elemt = e.target;
if (elemt) {
// calculate the new cursor position:
let pos1 = elemt.dataset.pos3 - elemt.clientX;
let pos2 = elemt.dataset.pos4 - elemt.clientY;
let = elemt.clientX;
let = elemt.clientY;
// set the element's new position:
elemt.style.top = (elemt.offsetTop - pos2) + "px";
elemt.style.left = (elemt.offsetLeft - pos1) + "px";
}
}
function closeDragElement() {
// stop moving when mouse button is released:
document.onmouseup = null;
document.onmousemove = null;
}
const CreerPerso = document.getElementById('createPerso');
const body = document.querySelector('body');
CreerPerso.addEventListener("click", CreationPersonnage);
function CreationPersonnage() {
const divImg = document.createElement('div');
divImg.classList.add("imgPerso");
divImg.innerHTML = "<img src='images/circle.png' />";
body.appendChild(divImg);
//drag images Personnage
dragElement(divImg);
}
document.addEventListener("mouseup", closeDragElement);
document.addEventListener("mousemove", elementDrag);
.imgPerso {
position: absolute
}
<button id="createPerso" class="btn btn-primary">Créer Personnage</button>

How to make a draggable div resize-able on all 4 corners with pure javascript?

I noticed these resize pointers in the css spec...
https://drafts.csswg.org/css-ui-3/#valdef-cursor-se-resize
Is there a CSS shortcut for 4 corner resizability similar to the one corner ('resize: both') method?
If not, are there known conflicts when combining resizability with a draggable div?
My starting point was here...
https://www.w3schools.com/howto/howto_js_draggable.asp
Any help navigating the posX, posY is appreciated.
notes for getBoundingClient()
———---
| |
|____ | div.getBoundingClientRect()
SE (bottom right):
Height and width / top and left are stationary
SW (bottom left):
Height and width and left / top is stationary
NW (top left):
Height and width top and left
NE (top right):
Height and width and Top / Left is stationary
edit: removed padding and borders.
const myDiv = document.getElementById('mydiv')
let isResizing = false;
//Make the DIV element draggable:
dragElement(myDiv);
function dragElement(elmnt) {
if (!isResizing) {
let pos1 = 0,
pos2 = 0,
pos3 = 0,
pos4 = 0;
if (document.getElementById(elmnt.id + "header")) {
//if present, the header is where you move the DIV from:
document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown;
} else {
//otherwise, move the DIV from anywhere inside the DIV:
elmnt.onmousedown = dragMouseDown;
}
function dragMouseDown(e) {
e = e || window.event;
e.preventDefault();
// get the mouse cursor position at startup:
pos3 = e.clientX;
pos4 = e.clientY;
document.onmouseup = closeDragElement;
// call a function whenever the cursor moves:
document.onmousemove = elementDrag;
}
function elementDrag(e) {
e = e || window.event;
e.preventDefault();
// calculate the new cursor position:
pos1 = pos3 - e.clientX;
pos2 = pos4 - e.clientY;
pos3 = e.clientX;
pos4 = e.clientY;
// set the element's new position:
elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
}
function closeDragElement() {
//stop moving when mouse button is released:
document.onmouseup = null;
document.onmousemove = null;
}
}
}
// Resize
(function fourCorners() {
const resizers = document.querySelectorAll('.resizer')
let currentResizer
for (let resizer of resizers) {
resizer.addEventListener('mousedown', mouseDown)
function mouseDown(e) {
currentResizer = e.target
e.preventDefault()
isResizing = true;
let posX = e.clientX;
let posY = e.clientY;
myDiv.addEventListener('mousemove', mouseMove)
myDiv.addEventListener('mouseup', mouseUp)
function mouseMove(e) {
e.preventDefault()
const rect = myDiv.getBoundingClientRect()
if (currentResizer.classList.contains('se')) {
//console.log(currentResizer.classList.value)
myDiv.style.width = rect.width - (posX - e.clientX) + 'px';
myDiv.style.height = rect.height - (posY - e.clientY) + 'px';
} else if (currentResizer.classList.contains('sw')) {
//console.log(currentResizer.classList.value)
myDiv.style.width = rect.width + (posX - e.clientX) + 'px';
myDiv.style.height = rect.height - (posY - e.clientY) + 'px';
myDiv.style.left = rect.left - (posX - e.clientX) + 'px';
} else if (currentResizer.classList.contains('ne')) {
//console.log(currentResizer.classList.value)
myDiv.style.width = rect.width - (posX - e.clientX) + 'px';
myDiv.style.height = rect.height + (posY - e.clientY) + 'px';
myDiv.style.top = rect.top - (posY - e.clientY) + 'px';
} else {
//console.log(currentResizer.classList.value)
myDiv.style.width = rect.width + (posX - e.clientX) + 'px';
myDiv.style.height = rect.height + (posY - e.clientY) + 'px';
myDiv.style.top = rect.top - (posY - e.clientY) + 'px';
myDiv.style.left = rect.left - (posX - e.clientX) + 'px';
}
posX = e.clientX;
posY = e.clientY;
}
function mouseUp(e) {
myDiv.removeEventListener('mousemove', mouseMove)
myDiv.removeEventListener('mouseup', mouseUp)
isResizing = false
}
}
}
})()
* {
margin: 0;
padding : 0;
}
#mydiv {
position: absolute; /* NECESSARY */
background-color: whitesmoke;
box-sizing: border-box;
text-align: center;
/* border: 1px solid #222; */
height: 200px;
width: 200px;
/* resize: both; /* CSS RESIZE */
overflow: hidden; /* CSS RESIZE */
}
#mydivheader {
/* padding: 10px; */
cursor: move;
background-color: dodgerblue;
color: #fff;
}
#content {
color: #000;
margin: 0px;
background-color: whitesmoke;
}
/* ::-webkit-resizer {
position: absolute;
height: 20px;
width: 20px;
border-top-left-radius: 25px;
background-color: #dd0;
z-index: 2;
} */
.resizer {
position: absolute;
height: 20px;
width: 20px;
background-color: #dd0;
z-index: 2;
}
.resizer.nw {
top: -1px;
left: -1px;
cursor: nw-resize;
border-bottom-right-radius: 25px;
}
.resizer.ne {
top: -1px;
right: -1px;
cursor: ne-resize;
border-bottom-left-radius: 25px;
}
.resizer.sw {
bottom: -1px;
left: -1px;
cursor: sw-resize;
border-top-right-radius: 25px;
}
.resizer.se {
bottom: -1px;
right: -1px;
cursor: se-resize;
border-top-left-radius: 25px;
}
<div id="mydiv">
<div class='resizer nw'></div>
<div class='resizer ne'></div>
<div class='resizer sw'></div>
<div class='resizer se'></div>
<div id="mydivheader">Click here to move
<div id='content'>
<div id='image-container'><img height='auto' width='100%' src='https://picsum.photos/600' /></div>
</div>
</div>
</div>
Well if you want to make it nice and easy you could use jQuery to help it resize would probably be the easiest way. Then after you learn how to do it with jQuery you could do it with pure js.
So, you want the resize handle to appear on all four corners? That'll require some bounds checking.
You can modify the offset check in drag to account for any corner and handle the drag as a resize event instead. The code somewhat works for top-left and bottom-right resizing, but doe not work too well with the opposite corners. This is a start.
This is a start:
const cursor = document.querySelector('#cursor');
const cornerThreshold = 4;
const dragStart = e => {
const [ horz, vert ] = getDirection(e, cornerThreshold);
const bounds = e.target.getBoundingClientRect();
const cursor = getCursorType(e);
if (cursor === 'grab') {
e.target.dataset.isDragging = true;
} else {
e.target.dataset.isResizing = true;
}
e.target.dataset.startWidth = bounds.width;
e.target.dataset.startHeight = bounds.height;
e.target.dataset.originX = e.clientX;
e.target.dataset.originY = e.clientY;
e.target.dataset.offsetX = e.clientX - e.target.offsetLeft;
e.target.dataset.offsetY = e.clientY - e.target.offsetTop;
e.target.dataset.dirHorz = horz;
e.target.dataset.dirVert = vert;
e.target.style.zIndex = 999;
};
const dragEnd = e => {
delete e.target.dataset.isDragging;
delete e.target.dataset.offsetX;
delete e.target.dataset.offsetY;
delete e.target.dataset.originX;
delete e.target.dataset.originY;
delete e.target.dataset.startWidth;
delete e.target.dataset.startHeight;
delete e.target.dataset.dirHorz;
delete e.target.dataset.dirVert;
delete e.target.dataset.resizeDirection;
e.target.style.removeProperty('z-index');
e.target.style.removeProperty('cursor');
};
const drag = e => {
e.target.style.cursor = getCursorType(e);
cursor.textContent = `(${e.clientX}, ${e.clientY})`;
if (e.target.dataset.isDragging) {
e.target.style.left = `${e.clientX - parseInt(e.target.dataset.offsetX, 10)}px`;
e.target.style.top = `${e.clientY - parseInt(e.target.dataset.offsetY, 10)}px`;
} else if (e.target.dataset.isResizing) {
const bounds = e.target.getBoundingClientRect();
const startWidth = parseInt(e.target.dataset.startWidth, 10);
const startHeight = parseInt(e.target.dataset.startWidth, 10);
const deltaX = e.clientX - parseInt(e.target.dataset.originX, 10);
const deltaY = e.clientY - parseInt(e.target.dataset.originY, 10);
const originX = parseInt(e.target.dataset.originX, 10);
const originY = parseInt(e.target.dataset.originY, 10);
const dirHorz = parseInt(e.target.dataset.dirHorz, 10);
const dirVert = parseInt(e.target.dataset.dirVert, 10);
if (dirHorz < 0) {
e.target.style.left = `${originX + deltaX}px`;
e.target.style.width = `${startWidth - deltaX}px`
} else if (dirHorz > 0) {
e.target.style.width = `${startWidth + deltaX}px`;
}
if (dirVert < 0) {
e.target.style.top = `${originY + deltaY}px`;
e.target.style.height = `${startHeight - deltaY}px`;
} else if (dirVert > 0) {
e.target.style.height = `${startHeight + deltaY}px`;
}
}
};
const focus = e => { };
const unfocus = e => { e.target.style.removeProperty('cursor'); };
const getDirection = (e, threshold) => {
const bounds = e.target.getBoundingClientRect();
const offsetX = e.clientX - e.target.offsetLeft;
const offsetY = e.clientY - e.target.offsetTop;
const isTop = offsetY <= threshold;
const isLeft = offsetX <= threshold;
const isBottom = offsetY > (bounds.height - threshold);
const isRight = offsetX > (bounds.width - threshold);
if (isTop && isLeft) return [ -1, -1 ];
else if (isTop && isRight) return [ -1, 1 ];
else if (isBottom && isLeft) return [ 1, -1 ];
else if (isBottom && isRight) return [ 1, 1 ];
else return [ 0, 0 ];
};
const getCursorType = (e) => {
if (e.target.dataset.isDragging) {
return 'grabbing';
} else {
const [ horz, vert ] = getDirection(e, cornerThreshold);
const isTop = vert === -1;
const isLeft = horz === -1;
const isBottom = vert === 1;
const isRight = horz === 1;
if ((isTop && isLeft) || (isBottom && isRight)) return 'nwse-resize';
if ((isTop && isRight) || (isBottom && isLeft)) return 'nesw-resize';
}
return 'grab';
};
document.querySelectorAll('.draggable').forEach(draggable => {
draggable.addEventListener('mousedown', dragStart);
draggable.addEventListener('mouseup', dragEnd);
draggable.addEventListener('mousemove', drag);
draggable.addEventListener('mouseenter', focus);
draggable.addEventListener('mouseleave', unfocus);
});
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
.container {
position: relative;
width: 60%;
height: 60%;
border: thin solid grey;
}
.square {
position: absolute;
height: 2em;
width: 2em;
}
.color-red { background: red; }
.color-blue { background: blue; }
.color-green { background: green; }
#square-1 { top: 10px; left: 10px; }
#square-2 { top: 50px; left: 50px; }
#square-3 { top: 100px; left: 100px; }
<div class="container">
<div id="square-1" class="square color-red draggable resizable"></div>
<div id="square-2" class="square color-blue draggable resizable"></div>
<div id="square-3" class="square color-green draggable resizable"></div>
</div>
<br />
<div>Cursor: <span id="cursor">(0, 0)</span></div>

Javascript move all childs inside div element

I'm trying to create a simple drag function that moves all childs inside a div tag depending on mouse movement, in simple world I calculate deltaX and deltaY and apply those to all childs inside a div by changing style.top and style.left. As regarding the X coordinate it works well while Y doesn't work (only increase) and I cannt explain why. This is what I have done
//Make the DIV element draggagle:
dragElement(document.getElementById(("mydiv")));
function dragElement(elmnt) {
var deltaX = 0, deltaY = 0, initX = 0, initY = 0;
var flag=true;
elmnt.onmousedown = dragMouseDown;
var childrens;
function dragMouseDown(e) {
e = e || window.event;
//console.log("dragMouseDown: "+e.clientX+" "+e.clientY);
childrens = document.getElementById("mydiv").querySelectorAll(".child");
// get the mouse cursor position at startup:
initX = e.clientX;
initY = e.clientY;
document.onmouseup = closeDragElement;
// call a function whenever the cursor moves:
document.onmousemove = elementDrag;
}
function elementDrag(e) {
if(flag){
flag=false;
e = e || window.event;
// calculate the new cursor position:
deltaX = e.clientX-initX;
deltaY = e.clientY-initY;
console.log("deltaX: "+deltaX+" deltaY: "+deltaY);
for (var i = 0; i < childrens.length; i++) {
//console.log("childrens[i].offsetTop: "+childrens[i].offsetTop+" childrens[i].offsetLeft: "+childrens[i].offsetLeft);
childrens[i].style.top = (childrens[i].offsetTop + deltaY) + "px"; // dont work (only increase)
childrens[i].style.left = (childrens[i].offsetLeft + deltaX) + "px";
}
initX = e.clientX;
initY = e.clientY;
deltaX=0;
deltaY=0;
flag=true;
}
}
function closeDragElement() {
/* stop moving when mouse button is released:*/
document.onmouseup = null;
document.onmousemove = null;
}
}
#mydiv {
position: fixed;
z-index: 9;
background-color: #f1f1f1;
text-align: center;
width:400px;
height:400px;
border: 1px solid #d3d3d3;
}
.child {
position: relative;
padding: 10px;
cursor: move;
z-index: 10;
background-color: #2196F3;
color: #fff;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>Draggable DIV Element</h1>
<p>Click and hold the mouse button down while moving the DIV element</p>
<div id="mydiv" style="background-color:blue">
<p class="child" style="background-color:red">Move 1</p>
</div>
Try something like this:
dragElement(document.getElementById(("mydiv")));
function dragElement(elmnt) {
var deltaX = 0,
deltaY = 0,
initX = 0,
initY = 0;
var flag = true;
elmnt.onmousedown = dragMouseDown;
var childrens;
function dragMouseDown(e) {
e = e || window.event;
childrens = document.getElementById("mydiv").querySelectorAll(".child");
for (var i = 0; i < childrens.length; i++) {
childrens[i].style.top = childrens[i].style.top == "" ? "0px" : childrens[i].style.top;
childrens[i].style.left = childrens[i].style.left == "" ? "0px" : childrens[i].style.left;
}
initX = e.clientX;
initY = e.clientY;
document.onmouseup = closeDragElement;
document.onmousemove = elementDrag;
}
function elementDrag(e) {
if (flag) {
flag = false;
e = e || window.event;
deltaX = e.clientX - initX;
deltaY = e.clientY - initY;
for (var i = 0; i < childrens.length; i++) {
childrens[i].style.top = parseInt(childrens[i].style.top) + deltaY + "px";
childrens[i].style.left = parseInt(childrens[i].style.left) + deltaX + "px";
}
initX = e.clientX;
initY = e.clientY;
flag = true;
}
}
function closeDragElement() {
document.onmouseup = null;
document.onmousemove = null;
}
}
#mydiv {
position: fixed;
z-index: 9;
background-color: #f1f1f1;
text-align: center;
width: 400px;
height: 400px;
border: 1px solid #d3d3d3;
}
.child {
position: relative;
padding: 10px;
cursor: move;
z-index: 10;
background-color: #2196F3;
color: #fff;
}
<h1>Draggable DIV Element</h1>
<p>Click and hold the mouse button down while moving the DIV element</p>
<div id="mydiv" style="background-color:blue">
<p class="child" style="background-color:red">Move 1</p>
<p class="child" style="background-color:yellow">Move 2</p>
</div>
This isn't a nice solution but it works. Consider using jQuery and jQuery Draggable.

HTML5: Drag/drop on X-axis and without fade?

I've been looking for drag-and-drop examples/tutorials for HTML5, but all of them so far involve an object that fades as it's being dragged and without being constrained to any axis. I was wondering if it's possible to have the actual object itself be dragged as opposed to a ghost of it and whether I can constrain it to X or Y axis?
Thanks!
Yes, easily, by writing it yourself.
elem.onmousedown = function(e) {
e = e || window.event;
var start = 0, diff = 0;
if( e.pageX) start = e.pageX;
else if( e.clientX) start = e.clientX;
elem.style.position = 'relative';
document.body.onmousemove = function(e) {
e = e || window.event;
var end = 0;
if( e.pageX) end = e.pageX;
else if( e.clientX) end = e.clientX;
diff = end-start;
elem.style.left = diff+"px";
};
document.body.onmouseup = function() {
// do something with the action here
// elem has been moved by diff pixels in the X axis
elem.style.position = 'static';
document.body.onmousemove = document.body.onmouseup = null;
};
}
Use the Event.movementX to determine the difference in pointer position:
const dragX = (evt) => {
const el = evt.currentTarget;
const move = (evt) => {
el.style.left = `${el.offsetLeft + evt.movementX}px`;
};
const up = () => {
removeEventListener("pointermove", move);
removeEventListener("pointerup", up);
};
addEventListener("pointermove", move);
addEventListener("pointerup", up);
};
// Use like:
const elDraggable = document.querySelector("#draggable");
elDraggable.addEventListener("pointerdown", dragX);
#draggable {
display: inline-block;
position: absolute;
top: 2rem;
left: 2rem;
background: red;
padding: 1rem;
user-select: none; /* prevent text selection */
}
<div id="draggable">X axis draggable</div>

Categories