How to make drag and drop with javascript - javascript

I have created a drag and drop application which contains left and right panel. When I drag the ball from left panel to right panel the ball is dragged. But the problem is here when I drag the ball the ball should not be removed from left panel while dragging it.Again it only should be dragged/move to right panel,and should not go back to left panel.Here is the code below
let currentDroppable = null;
ball.onmousedown = function(event) {
let shiftX = event.clientX - ball.getBoundingClientRect().left;
let shiftY = event.clientY - ball.getBoundingClientRect().top;
ball.style.position = 'absolute';
ball.style.zIndex = 1000;
document.body.append(ball);
moveAt(event.pageX, event.pageY);
function moveAt(pageX, pageY) {
ball.style.left = pageX - shiftX + 'px';
ball.style.top = pageY - shiftY + 'px';
}
function onMouseMove(event) {
moveAt(event.pageX, event.pageY);
ball.hidden = true;
let elemBelow = document.elementFromPoint(event.clientX, event.clientY);
ball.hidden = false;
if (!elemBelow) return;
let droppableBelow = elemBelow.closest('.droppable');
if (currentDroppable != droppableBelow) {
if (currentDroppable) { // null when we were not over a droppable before this event
leaveDroppable(currentDroppable);
}
currentDroppable = droppableBelow;
if (currentDroppable) { // null if we're not coming over a droppable now
// (maybe just left the droppable)
enterDroppable(currentDroppable);
}
}
}
document.addEventListener('mousemove', onMouseMove);
ball.onmouseup = function() {
document.removeEventListener('mousemove', onMouseMove);
ball.onmouseup = null;
};
};
function enterDroppable(elem) {
elem.style.background = 'pink';
}
function leaveDroppable(elem) {
elem.style.background = '';
}
ball.ondragstart = function() {
return false;
};
#gate {
cursor: pointer;
margin-bottom: 100px;
width: 83px;
height: 46px;
border: 1px solid;
}
#ball {
cursor: pointer;
width: 40px;
height: 40px;
}
<div style="float:left;border: 1px solid;width: 15%;">Left Pannel<img src="https://en.js.cx/clipart/ball.svg" id="ball"></div>
<div style="float: left;border: 1px solid;width: 80%;height: 1000px;">Right Panel</div>

<head>
<script>
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("text", ev.target.id);
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
ev.target.appendChild(document.getElementById(data));
}
</script>
</head>
<body>
<div style="float:left;border: 1px solid;width: 15%;" id="div1" ondrop="drop(event)" ondragover="allowDrop(event)">
Left Pannel
<img id="ball" src="https://en.js.cx/clipart/ball.svg" draggable="true" ondragstart="drag(event)">
</div>
<div id="div2" ondrop="drop(event)" ondragover="allowDrop(event)"
style="float: left;border: 1px solid;width: 80%;height: 1000px;">Right Panel</div>
</body>

Related

Only the last draggable <div> element / JS function stops when released and not the previous?

I am having problems with the following code (heavily cut down version). essentially I am trying to make the two different windows draggable (via the title bar only). It works perfectly when there is only one window, however, once I add another - they're both draggable, but one (first called in the code) won't let go.
makeDragable('#handle_1', '#moveable_1')
makeDragable('#handle_2', '#moveable_2')
So '#handle_1', '#moveable_1' would not be dropped after releasing the mouse.
This is my first time using JS - and html/css properly so I am sorry if this is a fundamental error. The JS is not my code. I am assuming the problem lies here:
/* End dragging */
document.onmouseup = function(e) {
if (dragObj) {
dragObj = null;
But just can't work it out. I'd prefer to use this code as it allows me to only allow the main bar to be draggable rather than the entire window. I apologise if my post is convoluted, any critique would be highly appreciated as this is my first Stack post.
Thanks in advance!
body {
background-image: url('https://www.betaarchive.com/imageupload/1304990899.or.90622.png');
font-family: "Pixelated MS Sans Serif",Arial;
font-size: 11px;
}
.grid-container {
display: grid;
gap: 10px;
font-size: 13px;
margin: 15px 35px 35px 35px;
}
.grid-container > div {
text-align: center;
margin: 10px 0px 10px 0px;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="https://unpkg.com/xp.css"/>
<link rel="stylesheet" href="styles_login.css"/>
<title>Login Screen</title>
</head>
<body>
<div id="moveable_1">
<div class="window" style="width: 350px; position: absolute; left: 100px; top: 150px;">
<div id="handle_1" class="title-bar">
<div class="title-bar-text">Login Screen</div>
</div>
<div class="window-content">
<div class="window-content-inner"></div>
<div class="status-bar">
<p class="status-bar-field">Test</p>
</div>
</div>
</div>
</div>
<div id="moveable_2">
<div class="window" style="width: 650px; position: absolute; left: 450px; top: 300px;">
<div id="handle_2" class="title-bar">
<div class="title-bar-text">Chat Screen</div>
</div>
<div class="window-content">
<div class="window-content-inner"></div>
<div class="status-bar">
<p class="status-bar-field">Test 2</p>
</div>
</div>
</div>
</div>
</body>
<script src="./renderer.js"></script>
<script> // Draggable Content JS
function makeDragable(dragHandle, dragTarget) {
let dragObj = null; //object to be moved
let xOffset = 0; //used to prevent dragged object jumping to mouse location
let yOffset = 0;
document.querySelector(dragHandle).addEventListener("mousedown", startDrag, true);
document.querySelector(dragHandle).addEventListener("touchstart", startDrag, true);
/*sets offset parameters and starts listening for mouse-move*/
function startDrag(e) {
e.preventDefault();
e.stopPropagation();
dragObj = document.querySelector(dragTarget);
dragObj.style.position = "absolute";
let rect = dragObj.getBoundingClientRect();
if (e.type=="mousedown") {
xOffset = e.clientX - rect.left; //clientX and getBoundingClientRect() both use viewable area adjusted when scrolling aka 'viewport'
yOffset = e.clientY - rect.top;
window.addEventListener('mousemove', dragObject, true);
} else if(e.type=="touchstart") {
xOffset = e.targetTouches[0].clientX - rect.left;
yOffset = e.targetTouches[0].clientY - rect.top;
window.addEventListener('touchmove', dragObject, true);
}
}
/*Drag object*/
function dragObject(e) {
e.preventDefault();
e.stopPropagation();
if(dragObj == null) {
return; // if there is no object being dragged then do nothing
} else if(e.type=="mousemove") {
dragObj.style.left = e.clientX-xOffset +"px"; // adjust location of dragged object so doesn't jump to mouse position
dragObj.style.top = e.clientY-yOffset +"px";
} else if(e.type=="touchmove") {
dragObj.style.left = e.targetTouches[0].clientX-xOffset +"px"; // adjust location of dragged object so doesn't jump to mouse position
dragObj.style.top = e.targetTouches[0].clientY-yOffset +"px";
}
}
/*End dragging*/
document.onmouseup = function(e) {
if (dragObj) {
dragObj = null;
window.removeEventListener('mousemove', dragObject, true);
window.removeEventListener('touchmove', dragObject, true);
}
}
}
makeDragable('#handle_1', '#moveable_1')
makeDragable('#handle_2', '#moveable_2')
</script>
</html>
Link to original code
Your problem was that you were storing a dragObj for each "window" inside the function call (captured via a closure). Hence when you switched to the other one, it all went a bit wrong. Moving the
let dragObj = null; line outside of your MakeDraggable function makes it work correctly.
You would be better developing a draggable/window class that encapsulates each window. You could then store a static variable that holds the dragObj there (rather than making it wholly global, as we have it now.
Let me know if you need any further help.
body {
background-image: url('https://www.betaarchive.com/imageupload/1304990899.or.90622.png');
font-family: "Pixelated MS Sans Serif",Arial;
font-size: 11px;
}
.grid-container {
display: grid;
gap: 10px;
font-size: 13px;
margin: 15px 35px 35px 35px;
}
.grid-container > div {
text-align: center;
margin: 10px 0px 10px 0px;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="https://unpkg.com/xp.css"/>
<link rel="stylesheet" href="styles_login.css"/>
<title>Login Screen</title>
</head>
<body>
<div id="moveable_1">
<div class="window" style="width: 350px; position: absolute; left: 100px; top: 150px;">
<div id="handle_1" class="title-bar">
<div class="title-bar-text">Login Screen</div>
</div>
<div class="window-content">
<div class="window-content-inner"></div>
<div class="status-bar">
<p class="status-bar-field">Test</p>
</div>
</div>
</div>
</div>
<div id="moveable_2">
<div class="window" style="width: 650px; position: absolute; left: 450px; top: 300px;">
<div id="handle_2" class="title-bar">
<div class="title-bar-text">Chat Screen</div>
</div>
<div class="window-content">
<div class="window-content-inner"></div>
<div class="status-bar">
<p class="status-bar-field">Test 2</p>
</div>
</div>
</div>
</div>
</body>
<script src="./renderer.js"></script>
<script> // Draggable Content JS
let dragObj = null; //object to be moved
function makeDraggable(dragHandle, dragTarget) {
let xOffset = 0; //used to prevent dragged object jumping to mouse location
let yOffset = 0;
document.querySelector(dragHandle).addEventListener("mousedown", startDrag, true);
document.querySelector(dragHandle).addEventListener("touchstart", startDrag, true);
/*sets offset parameters and starts listening for mouse-move*/
function startDrag(e) {
e.preventDefault();
e.stopPropagation();
dragObj = document.querySelector(dragTarget);
dragObj.style.position = "absolute";
let rect = dragObj.getBoundingClientRect();
if (e.type=="mousedown") {
xOffset = e.clientX - rect.left; //clientX and getBoundingClientRect() both use viewable area adjusted when scrolling aka 'viewport'
yOffset = e.clientY - rect.top;
window.addEventListener('mousemove', dragObject, true);
} else if(e.type=="touchstart") {
xOffset = e.targetTouches[0].clientX - rect.left;
yOffset = e.targetTouches[0].clientY - rect.top;
window.addEventListener('touchmove', dragObject, true);
}
}
/*Drag object*/
function dragObject(e) {
e.preventDefault();
e.stopPropagation();
if(dragObj == null) {
return; // if there is no object being dragged then do nothing
} else if(e.type=="mousemove") {
dragObj.style.left = e.clientX-xOffset +"px"; // adjust location of dragged object so doesn't jump to mouse position
dragObj.style.top = e.clientY-yOffset +"px";
} else if(e.type=="touchmove") {
dragObj.style.left = e.targetTouches[0].clientX-xOffset +"px"; // adjust location of dragged object so doesn't jump to mouse position
dragObj.style.top = e.targetTouches[0].clientY-yOffset +"px";
}
}
/*End dragging*/
document.onmouseup = function(e) {
if (dragObj) {
dragObj = null;
window.removeEventListener('mousemove', dragObject, true);
window.removeEventListener('touchmove', dragObject, true);
}
}
}
makeDraggable('#handle_1', '#moveable_1')
makeDraggable('#handle_2', '#moveable_2')
</script>
</html>

Unable to get proper position in Canvas using ES6 (why isn't this code working properly?)

I am trying make an paint app using ES6. But i am not getting proper position and line in canvas.
This line is not drawn in correct position, like top-left is formed when i click and from 0,0 corner of canvas.
As you can see Line is not starting from the point Cursor is pointing and this difference increases as we move from TOP-LEFT cornor to BOTTOM-RIGHT cornor.
const TOOL_LINE = 'line';
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
class Paint {
constructor(canvasId) {
this.canvas = document.getElementById(canvasId);
this.context = canvas.getContext("2d");
}
set activeTool(tool) {
this.tool = tool;
}
init() {
this.canvas.onmousedown = e => this.onMouseDown(e);
}
onMouseDown(e) {
this.saveData = this.context.getImageData(0, 0, this.canvas.clientWidth, this.canvas.clientHeight);
this.canvas.onmousemove = e => this.onMouseMove(e);
document.onmouseup = e => this.onMouseUp(e);
this.startPos = this.getMouseCoordinatesCanvas(e, this.canvas);
}
onMouseMove(e) {
this.currentPos = this.getMouseCoordinatesCanvas(e, this.canvas);
switch (this.tool) {
case TOOL_LINE:
this.drawShape();
break;
default:
break;
}
}
onMouseUp(e) {
this.canvas.onmousemove = null;
document.onmouseup = null;
}
drawShape() {
this.context.putImageData(this.saveData, 0, 0);
this.context.beginPath();
this.context.moveTo(this.startPos.x, this.startPos.y);
this.context.lineTo(this.currentPos.x, this.currentPos.y);
this.context.stroke();
}
getMouseCoordinatesCanvas(e, canvas) {
let rect = canvas.getBoundingClientRect();
let x = e.clientX - rect.left;
let y = e.clientY - rect.top;
return new Point(x, y);
}
}
var paint = new Paint("canvas");
paint.activeTool = TOOL_LINE;
paint.init();
document.querySelectorAll("[data-tools]").forEach(
item => {
item.addEventListener("click", e => {
let selectedTool = item.getAttribute("data-tools");
paint.activeTool = selectedTool;
});
}
);
#Container {
background-color: lime;
height: 310px;
}
.toolbox,
#canvas {
display: inline-block;
}
.toolbox {
background-color: gray;
padding: 0px 15px 15px 15px;
left: 10px;
top: 11px;
}
.group {
margin: 5px 2px;
}
#line {
transform: rotate(-90deg);
}
.ico {
margin: 3px;
font-size: 23px;
}
.item:hover,
.item.active {
background-color: rgba(160, 160, 160, 0.5);
color: white;
}
#canvas {
background-color: white;
margin: 5px;
float: right;
width: 400px;
height: 300px;
}
<script src="https://kit.fontawesome.com/c1d28c00bc.js" crossorigin="anonymous"></script>
<div class="container">
<div id="Container">
<div class="toolbox">
<center>
<div class="group tools">
<div class="item active" data-tools="line">
<i class="ico far fa-window-minimize" id="line" title="Line"></i>
</div>
</div>
</center>
</div>
<canvas id="canvas"></canvas>
</div>
</div>
Here is link of code.
Thanks in advance.
The issue is 1 or both of 2 things
Your canvas is being displayed at 400x300 but it only has 300x150 pixels. Canvases have 2 sizes. One size is the size they are displayed set with CSS. The other is how many pixels which is usually set in code by setting canvas.width and canvas.height. The default number of pixels is 300x150
If you actually want them to be different sizes then you need to take that into account in your mouse code. The correct code is
getMouseCoordinatesCanvas(e, canvas) {
let rect = canvas.getBoundingClientRect();
let x = (e.clientX - rect.left) * canvas.width / rect.width;
let y = (e.clientY - rect.top) * canvas.height / rect.height;
return new Point(x, y);
}
const TOOL_LINE = 'line';
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
class Paint {
constructor(canvasId) {
this.canvas = document.getElementById(canvasId);
this.context = canvas.getContext("2d");
}
set activeTool(tool) {
this.tool = tool;
}
init() {
this.canvas.onmousedown = e => this.onMouseDown(e);
}
onMouseDown(e) {
this.saveData = this.context.getImageData(0, 0, this.canvas.width, this.canvas.height);
this.canvas.onmousemove = e => this.onMouseMove(e);
document.onmouseup = e => this.onMouseUp(e);
this.startPos = this.getMouseCoordinatesCanvas(e, this.canvas);
}
onMouseMove(e) {
this.currentPos = this.getMouseCoordinatesCanvas(e, this.canvas);
switch (this.tool) {
case TOOL_LINE:
this.drawShape();
break;
default:
break;
}
}
onMouseUp(e) {
this.canvas.onmousemove = null;
document.onmouseup = null;
}
drawShape() {
this.context.putImageData(this.saveData, 0, 0);
this.context.beginPath();
this.context.moveTo(this.startPos.x, this.startPos.y);
this.context.lineTo(this.currentPos.x, this.currentPos.y);
this.context.stroke();
}
getMouseCoordinatesCanvas(e, canvas) {
let rect = canvas.getBoundingClientRect();
let x = (e.clientX - rect.left) * canvas.width / rect.width;
let y = (e.clientY - rect.top) * canvas.height / rect.height;
return new Point(x, y);
}
}
var paint = new Paint("canvas");
paint.activeTool = TOOL_LINE;
paint.init();
document.querySelectorAll("[data-tools]").forEach(
item => {
item.addEventListener("click", e => {
let selectedTool = item.getAttribute("data-tools");
paint.activeTool = selectedTool;
});
}
);
#Container {
background-color: lime;
height: 310px;
}
.toolbox,
#canvas {
display: inline-block;
}
.toolbox {
background-color: gray;
padding: 0px 15px 15px 15px;
left: 10px;
top: 11px;
}
.group {
margin: 5px 2px;
}
#line {
transform: rotate(-90deg);
}
.ico {
margin: 3px;
font-size: 23px;
}
.item:hover,
.item.active {
background-color: rgba(160, 160, 160, 0.5);
color: white;
}
#canvas {
background-color: white;
margin: 5px;
float: right;
width: 400px;
height: 300px;
}
<script src="https://kit.fontawesome.com/c1d28c00bc.js" crossorigin="anonymous"></script>
<div class="container">
<div id="Container">
<div class="toolbox">
<center>
<div class="group tools">
<div class="item active" data-tools="line">
<i class="ico far fa-window-minimize" id="line" title="Line"></i>
</div>
</div>
</center>
</div>
<canvas id="canvas"></canvas>
</div>
</div>
If you don't want them to be different sizes then you need to make the sizes match. I always set the size using CSS and then use code to make the canvas match that size.
Something like this
function resizeCanvasToDisplaySize(canvas) {
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
canvas.width = width;
canvas.height = height;
}
return needResize;
}
Note that anytime you change the canvas size it will get cleared but in any case.
const TOOL_LINE = 'line';
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
function resizeCanvasToDisplaySize(canvas) {
const width = canvas.clientWidth;
const height = canvas.clientHeight;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
canvas.width = width;
canvas.height = height;
}
return needResize;
}
class Paint {
constructor(canvasId) {
this.canvas = document.getElementById(canvasId);
this.context = canvas.getContext("2d");
resizeCanvasToDisplaySize(canvas);
}
set activeTool(tool) {
this.tool = tool;
}
init() {
this.canvas.onmousedown = e => this.onMouseDown(e);
}
onMouseDown(e) {
this.saveData = this.context.getImageData(0, 0, this.canvas.width, this.canvas.height);
this.canvas.onmousemove = e => this.onMouseMove(e);
document.onmouseup = e => this.onMouseUp(e);
this.startPos = this.getMouseCoordinatesCanvas(e, this.canvas);
}
onMouseMove(e) {
this.currentPos = this.getMouseCoordinatesCanvas(e, this.canvas);
switch (this.tool) {
case TOOL_LINE:
this.drawShape();
break;
default:
break;
}
}
onMouseUp(e) {
this.canvas.onmousemove = null;
document.onmouseup = null;
}
drawShape() {
this.context.putImageData(this.saveData, 0, 0);
this.context.beginPath();
this.context.moveTo(this.startPos.x, this.startPos.y);
this.context.lineTo(this.currentPos.x, this.currentPos.y);
this.context.stroke();
}
getMouseCoordinatesCanvas(e, canvas) {
let rect = canvas.getBoundingClientRect();
let x = (e.clientX - rect.left) * canvas.width / rect.width;
let y = (e.clientY - rect.top) * canvas.height / rect.height;
return new Point(x, y);
}
}
var paint = new Paint("canvas");
paint.activeTool = TOOL_LINE;
paint.init();
document.querySelectorAll("[data-tools]").forEach(
item => {
item.addEventListener("click", e => {
let selectedTool = item.getAttribute("data-tools");
paint.activeTool = selectedTool;
});
}
);
#Container {
background-color: lime;
height: 310px;
}
.toolbox,
#canvas {
display: inline-block;
}
.toolbox {
background-color: gray;
padding: 0px 15px 15px 15px;
left: 10px;
top: 11px;
}
.group {
margin: 5px 2px;
}
#line {
transform: rotate(-90deg);
}
.ico {
margin: 3px;
font-size: 23px;
}
.item:hover,
.item.active {
background-color: rgba(160, 160, 160, 0.5);
color: white;
}
#canvas {
background-color: white;
margin: 5px;
float: right;
width: 400px;
height: 300px;
}
<script src="https://kit.fontawesome.com/c1d28c00bc.js" crossorigin="anonymous"></script>
<div class="container">
<div id="Container">
<div class="toolbox">
<center>
<div class="group tools">
<div class="item active" data-tools="line">
<i class="ico far fa-window-minimize" id="line" title="Line"></i>
</div>
</div>
</center>
</div>
<canvas id="canvas"></canvas>
</div>
</div>
A common reason to make them different sizes is to support HI-DPI displays. In that case though the mouse code can go back to the way it was if you use the canvas transform.
function resizeCanvasToDisplaySize(canvas) {
const width = canvas.clientWidth * devicePixelRatio | 0;
const height = canvas.clientHeight * devicePixelRatio | 0;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
canvas.width = width;
canvas.height = height;
}
return needResize;
}
and then set the transform before drawing
ctx.scale(devicePixelRatio, devicePixelRatio);
const TOOL_LINE = 'line';
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
function resizeCanvasToDisplaySize(canvas) {
const width = canvas.clientWidth * devicePixelRatio | 0;
const height = canvas.clientHeight * devicePixelRatio | 0;
const needResize = canvas.width !== width || canvas.height !== height;
if (needResize) {
canvas.width = width;
canvas.height = height;
}
return needResize;
}
class Paint {
constructor(canvasId) {
this.canvas = document.getElementById(canvasId);
this.context = canvas.getContext("2d");
resizeCanvasToDisplaySize(canvas);
}
set activeTool(tool) {
this.tool = tool;
}
init() {
this.canvas.onmousedown = e => this.onMouseDown(e);
}
onMouseDown(e) {
this.saveData = this.context.getImageData(0, 0, this.canvas.width, this.canvas.height);
this.canvas.onmousemove = e => this.onMouseMove(e);
document.onmouseup = e => this.onMouseUp(e);
this.startPos = this.getMouseCoordinatesCanvas(e, this.canvas);
}
onMouseMove(e) {
this.currentPos = this.getMouseCoordinatesCanvas(e, this.canvas);
switch (this.tool) {
case TOOL_LINE:
this.drawShape();
break;
default:
break;
}
}
onMouseUp(e) {
this.canvas.onmousemove = null;
document.onmouseup = null;
}
drawShape() {
this.context.setTransform(1, 0, 0, 1, 0, 0); // the default
this.context.putImageData(this.saveData, 0, 0);
this.context.scale(devicePixelRatio, devicePixelRatio);
this.context.beginPath();
this.context.moveTo(this.startPos.x, this.startPos.y);
this.context.lineTo(this.currentPos.x, this.currentPos.y);
this.context.stroke();
}
getMouseCoordinatesCanvas(e, canvas) {
let rect = canvas.getBoundingClientRect();
let x = (e.clientX - rect.left);
let y = (e.clientY - rect.top);
return new Point(x, y);
}
}
var paint = new Paint("canvas");
paint.activeTool = TOOL_LINE;
paint.init();
document.querySelectorAll("[data-tools]").forEach(
item => {
item.addEventListener("click", e => {
let selectedTool = item.getAttribute("data-tools");
paint.activeTool = selectedTool;
});
}
);
#Container {
background-color: lime;
height: 310px;
}
.toolbox,
#canvas {
display: inline-block;
}
.toolbox {
background-color: gray;
padding: 0px 15px 15px 15px;
left: 10px;
top: 11px;
}
.group {
margin: 5px 2px;
}
#line {
transform: rotate(-90deg);
}
.ico {
margin: 3px;
font-size: 23px;
}
.item:hover,
.item.active {
background-color: rgba(160, 160, 160, 0.5);
color: white;
}
#canvas {
background-color: white;
margin: 5px;
float: right;
width: 400px;
height: 300px;
}
<script src="https://kit.fontawesome.com/c1d28c00bc.js" crossorigin="anonymous"></script>
<div class="container">
<div id="Container">
<div class="toolbox">
<center>
<div class="group tools">
<div class="item active" data-tools="line">
<i class="ico far fa-window-minimize" id="line" title="Line"></i>
</div>
</div>
</center>
</div>
<canvas id="canvas"></canvas>
</div>
</div>
note this line
this.saveData = this.context.getImageData(0, 0, this.canvas.clientWidth, this.canvas.clientHeight);
was wrong too. It should be
this.saveData = this.context.getImageData(0, 0, this.canvas.width, this.canvas.height);
clientWidth and clientHeight are the display size. width and height are the resolution (number of pixels in the canvas)

Drag and drop change image with switch

i am working on my game but i have some problems...
1. if the image is in the class .room it has a another src but if you drop it in the class .items it should change to a icon. And if you drag it again to .room it will turn back.
2. There are many different image so i want to have a switch. if the draged objekt is dragging to .items the image should change. so the id of the image should go to the switch and check if the id and case is the same. the scr should be from the icon.
3. if it is possible i want to safe the id of the image in local.storage so i can use the objekt in the next page
<html>
<head>
<style>
.room {
width: 500px;
height: 150px;
margin: 10px;
padding: 10px;
border: 1px solid black;
}
.items {
width: 500px;
height: 150px;
margin: 10px;
padding: 10px;
border: 1px solid black;
}
</style>
<script>
function allowDrop(ev) {
if (ev.target.className === "items") {
ev.target.style.border = "3px dashed black";
}
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("img", ev.target.id);
}
function dragleave(ev) {
if (ev.target.className === "items") {
ev.target.style.border = "0px dashed transparent";
}
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("img");
ev.target.style.border = "0px dashed transparent";
if (ev.target=="[object HTMLImageElement]"){
ev.target = ev.target.parentNode;
}
else {
ev.target.appendChild(document.getElementById(data));
}
if (ev.target.id === ev.dataTransfer.getData("ori")) {
return;
}
var image = document.createElement("img");
image.id =
image.draggable = true;
image.addEventListener('dragstart', drag);
if (ev.target.className === 'items') {
icon();
} else if (ev.target.className === 'room') {
room();
}
var originEle = document.getElementById(ev.dataTransfer.getData("ori"));
originEle.outerHTML = '';
delete originEle;
ev.target.appendChild(image);
}
function icon(){
switch(image.id) {
case "teddy": image.src="pic/Icons/teddy.png";break;
case "book": image.src="pic/Icons/Buch.png";break;
}
}
function room(){
switch(image.id) {
case "teddy": image.src= "pic/Home/HomeRoom_booksL.png";break;
case "booksR": image.src= "pic/Home/HomeRoom_buch.png";break;}
}
function reset(){
var container = document.getElementById("field");
container.innerHTML= html;
}
var html;
window.onload = function(){
html = document.getElementById('field').innerHTML;
};
</script>
</head>
<body>
<h2>Drag and Drop</h2>
<div>
<div class="room" ondrop="drop(event)" ondragover="allowDrop(event)">
</div>
<h2>items</h2>
<div class="items" ondrop="drop(event)" ondragover="allowDrop(event)">
<img id="book" src="pic/Icons/Buch.png" draggable="true" ondragstart="drag(event)" id="drag1">
<img id="teddy" alt="booksL"src="pic/Home/HomeRoom_teddy.png" id="drag2" draggable="true" ondragstart="drag(event)" >
</div>
</div>
</body>
</html>
About the 3rd question - saving to localStorage:
add the code below to your drop function.
localStorage.setItem("name", data);

Draggable editable field

I want to have an editable field that I can drag and drop. Here is my code (the red div is the drop zone) :
function drag(ev) {
let targetId = ev.target.id;
let rect = document.getElementById(targetId).getBoundingClientRect();
ev.dataTransfer.setData("targetId", targetId);
let offsetX = ev.clientX - rect.left;
let offsetY = ev.clientY - rect.top;
ev.dataTransfer.setData("offsetX", offsetX);
ev.dataTransfer.setData("offsetY", offsetY);
}
function drop(ev) {
let targetId = ev.dataTransfer.getData("targetId");
let offsetX = parseInt(ev.dataTransfer.getData("offsetX"));
let offsetY = parseInt(ev.dataTransfer.getData("offsetY"));
let dropX = ev.clientX - offsetX;
let dropY = ev.clientY - offsetY;
let el = document.getElementById(targetId);
el.style.left = dropX + "px";
el.style.top = dropY + "px";
ev.preventDefault();
}
function allowDrop(ev) {
ev.preventDefault();
}
.item {
min-width: 25px;
position: absolute;
border: solid;
background: white;
}
#item1 {
padding: 3px;
}
#drop-zone {
width: 300px;
height: 200px;
background: red;
border: solid;
}
<div id="drop-zone" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<br>
<span class="item" contenteditable="true" draggable="true" ondragstart="drag(event)">Item1</span>
<br><br>
<div id="item1" class="item" draggable="true" ondragstart="drag(event)">
<span contenteditable="true">Item2</span>
</div>
I made 2 tests. My first test is Item1, where the <span> itself is draggable. Unfortunately, the browser cannot differenciate between "place the cursor" and "drag the element", so Item1 is not draggable.
Then my idea was to have a border around the field on which we would click to grab the element, so I made Item2 where I put the <span> in a containing <div>. But now the problem is that, as the div is draggable, the span also is draggable, but I want to place the cursor freely in the span, and when I click on the span to write some text, the cursor is always at the beginning. How should I do ?
Note : when I remove the padding: 3px line, Item2 doesn't work.
Thank you for your help.

HTML5 drag and drop, dropped div moves a bit from dropped position

I have the following working code (also see this fiddle):
<!DOCTYPE HTML>
<html>
<head>
<style>
#div1 {width:350px;height:170px;padding:10px;border:1px solid #aaaaaa;}
#drag1 {width:50px;height:50px;padding:10px;border:1px solid #000;background-color: #f00; position: absolute;}
</style>
<script>
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("text/html", ev.target.id);
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text/html");
ev.target.appendChild(document.getElementById(data));
//window.alert( ev.clientX + ',' + ev.clientY);
document.getElementById("drag1").style.left = ev.clientX + 'px';
document.getElementById("drag1").style.top = ev.clientY + 'px';
return false;
}
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)">
<div id="drag1" draggable="true" ondragstart="drag(event)"></div>
</div>
</body>
</html>
Here you can drag and drop a colored div only inside the main div. The problem is that this red div jumps a bit from his dropped position. I think this is because I use the mouse ev.clientX and Y. So how can I fix this so the DIV stays at the dropped position?
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("text/html", ev.target.id);
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text/html");
ev.target.appendChild(document.getElementById(data));
//window.alert( ev.clientX + ',' + ev.clientY);
document.getElementById("drag1").style.left = ev.clientX + 'px';
document.getElementById("drag1").style.top = ev.clientY + 'px';
return false;
}
#div1 {width:350px;height:170px;padding:10px;border:1px solid #aaaaaa;}
#drag1 {width:50px;height:50px;padding:10px;border:1px solid #000;background-color: #f00; position: absolute;}
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)">
<div id="drag1" draggable="true" ondragstart="drag(event)"></div>
</div>
You're dropping the div's top left corner to the mouse's location, you have to find the offset from inside the div where the mouse is actually dragging. By checking the event object(in chrome), offsetX and offsetY and layerX and layerY seem to have the offset from the origin of the div to the mouse.
Here is a question with alot of discussion on offsetXY and layerXY and associated properties event.offsetX in Firefox, note: don't just read the accepted answer.
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("application/json",
JSON.stringify([ev.target.id,
(ev.offsetX || ev.clientX - $(ev.target).offset().left),
(ev.offsetY || ev.clientY - $(ev.target).offset().top)]
));
}
function drop(ev) {
ev.preventDefault();
var data = JSON.parse(ev.dataTransfer.getData("application/json"));
ev.target.appendChild(document.getElementById(data[0]));
//window.alert( ev.clientX + ',' + ev.clientY);
document.getElementById("drag1")
.style.left = ev.clientX - data[1] + 'px';
document.getElementById("drag1").style.top = ev.clientY - data[2] + 'px';
return false;
}
#div1 { width:350px; height:170px; padding:10px; border:1px solid #aaaaaa; }
#drag1 { width:50px; height:50px; padding:10px; border:1px solid #000; background-color: #f00; position: absolute; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)">
<div id="drag1" draggable="true" ondragstart="drag(event)"></div>
</div>

Categories