I have an element which I would like to move with the mouse.
var troll = document.getElementById('troll');
troll.addEventListener('dragover', (e) => {
e.preventDefault();
e.target.style.left = e.clientX + 'px';
e.target.style.top = e.clientY + 'px';
}, false);
img {
width: 100px;
cursor: pointer;
position: absolute;
}
<div id="troll">
<img src="http://images.mmorpg.com/features/7909/images/Troll.png" alt="Troll">
</div>
From left to right and from top to bottom it works OK. Not perfect, since the very first move takes a whole space and it doesn't look smooth. But the main problem is that I can't move from right to left or from bottom to top.
Any help would be appreciated.
You wanna use drag not dragover, and some logic to know where you're going up or down or left or top.
var troll = document.getElementById('troll');
var X,Y = 0;
troll.addEventListener('drag', (e) => {
e.preventDefault();
if (e.clientX > X)
{
e.target.style.left = X + 'px';
}
else if (e.clientX < X)
{
e.target.style.left = X-- + 'px';
}
if (e.clientY > Y)
{
e.target.style.top = Y + 'px';
}
else if (e.clientY < Y)
{
e.target.style.top = Y-- + 'px';
}
X = e.clientX;
Y = e.clientY;
}, false);
img {
width: 100px;
cursor: pointer;
position: absolute;
}
<div id="troll">
<img src="http://images.mmorpg.com/features/7909/images/Troll.png" alt="Troll">
</div>
Related
I want the orange rectangle to be draggable using mouse or touch. The function for the mouse is working for me, so I tried copying it and replacing mousedown with ontouchstart, mousemove with ontouchmove and mouseup with ontouchend but it doesn't seem to move. Any suggestions? Thanks!
var move = document.querySelector('.move');
move.addEventListener('mousedown', mousedown);
move.addEventListener('ontouchstart', ontouchstart);
function mousedown() {
move.addEventListener('mousemove', mousemove);
move.addEventListener('mouseup', mouseup);
function mousemove(e){
var x = e.clientX - 100 + 'px';
var y = e.clientY - 100 + 'px';
this.style.left = x;
this.style.top = y;
}
function mouseup() {
move.removeEventListener('mousemove', mousemove)
}
}
function ontouchstart() {
move.addEventListener('ontouchmove', ontouchmove);
move.addEventListener('ontouchend', ontouchend);
function ontouchmove(e){
var x = e.clientX - 100 + 'px';
var y = e.clientY - 100 + 'px';
this.style.left = x;
this.style.top = y;
}
function ontouchend() {
move.removeEventListener('ontouchmove', ontouchmove)
}
}
.move {
height: 200px;
width: 200px;
background: orange;
position: fixed;
}
<body>
<div class="move"></div>
<script src="script.js"></script>
</body>
For one, the names of your events are incorrect. Omit the on prefix.
Second, touchmove works a little different from mousemove. The event parameter that gets passed to touchmove does not have a clientX or clientY property. Instead it contains a TouchList that needs to be iterated. See below:
var move = document.querySelector('.move');
move.addEventListener('mousedown', mousedown);
move.addEventListener('touchstart', ontouchstart);
function mousedown() {
move.addEventListener('mousemove', mousemove);
move.addEventListener('mouseup', mouseup);
function mousemove(e) {
var x = e.clientX - 100 + 'px';
var y = e.clientY - 100 + 'px';
this.style.left = x;
this.style.top = y;
}
function mouseup() {
move.removeEventListener('mousemove', mousemove)
}
}
function ontouchstart() {
move.addEventListener('touchmove', ontouchmove);
move.addEventListener('touchend', ontouchend);
function ontouchmove(e) {
e.preventDefault();
for (target of e.targetTouches) {
var x = target.clientX - 100 + "px";
var y = target.clientY - 100 + "px";
this.style.left = x;
this.style.top = y;
}
}
function ontouchend() {
move.removeEventListener('touchmove', ontouchmove)
}
}
.move {
height: 200px;
width: 200px;
background: orange;
position: fixed;
}
<body>
<div class="move"></div>
<script src="script.js"></script>
</body>
For more information see Touch Events and Using Touch Events.
I'm trying to trigger an event when the cursor position moves X amount of pixels, say 100px. So, for every 100px the cursor moves in either X or Y direction, I trigger an event. This should continue for every 100px movement.
I've successfully detected the 'current' X and Y position of the cursor, and have set a pixel threshold, but am struggling with the maths on the rest. Can anyone help?
$(window).on('mousemove', function(e){
// Vars
var cursorX = e.clientX;
var cursorY = e.clientY;
var cursorThreshold = 100;
... detect every 100px movement here...
});
You need to keep track of the old cursor positions. Then you can calculate the distance using the Pythagorean theorem:
totalDistance += Math.sqrt(Math.pow(oldCursorY - cursorY, 2) + Math.pow(oldCursorX - cursorX, 2))
This works in any direction.
Example:
Note: Unlike #wayneOS's approach (+1 from me) I do not keep track of the direction.
It's a rather minimalistic implementation.
var totalDistance = 0;
var oldCursorX, oldCursorY;
$(window).on("mousemove", function(e){
var cursorThreshold = 100;
if (oldCursorX) totalDistance += Math.sqrt(Math.pow(oldCursorY - e.clientY, 2) + Math.pow(oldCursorX - e.clientX, 2));
if (totalDistance >= cursorThreshold){
console.log("Mouse moved 100px!");
totalDistance = 0;
}
oldCursorX = e.clientX;
oldCursorY = e.clientY;
});
.d {
width: 0;
height: 0;
border-style: solid;
border-width: 100px 100px 0 0;
border-color: #e54646 transparent transparent transparent;
}
.s { display: flex; }
.p1 { margin-left: 100px; }
.p2 { margin-right: 20px; padding-top: 20px; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p class="p1">100px X</p>
<div class="s">
<p class="p2">100px Y</p>
<div class="d"></div>
</div>
To track mouse-movement for defined steps, you just need to save the last position and than check if the cursor has moved more than the threshold in one direction. Here is an example:
// Vars
var lastCursorX = null;
var lastCursorY = null;
var cursorThreshold = 100;
$(window).on('mousemove', function(e){
//set start-points
if (lastCursorX === null)
lastCursorX = e.clientX;
if (lastCursorY === null)
lastCursorY = e.clientY;
//check for move left
if (e.clientX <= lastCursorX - cursorThreshold) {
lastCursorX = e.clientX;
console.log (cursorThreshold + 'px moved left');
}
//check for move right
if (e.clientX >= lastCursorX + cursorThreshold) {
lastCursorX = e.clientX;
console.log (cursorThreshold + 'px moved right');
}
//check for move up
if (e.clientY <= lastCursorY - cursorThreshold) {
lastCursorY = e.clientY;
console.log (cursorThreshold + 'px moved up');
}
//check for move down
if (e.clientY >= lastCursorY + cursorThreshold) {
lastCursorY = e.clientY;
console.log (cursorThreshold + 'px moved down');
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
I am JavaScript Beginner and I am working on a small code where I have an image displayed inside a Modal and I am trying to draw a bounding box over the image.
I have tried the following code to draw the bounding box over the image.
Html: ( the code for the modal that shows the image)
<div id="myModal" class="modal">
<!-- The Close Button -->
<span class="close">×</span>
<!-- Modal Content (The Image) -->
<div id="imagearea" class="imagearea">
<img class="modal-content" id="img01">
</div>
</div>
Javascript: ( the logic that I tried to draw a bounding box over the image)
initDraw(document.getElementById('imgarea'));
function initDraw(imgarea) {
var mouse = {
x: 0,
y: 0,
startX: 0,
startY: 0
};
function setMousePosition(e) {
var ev = e || window.event; //Moz || IE
if (ev.pageX) { //Moz
mouse.x = ev.pageX + window.pageXOffset;
mouse.y = ev.pageY + window.pageYOffset;
} else if (ev.clientX) { //IE
mouse.x = ev.clientX + document.body.scrollLeft;
mouse.y = ev.clientY + document.body.scrollTop;
}
};
var element = null;
imgarea.onmousemove = function (e) {
setMousePosition(e);
if (element !== null) {
element.style.width = Math.abs(mouse.x - mouse.startX) + 'px';
element.style.height = Math.abs(mouse.y - mouse.startY) + 'px';
element.style.left = (mouse.x - mouse.startX < 0) ? mouse.x + 'px' : mouse.startX + 'px';
element.style.top = (mouse.y - mouse.startY < 0) ? mouse.y + 'px' : mouse.startY + 'px';
}
}
imagearea.onmouseup = function (e) {
if (element !== null) {
element = null;
imagearea.style.cursor = "default";
console.log("finsihed.");
} }
imagearea.onmousedown = function (e) {
if(element==null){
console.log("begun.");
mouse.startX = mouse.x;
mouse.startY = mouse.y;
element = document.createElement('div');
element.className = 'rectangle'
element.style.left = mouse.x + 'px';
element.style.top = mouse.y + 'px';
imagearea.appendChild(element)
imagearea.style.cursor = "crosshair";
e.preventDefault();
}
}
}
css: (for the bounding box)
.rectangle {
border: 10px solid red;
position: absolute;
}
.imagearea {
display: flex;
flex-direction: column;
float: left;
width: 35%;
max-width: 700px;
position: relative;
}
#img01{
position: absolute;
}
The above code displays the image in modal and when I try to draw the bounding box on the image, the cursor changes to crosshair as expected , but I could not see the bounding box when i draw it over the image. Just the cursor changes but the rectangle(bounding box) which I draw over the image is not visible.
Can some one help me with this. Thank you
There are two problems.
You can't append children to <img>.
Your calculations are based on the viewport, while border's CSS is relative to the image. There are multiple ways to fix that, the quickest one would be to subtract image's position from your mouse position, like this:
function setMousePosition(e) {
// your mouse calculations
const boundaries = e.currentTarget.getBoundingClientRect();
mouse.x -= boundaries.left;
mouse.y -= boundaries.top;
}
Also, make sure you use setMousePosition() in your mousedown handler.
I am trying to develop a simple app.
When we drag the small box inside the bigger box, the smaller box should move inside the bigger box.
However, it can't go outside the bigger box. I know how to move the smaller box, but I don't know how to keep it inside the bigger box. Can somebody help me, please?
As I mentioned, my code moves the small box properly but does not keep it inside the bigger box.
var guy=document.getElementById("guy");
var cont=document.getElementById("container");
var lastX,lastY; // Tracks the last observed mouse X and Y position
guy.addEventListener("mousedown", function(event) {
if (event.which == 1) {
lastX = event.pageX;
lastY = event.pageY;
addEventListener("mousemove", moved);
event.preventDefault(); // Prevent selection
}
});
function buttonPressed(event) {
if (event.buttons == null)
return event.which != 0;
else
return event.buttons != 0;
}
function moved(event) {
if (!buttonPressed(event)) {
removeEventListener("mousemove", moved);
} else {
var distX = event.pageX - lastX;
var distY = event.pageY - lastY;
guy.style.left =guy.offsetLeft + distX + "px";
guy.style.top = guy.offsetTop + distY + "px";
lastX = event.pageX;
lastY = event.pageY;
}
}
#container {
height:400px;
width:600px;
outline: 1px solid black;
position:absolute;
left:50px;
top: 0px;
background-color:green;
}
#guy {
position:absolute;
height:50px;
width:50px;
outline: 1px solid black;
background-color:red;
left: 200px;
top: 200px;
}
<div id="container" draggable="true" ></div>
<div id="guy"></div>
You need to restrict guy's position to the container's bounds. In other words, guy's x position can at minimum be the container's x position, at maximum the container's x position plus the container's width minus guy's witdh. The same goes for the y axis, but with height instead of width.
var guy=document.getElementById("guy");
var cont=document.getElementById("container");
var lastX,lastY; // Tracks the last observed mouse X and Y position
var minX = cont.offsetLeft;
var maxX = minX + cont.offsetWidth - guy.offsetWidth;
var minY = cont.offsetTop;
var maxY = minY + cont.offsetHeight - guy.offsetHeight;
guy.addEventListener("mousedown", function(event) {
if (event.which == 1) {
lastX = event.pageX;
lastY = event.pageY;
addEventListener("mousemove", moved);
event.preventDefault(); // Prevent selection
}
});
function buttonPressed(event) {
if (event.buttons == null)
return event.which != 0;
else
return event.buttons != 0;
}
function moved(event) {
if (!buttonPressed(event)) {
removeEventListener("mousemove", moved);
} else {
var distX = event.pageX - lastX;
var distY = event.pageY - lastY;
var targetX = guy.offsetLeft + distX;
var targetY = guy.offsetTop + distY;
guy.style.left = Math.min(maxX, Math.max(minX, targetX)) + "px";
guy.style.top = Math.min(maxY, Math.max(minY, targetY)) + "px";
lastX = event.pageX;
lastY = event.pageY;
}
}
#container {
height:200px;
width:300px;
outline: 1px solid black;
position:absolute;
left:50px;
top: 0px;
background-color:green;
}
#guy {
position:absolute;
height:50px;
width:50px;
outline: 1px solid black;
background-color:red;
left: 100px;
top: 100px;
}
<div id="container" draggable="true" ></div>
<div id="guy"></div>
Why when the ball is placed relative positioning when you press the mouse it bounces? Absolute positioning is when this doesn't happen.
var ball = document.querySelector('.ball');
ball.onmousedown = function(event) {
var shiftX = event.pageX - getCoords(this).left,
shiftY = event.pageY - getCoords(this).top;
this.style.position = 'relative';
this.zIndex = 10000;
function move(event) {
this.style.left = event.pageX - shiftX + 'px';
this.style.top = event.pageY - shiftY + 'px';
}
move.call(this, event);
document.onmousemove = function(event) {
move.call(ball, event);
};
this.onmouseup = function(event) {
document.onmousemove = this.onmouseup = null;
};
return false;
};
ball.ondragstart = function() {
return false;
};
function getCoords(elem) {
var box = elem.getBoundingClientRect();
return {
top: box.top + window.pageYOffset,
left: box.left + window.pageXOffset
};
}
body {
margin: 50px;
}
img {
cursor: pointer;
}
<img class="ball" src="https://js.cx/clipart/ball.svg" alt="" />
I guess it's because of the padding of the body element. Please explain.
it seems i found answer
Implementing drag and drop on relatively positioned elements in JavaScript
and as it says, with relative position, your element contain offset of all objects in his parent-tag
and parent's margin and padding too
so when you try to get elemtn's position, you should count it's real offset in parent, see in my code example work with count index
<html>
<body>
<div id=obj1 style="width:100px; height:100px; background:#000; position:relative; " ></div>
<div id=obj2 style="width:100px; height:100px; background:#000; position:relative; " ></div>
<div id=obj3 style="width:100px; height:100px; background:#000; position:relative; " ></div>
<script>
var dragObj, count=0;
function set_drag_drop(obj)
{
if(count>0){
// count margins and divs offset
// body{ margin:10px; }
// height:100px;
obj.adx = 10;
obj.ady = 10 + (count*100)
}else{
obj.adx = 0;
obj.ady = 0;
}
count++;
obj.onmousedown = function(e)
{
var rect = obj.getBoundingClientRect();
obj.dx = rect.left - e.clientX;
obj.dy = rect.top - e.clientY;
obj.isDown = true;
dragObj = this;
}
obj.onmouseup = function(e)
{
obj.isDown = false;
}
document.onmousemove = function(e)
{
if(dragObj && dragObj.isDown)
{
dragObj.style.left = e.pageX -dragObj.adx+ dragObj.dx +"px";
dragObj.style.top = e.pageY -dragObj.ady+ dragObj.dy + "px";
}
}
}
set_drag_drop(document.getElementById("obj1"));
set_drag_drop(document.getElementById("obj2"));
set_drag_drop(document.getElementById("obj3"));
</script>
</html>