Automatic drag and drop with a click - javascript

I'm looking for an automatic drag and dropper. First, when I click anywhere on the screen, get coordinates, then drag and drop an element with the ID of "ball". using jQuery OR javascript.
I coded a similar script to what I want, but this script got patched when the website's client got updated. This one automatically dragged and dropped when I pressed key 1(keycode 49),
(function () {
'use strict';
var mouseX = 0;
var mouseY = 0;
var invName = '';
var timer = 0;
document.body.addEventListener('mousemove', function (e) {
mouseX = e.clientX;
mouseY = e.clientY;
});
$('.inventory-box').mousedown(function (e) {invName = e.currentTarget.id;});
function drop () {
$('#' + invName).trigger($.Event('mousedown', {button: 0}));
$('body').trigger($.Event('mouseup', {
button: 0,
clientX: mouseX,
clientY: mouseY
}));
timer = setTimeout(drop, 100);
}
window.addEventListener('keyup', function (e) {
if (e.keyCode == 49 && !timer) {
invName = 'ball';
drop();
setTimeout(function () {
(clearTimeout(timer), timer = 0);
}, 20);
}
});
})();

when I click anywhere on the screen, it gets it's coordinates, then drag and drops an element with the ID of "ball"
Here's a very simple vanilla JavaScript method that will locate an element with the ID of "ball" at the cursor location upon click.
The "ball" will follow the cursor until the next click, then the ball will be dropped at the click location.
const ball = document.getElementById('ball');
const ballHalfHeight = Math.round(ball.offsetHeight / 2);
const ballHalfWidth = Math.round(ball.offsetWidth / 2);
let dragState = false;
// move ball to position
function moveBallTo(x, y) {
ball.style.top = y - ballHalfHeight + 'px';
ball.style.left = x - ballHalfWidth + 'px';
}
// listen for 'mousemove' and drag ball
function dragListener(evt) {
const {clientX, clientY} = evt;
moveBallTo(clientX, clientY);
};
// respond to 'click' events (start or finish dragging)
window.addEventListener('click', (evt) => {
const {clientX, clientY} = evt;
moveBallTo(clientX, clientY);
ball.classList.remove('hidden');
// handle dragging
if (!dragState) {
window.addEventListener('mousemove', dragListener);
} else {
window.removeEventListener('mousemove', dragListener);
}
dragState = !dragState;
});
.div-ball {
position: fixed;
background-color: dodgerblue;
width: 2rem;
height: 2rem;
border-radius: 1rem;
}
.hidden {
opacity: 0;
}
<body>
<h4>Click anywhere</h4>
<div class="div-ball hidden" id="ball"></div>
</body>

Related

How can we force canvas to stay still

How can one force a canvas to remain still while you draw on it on android phones?
We have a project in Ionic, where the below code is used to allow the end user to draw on a canvas element, but when he starts drawing, the page scrolls with him.
Strange enough though, the code stops the form from scrolling up and down if the user drags left or right, but if they move their finger up or down before going left or right, the page scrolls with their draw movements, and they end up with basically nothing being drawn...
Does anybody see how I can force the scrolling to hold while the user draw's on the canvas?
//employer_signature_canvas setup
var employer_signature_canvas = document.getElementById("employer_my_canvas");
var ctx = employer_signature_canvas.getContext("2d");
ctx.strokeStyle = "#222222";
ctx.lineWith = 2;
// Set up mouse events for drawing
var drawing = false;
var mousePos = { x:0, y:0 };
var lastPos = mousePos;
employer_signature_canvas.addEventListener("mousedown", function (e) {
drawing = true;
lastPos = getMousePos(employer_signature_canvas, e);
}, false);
employer_signature_canvas.addEventListener("mouseup", function (e) {
drawing = false;
}, false);
employer_signature_canvas.addEventListener("mousemove", function (e) {
mousePos = getMousePos(employer_signature_canvas, e);
}, false);
// Get the position of the mouse relative to the employer_signature_canvas
function getMousePos(employer_signature_canvasDom, mouseEvent) {
var rect = employer_signature_canvasDom.getBoundingClientRect();
return {
x: mouseEvent.clientX - rect.left,
y: mouseEvent.clientY - rect.top
};
}
// Get a regular interval for drawing to the screen
window.requestAnimFrame = (function (callback) {
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimaitonFrame ||
function (callback) {
window.setTimeout(callback, 1000/60);
};
})();
// Draw to the employer_signature_canvas
function renderemployer_signature_canvas() {
if (drawing) {
ctx.moveTo(lastPos.x, lastPos.y);
ctx.lineTo(mousePos.x, mousePos.y);
ctx.stroke();
lastPos = mousePos;
}
}
// Allow for animation
(function drawLoop () {
requestAnimFrame(drawLoop);
renderemployer_signature_canvas();
})();
// Set up touch events for mobile, etc
employer_signature_canvas.addEventListener("touchstart", function (e) {
mousePos = getTouchPos(employer_signature_canvas, e);
var touch = e.touches[0];
var mouseEvent = new MouseEvent("mousedown", {
clientX: touch.clientX,
clientY: touch.clientY
});
employer_signature_canvas.dispatchEvent(mouseEvent);
}, false);
employer_signature_canvas.addEventListener("touchend", function (e) {
var mouseEvent = new MouseEvent("mouseup", {});
employer_signature_canvas.dispatchEvent(mouseEvent);
}, false);
employer_signature_canvas.addEventListener("touchmove", function (e) {
var touch = e.touches[0];
var mouseEvent = new MouseEvent("mousemove", {
clientX: touch.clientX,
clientY: touch.clientY
});
employer_signature_canvas.dispatchEvent(mouseEvent);
}, false);
// Get the position of a touch relative to the employer_signature_canvas
function getTouchPos(employer_signature_canvasDom, touchEvent) {
var rect = employer_signature_canvasDom.getBoundingClientRect();
return {
x: touchEvent.touches[0].clientX - rect.left,
y: touchEvent.touches[0].clientY - rect.top
};
}
// Prevent scrolling when touching the employer_signature_canvas
document.body.addEventListener("touchstart", function (e) {
if (e.target == employer_signature_canvas) {
e.preventDefault();
}
}, false);
document.body.addEventListener("touchend", function (e) {
if (e.target == employer_signature_canvas) {
e.preventDefault();
}
}, false);
document.body.addEventListener("touchmove", function (e) {
if (e.target == employer_signature_canvas) {
e.preventDefault();
}
}, false);
In your template (ionic page) you can use css to remove bounce and rubberband effects:
<ion-content no-bounce class="no-scroll"><ion-content>
in your scss:
.no-scroll .scroll-content {
overflow: hidden;
float: none;
}

Javascript help handling mouseclick in canvas

I'm trying to get my inputhandler to work in Javascript.
What
In my Game.update I currently have this code:
this.Update = function() {
if (input.GetMousePressed()) {
console.log(input.GetMousePosition());
}
}
And this is my inputhandler:
function InputHandler(canvas) {
this.canvas = canvas;
this.mousePressed = false;
this.mouseDown = false;
this.mousePosition = new Position(0, 0);
this.GetMousePosition = function() {
return this.mousePosition;
}
this.SetMousePosition = function(event) {
var rect = this.canvas.getBoundingClientRect();
this.mousePosition = new Position(event.clientX - rect.left, event.clientY - rect.top);
}
this.GetMousePressed = function() {
return this.mousePressed;
}
this.canvas.onmousedown = function(event) {
input.mouseDown = true;
input.SetMousePosition(event);
}
this.canvas.onclick = function(event) {
input.mouseClicked = true;
input.SetMousePosition(event);
}
window.onmouseup = function(event) {
if (input.mouseDown == true) {
input.mousePressed = true;
input.mouseDown = false;
}
}
The first problem is that I dont know how to handle mousePressed and set it to false. Now it stays true forever.
I'm quite new to Javascript and I'm thankful for any change that would make this better or cleaner code or if what Im doing is bad practice.
I'm using addEventListener for normal button pressing and maybe I should for this to?
Not sure why you need mousepressed/mouseup and click events. The only difference between successful pressed/up and click is that click target should be the same element.
So I would either use the first option or the last but not both.
Your mousePressed flag is set to true because it gets assigned true value once you press the mouse. You need to reset it back to false at some point.
Usually, you don't even need this flag since you trigger whatever function you need inside mousepressed event. Not sure why you would save the information that this happened, do you use it somewhere else?
Also, yes using addEventListener would be better.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
body {
background-color: black;
}
canvas {
position: absolute;
margin: auto;
left: 0;
right: 0;
border: solid 1px white;
border-radius: 10px;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script type="application/javascript">
var imageWidth = 180;
var imageHeight = 160;
var canvas = null;
var ctx = null;
var mouseDown = false;
var mouseX = 0;
var mouseY = 0;
var bounds = null;
function canvas_onmousedown(e) {
mouseDown = true;
}
function canvas_onmousemove(e) {
if (mouseDown) {
mouseX = e.clientX - bounds.left;
mouseY = e.clientY - bounds.top;
}
}
function canvas_onmouseup(e) {
mouseDown = false;
}
function loop() {
ctx.fillStyle = "gray";
ctx.fillRect(0,0,imageWidth,imageHeight);
if (mouseDown) {
ctx.fillStyle = "yellow";
} else {
ctx.fillStyle = "black";
}
ctx.fillRect(mouseX - 25,mouseY - 25,50,50);
requestAnimationFrame(loop);
}
window.onload = function() {
canvas = document.getElementById("canvas");
canvas.width = imageWidth;
canvas.height = imageHeight;
canvas.onmousedown = canvas_onmousedown;
canvas.onmousemove = canvas_onmousemove;
canvas.onmouseup = canvas_onmouseup;
ctx = canvas.getContext("2d");
bounds = canvas.getBoundingClientRect();
requestAnimationFrame(loop);
}
</script>
</body>
</html>

Move an image with Javascript using mouse events

This should be simple enough, but every time I try I end up with a different issue.
I am trying to move an image around the screen using mouse events such as mousedown, mouseup, mousemove, clientX and clientY. I am then trying to apply it to the image using absolute positioning.
I thought the below code would work as I get the coordinates on the initial click, and then the idea was to update them with mouse movement, but this does not work.
var image;
var dog = document.getElementById("dogPic");
var cat = document.getElementById("catPic");
dog.addEventListener("mousedown", initialClick, false);
cat.addEventListener("mousedown", initialClick, false);
function initialClick(e) {
var initialX = e.clientX;
var initialY = e.clientY;
image = document.getElementById(this.id);
document.addEventListener("mousemove", function(e){
var newX = e.clientX - initialX;
var newY = e.clientY - initialY;
image.style.left = newX;
image.style.top = newY;
}, false);
}
I am not asking for a complete answer, but can anyone direct me as to how I can approach dragging an image around the screen using the mouse movement events?
Thanks
var dog = document.getElementById("dogPic");
var cat = document.getElementById("catPic");
var moving = false;
dog.addEventListener("mousedown", initialClick, false);
cat.addEventListener("mousedown", initialClick, false);
function move(e){
var newX = e.clientX - 10;
var newY = e.clientY - 10;
image.style.left = newX + "px";
image.style.top = newY + "px";
}
function initialClick(e) {
if(moving){
document.removeEventListener("mousemove", move);
moving = !moving;
return;
}
moving = !moving;
image = this;
document.addEventListener("mousemove", move, false);
}
#dogPic, #catPic {
width: 20px;
height: 20px;
position: absolute;
background: red;
top: 10px;
left: 10px;
}
#dogPic {
background: blue;
top: 50px;
left: 50px;
}
<div id="dogPic"></div>
<div id="catPic"></div>
I made a modification to have a more realistic dragging experience. This required adding an X and Y offset so instead of jumping when picked up, the object seems to just move as expected.
let gMouseDownX = 0;
let gMouseDownY = 0;
let gMouseDownOffsetX = 0;
let gMouseDownOffsetY = 0;
function addListeners() {
document.getElementById('cursorImage').addEventListener('mousedown', mouseDown, false);
window.addEventListener('mouseup', mouseUp, false);
}
function mouseUp() {
window.removeEventListener('mousemove', divMove, true);
}
function mouseDown(e) {
gMouseDownX = e.clientX;
gMouseDownY = e.clientY;
var div = document.getElementById('cursorImage');
//The following block gets the X offset (the difference between where it starts and where it was clicked)
let leftPart = "";
if(!div.style.left)
leftPart+="0px"; //In case this was not defined as 0px explicitly.
else
leftPart = div.style.left;
let leftPos = leftPart.indexOf("px");
let leftNumString = leftPart.slice(0, leftPos); // Get the X value of the object.
gMouseDownOffsetX = gMouseDownX - parseInt(leftNumString,10);
//The following block gets the Y offset (the difference between where it starts and where it was clicked)
let topPart = "";
if(!div.style.top)
topPart+="0px"; //In case this was not defined as 0px explicitly.
else
topPart = div.style.top;
let topPos = topPart.indexOf("px");
let topNumString = topPart.slice(0, topPos); // Get the Y value of the object.
gMouseDownOffsetY = gMouseDownY - parseInt(topNumString,10);
window.addEventListener('mousemove', divMove, true);
}
function divMove(e){
var div = document.getElementById('cursorImage');
div.style.position = 'absolute';
let topAmount = e.clientY - gMouseDownOffsetY;
div.style.top = topAmount + 'px';
let leftAmount = e.clientX - gMouseDownOffsetX;
div.style.left = leftAmount + 'px';
}
addListeners();
<div style="height:500px;width:500;background-color:blue;">
<img src="http://placehold.it/100x100" id="cursorImage" ondragstart="return false;"/>
</div>
This code work with just plain javascript
function addListeners() {
document.getElementById('image').addEventListener('mousedown', mouseDown, false);
window.addEventListener('mouseup', mouseUp, false);
}
function mouseUp() {
window.removeEventListener('mousemove', divMove, true);
}
function mouseDown() {
window.addEventListener('mousemove', divMove, true);
}
function divMove(e){
var div = document.getElementById('image');
div.style.position = 'absolute';
div.style.top = e.clientY + 'px';
div.style.left = e.clientX + 'px';
}
addListeners();
<div style="height:500px;width:500;background-color:blue;">
<img src="http://placehold.it/100x100" id="image" />
</div>
Super simple working code with Jquery. Live demo: http://jsfiddle.net/djjL16p2/
<div id="content" style="margin-top: 100px">
<img id="lolcat" src="http://obeythekitty.com/wp-content/uploads/2015/01/lolcat_airplane.jpg" style="height: 100px; width: 120px; position: absolute;" draggable="false" />
</div>
JS:
$("#lolcat").mousedown(function() {
$(this).data("dragging", true);
});
$("#lolcat").mouseup(function() {
$(this).data("dragging", false);
});
$("#lolcat").mousemove(function(e) {
if (!$(this).data("dragging"))
return;
$(this).css("left", e.clientX - $(this).width()/2);
$(this).css("top", e.clientY - $(this).height()/2);
});

Using Mouse Drag To Control Background Position

I want to use the 'mouse's drag' to drag a background's position around, inside a box.
The CSS:
.filmmakers #map {
width : 920px;
height : 500px;
margin-top : 50px;
margin-left : 38px;
border : 1px solid rgb(0, 0, 0);
cursor : move;
overflow : hidden;
background-image : url('WorldMap.png');
background-repeat : no-repeat;
}
The html:
<div id = "map" src = "WorldMap.png" onmousedown = "MouseMove(this)"> </div>
The Javascript:
function MouseMove (e) {
var x = e.clientX;
var y = e.clientY;
e.style.backgroundPositionX = x + 'px';
e.style.backgroundPositionY = y + 'px';
e.style.cursor = "move";
}
Nothing happens, no errors, no warnings, nothing... I have tried lots of things: an absolutely positioned image inside a div (you can guess why that didn't work), A draggable div inside a div with a background image, a table with drag and drop, and finally I tried this:
function MouseMove () {
e.style.backgroundPositionX = 10 + 'px';
e.style.backgroundPositionY = 10 + 'px';
e.style.cursor = "move";
}
This works, but its not relative to the mouse's position, pageX and pageY don't work either.
A live demo: http://jsfiddle.net/VRvUB/224/
P.S: whatever your idea is, please don't write it in JQuery
From your question I understood you needed help implementing the actual "dragging" behavior. I guess not. Anyway, here's the results of my efforts: http://jsfiddle.net/joplomacedo/VRvUB/236/
The drag only happens when the mouse button, and.. well, it behaves as I think you might want it to. Just see the fiddle if you haven't =)
Here's the code for those who want to see it here:
var AttachDragTo = (function () {
var _AttachDragTo = function (el) {
this.el = el;
this.mouse_is_down = false;
this.init();
};
_AttachDragTo.prototype = {
onMousemove: function (e) {
if ( !this.mouse_is_down ) return;
var tg = e.target,
x = e.clientX,
y = e.clientY;
tg.style.backgroundPositionX = x - this.origin_x + this.origin_bg_pos_x + 'px';
tg.style.backgroundPositionY = y - this.origin_y + this.origin_bg_pos_y + 'px';
},
onMousedown: function(e) {
this.mouse_is_down = true;
this.origin_x = e.clientX;
this.origin_y = e.clientY;
},
onMouseup: function(e) {
var tg = e.target,
styles = getComputedStyle(tg);
this.mouse_is_down = false;
this.origin_bg_pos_x = parseInt(styles.getPropertyValue('background-position-x'), 10);
this.origin_bg_pos_y = parseInt(styles.getPropertyValue('background-position-y'), 10);
},
init: function () {
var styles = getComputedStyle(this.el);
this.origin_bg_pos_x = parseInt(styles.getPropertyValue('background-position-x'), 10);
this.origin_bg_pos_y = parseInt(styles.getPropertyValue('background-position-y'), 10);
//attach events
this.el.addEventListener('mousedown', this.onMousedown.bind(this), false);
this.el.addEventListener('mouseup', this.onMouseup.bind(this), false);
this.el.addEventListener('mousemove', this.onMousemove.bind(this), false);
}
};
return function ( el ) {
new _AttachDragTo(el);
};
})();
/*** IMPLEMENTATION ***/
//1. Get your element.
var map = document.getElementById('map');
//2. Attach the drag.
AttachDragTo(map);
​
This isn't working because you are passing the element "map" to your MouseMove function, and using it as both an event object and an element. You can fix this painlessly by using JavaScript to assign your event handler rather than HTML attributes:
<div id="map"></div>
And in your JavaScript:
document.getElementById('map').onmousemove = function (e) {
// the first parameter (e) is automatically assigned an event object
var x = e.clientX;
var y = e.clientY;
// The context of this is the "map" element
this.style.backgroundPositionX = x + 'px';
this.style.backgroundPositionY = y + 'px';
}
http://jsfiddle.net/VRvUB/229/
The downside of this approach is that the backgroundPositionX and backgroundPositionY style properties are not supported in all browsers.
You mention "an absolutely positioned image inside a div" which is probably the more compatible solution for this. To make this setup work, you need to set the position of the outer element to relative, which makes absolute child elements use its bounds as zero.
<div id="map">
<img src="" alt="">
</div>
CSS:
#map {
position:relative;
overflow:hidden;
}
#map img {
position:absolute;
left:0;
top:0;
}
Here it is applied to your code: http://jsfiddle.net/VRvUB/232/
This works 100%
Vanilla Javascript
document.getElementById('image').onmousemove = function (e) {
var x = e.clientX;
var y = e.clientY;
this.style.backgroundPositionX = -x + 'px';
this.style.backgroundPositionY = -y + 'px';
this.style.backgroundImage = 'url(https://i.ibb.co/vhL5kH2/image-14.png)';
}
document.getElementById('image').onmouseleave = function (e) {
this.style.backgroundPositionX = 0 + 'px';
this.style.backgroundPositionY = 0 + 'px';
this.style.backgroundImage = 'url(https://i.ibb.co/Ph9MCB2/template.png)';
}
.container {
max-width: 670px;
height: 377px;
}
#image {
max-width: 670px;
height: 377px;
cursor: crosshair;
overflow: hidden;
background-image: url('https://i.ibb.co/Ph9MCB2/template.png');
background-repeat: no-repeat;
}
<div class="container">
<div id="image">
</div>
</div>

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