How to prevent an element from moving diagonally - javascript

The element moves all the directions (top, right, bottom, left) including diagonally. I do not want it to move diagonally.
HTML
<body onload="move('theDiv')">
<div class="container">
<div id="theDiv" class="theDiv"></div>
</div>
</body>
Javascript
var dragValue;
function move(id) {
var element = document.getElementById("theDiv");
element.style.position = "sticky";
element.onmousedown = function() {
dragValue = element;
};
}
document.onmouseup = function(e) {
dragValue = null;
};
document.onmousemove = function(e) {
var x = e.pageX,
y = e.pageY;
dragValue.style.transform = "transltex(" + x + "px)";
dragValue.style.transform = "transltey(" + y + "px)";
};

Use lastPoint.
1. When the value of x in the current position is not equal to the value of x in the old position, that is, moving in the direction of the x-axis.
2. When the value of y of the current position is not equal to the value of y of the old position, it means moving in the direction of the y-axis.
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
<style>
.theDiv {
background-color: blue;
height: 100px;
width: 150px;
position: fixed;
top: 0;
left: 0;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body onload="move('theDiv')">
<div id="theDiv" class="theDiv"></div>
<script>
var dragValue;
var lastPoint;
function move(id) {
var element = document.getElementById("theDiv");
element.onmousedown = function(e) {
dragValue = element;
lastPoint = e;
lastPoint.pageX = lastPoint.pageX - ($('#theDiv').width() / 2);
lastPoint.pageY = lastPoint.pageY - ($('#theDiv').height() / 2);
};
}
document.onmouseup = function(e) {
dragValue = null;
lastPoint = null;
};
document.onmousemove = function(e) {
if (dragValue != null) {
var x = e.pageX - ($('#theDiv').width() / 2),
y = e.pageY - ($('#theDiv').height() / 2);
if (lastPoint.pageX == e.pageX)
dragValue.style.top = y + "px";
else
dragValue.style.left = x + "px";
lastPoint = e;
}
};
</script>
</body>
</html>
I had to change your code a bit to be able to run it. You can easily use this code or use it with your own code

Related

How to use vanilla script to bounce elements from each other

I've tried adding the top and left changes, and margin (with different positioning changes too) changes to each element if one approaches another but only the margin change works once. Is there a way to make them work more consistently?
This is where I've used a function to add the event listeners:
var three = document.getElementById('three');
var test = document.getElementById('test');
var two = document.getElementById('two');
var obj = null;
function testmovea(object, event) {
obj = document.getElementById(object.id);
document.addEventListener("mousemove", move);
}
function move(event) {
obj.innerText = event.clientX + ' ' + event.clientY;
obj.style.position = 'absolute';
obj.style.left = event.clientX + "px";
obj.style.top = event.clientY + "px";
three.addEventListener('mouseover', borders);
three.addEventListener('mouseleave', bordersOff);
two.addEventListener('mouseenter', bTwo);
test.addEventListener('mouseenter', bTest);
two.addEventListener('mouseleave', bTwoReset);
test.addEventListener('mouseleave', bTestReset);
document.addEventListener("mouseup", stopMove);
}
function bTwo() {
two.style.margin = "10%";
}
function bTwoReset() {
two.style.margin = "0%";
}
function bTest() {
test.style.margin = "10%";
}
function bTestReset() {
test.style.margin = "0%"
}
This is the mouse stop event I use:
function stopMove() {
document.removeEventListener('mousemove', move);
test.removeEventListener('mouseover', bTest);
two.removeEventListener('mouseover', bTwo);
test.removeEventListener('mouseleave', bTestReset);
two.removeEventListener('mouseleave', bTwoReset);
}
the testmovea function relies on a onmousedown property defined for a DOM element of the page
Update:
I've managed to get it to partially work:
function collide(el1, el2) {
if(twoBoundX >= threeBoundY || threeBoundY >= twoBoundX) {
two.style.margin = + event.clientX + "px";
two.style.margin = + event.clientY + "px";
}
}
where twoBoundX and threeBoundY are getBoundingClientRect() of the respective elements
Here's the full code snippet:
<html>
<head>
<style type="text/css">
#two {
border: 1px solid black;
padding: 1%;
margin: 1%;
margin-top: 10%;
width: 10%;
}
#three {
border: 1px solid black;
padding: 1%;
margin-top: 2%;
}
</style>
</head>
<body>
<div id="two" onmousedown="testmovea(this, event)" onclick="currentTwoPos()">
stop movement
</div>
<div id="three" onmousedown="testmovea(this)">Expand div</div>
<div style="height: 30%" id="two" contenteditable="true">
some contenteditable</div>
</body>
<script>
var three = document.getElementById('three');
var two = document.getElementById('two');
const twoBound = two.getBoundingClientRect();
const threeBound = three.getBoundingClientRect();
var threeBoundX = threeBound.x;
var threeBoundY = threeBound.y;
var twoBoundX = twoBound.x;
var twoBoundY = twoBound.y;
var twoBoundBottom = null;
var twoBoundTop = null;
var obj = null;
function collide(el1, el2) {
if(twoBoundX >= threeBoundY || threeBoundY >= twoBoundX) {
two.style.left = event.clientX + "px";
two.style.top = event.clientY + "px";
three.style.left = event.clientX + "px";
three.style.top = event.clientY + "px";
}
}
function testmovea(object, event) {
obj = document.getElementById(object.id);
document.addEventListener("mousemove", move);
}
function move(event) {
obj.innerText = event.clientX + ' ' + event.clientY;
obj.style.position = 'absolute';
obj.style.left = event.clientX + "px";
obj.style.top = event.clientY + "px";
two.addEventListener('mouseover', collide);
three.addEventListener('mouseover', collide);
document.addEventListener("mouseup", stopMove);
}
function stopMove() {
mousemove = false;
document.removeEventListener('mousemove', move);
three.removeEventListener('mouseover', collide);
two.removeEventListener('mouseover', collide);
}
</script>
</html>
collision detection
You need to define a function that checks whether two of your shapes collide. If you only have rectangles whose vertex are parallel with the OX and OY vertexes, it would look like this:
function areColliding(r1, r2) {
return !(
(r1.x > r2.x + r2.w) ||
(r1.x + r1.w < r2.x) ||
(r1.y > r2.y + r2.h) ||
(r1.y + r1.h < r2.y)
);
}
Of course, if some rotation or even other shapes are involved into your problem, then you need to extend/adjust the collision detector accordingly.
a shared function
You need to create a function that would receive the current status of the elements and the move that happens. It would look like this:
function handleMove(currentPositions, proposedPositions) {
while (!validPositions(proposedPositions)) {
proposedPositions = generateNewPositions(currentPositions, handleCollisions(proposedPositions));
}
refreshUI(proposedPositions);
}
currentPositions is the set of positions your elements currently have
proposedPositions is the set of positions your elements are going to have if there are no collisions
validPositions checks for any pair of shapes that would collide and returns true if none of those pair collide and false if at least one such pair collides
proposedPositions is being refreshed while there are still collisions
generateNewPositions is your handler for collision-based changes
handleCollisions effectuates changes to avoid collision
refreshUI refreshes the UI
event handling
your mouse events should handle change updates by loading all the positions of your elements and calling this shared functionality.
Note: If you have further problems, then you might need to create a reproducible example so we could see your exact structure, styling and code as well.
<html>
<head>
<style type="text/css">
#two {
border: 1px solid black;
width: 10%;
padding: 1%;
margin: 1%;
margin-top: 10%;
}
#three {
border: 1px solid black;
padding: 1%;
margin-top: 2%;
}
</style>
</head>
<body>
<div id="two" onmousedown="testmovea(this, event)" style="position: relative;">
stop movement
</div>
<div id="three" onmousedown="testmovea(this)" style="position: relative;">Expand div</div>
<!--<div style="height: 30%; position: relative;" id="two" contenteditable="true">
some contenteditable</div>-->
</body>
<script>
var three = document.getElementById('three');
var two = document.getElementById('two');
let moveStarted = false;
function collide() {
const first = two.getBoundingClientRect();
const second = three.getBoundingClientRect();
if (!(
(first.x + first.width < second.x) ||
(second.x + second.width < first.x) ||
(first.y + first.height < second.y) ||
(second.y + second.height < first.y)
)) {
two.style.left = event.clientX + "px";
two.style.top = event.clientY + "px";
three.style.left = event.clientX + "px";
three.style.top = event.clientY + "px";
}
}
function testmovea(object, event) {
obj = document.getElementById(object.id);
if (!moveStarted) {
document.addEventListener("mousemove", move);
moveStarted = true;
}
}
function move(event) {
//obj.innerText = event.clientX + ' ' + event.clientY;
obj.style.left = event.clientX + "px";
obj.style.top = event.clientY + "px";
if (!obj.classList.contains("dragged")) obj.classList.add("dragged");
collide(obj);
}
function stopMove() {
mousemove = false;
if (moveStarted) {
document.removeEventListener('mousemove', move);
moveStarted = false;
}
}
document.addEventListener("mouseup", stopMove);
</script>
</html>

How to draw rectangle box over an image present inside div?

I have developed a page where I dynamically import images and display them inside a div tag. Now i wanted to draw an rectangle over the image, and it should start from any point on the image.
I referred many sources and tried to implement the idea from it.
<style>
#rubberBand {
position: absolute;
visibility: hidden;
width: 0px; height: 0px;
border: 2px solid red;
}
</style>
<div class="imageside" id="picture"> </div>
<div ID="rubberBand"></div>
In the above code, the image is display at the div id "picture". Till this part of the code works fine.
var pic, rubber, pt = { x: 0, y: 0 };
picture= getpicture();
function getpicture(){
pic= document.getElementById('picture')
pic.innerHTML= getgImage(event.target.dataset.number);
}
function startRubber (evt) {
var ev = evt || window.event,
rs = rubber.style,
bb = pic.innerHTML.getBoundingClientRect();
console.dir(ev);
rs.left = bb.left + 'px';
rs.top = bb.top + 'px';
rs.width = bb.width + 'px';
rs.height = bb.height + 'px';
rs.display = 'block';
pt = { x: ev.clientX - bb.left, y: ev.clientY - bb.top };
return false;
}
function stopRubber () {
rubber.style.display = 'none';
}
function moveRubber (evt) {
var ev = evt || window.event;
rubber.style.left = (evt.clientX - pt.x) + 'px';
rubber.style.top = (evt.clientY - pt.y) + 'px';
}
rubber = document.getElementById('rubberBand');
pic = document.getElementById('picture').innerHTML;
pic.onmousedown = startRubber;
document.onmouseup = stopRubber;
document.onmousemove = moveRubber;
In the above code, the function getpicture() is responsible to display the images dynamically. When i execute the above code, the image displays on the page, but I am not able to draw the rectangle over the image. In console, no errors. Can someone help me out with problem and help me to draw the rectangle over the image.
check this out.
https://jsfiddle.net/2at9n7ye/3/
your issue is that you are accessing the pic variable before you load it.
var pic, rubber, pt = {
x: 0,
y: 0
};
picture = getpicture();
function getpicture() {
pic = document.getElementById('picture');
pic.innerHTML = "<img src='https://i.imgur.com/mvMlmMb.jpg' id='img' width='100px' height='100px'/>";
}
function startRubber(evt) {
var ev = evt || window.event,
rs = rubber.style,
bb = pic.getBoundingClientRect
rs.left = bb.left + 'px';
rs.top = bb.top + 'px';
rs.width = bb.width + 'px';
rs.height = bb.height + 'px';
rs.display = 'block';
pt = {
x: ev.clientX - bb.left,
y: ev.clientY - bb.top
};
return false;
}
function stopRubber() {
rubber.style.display = 'none';
}
function moveRubber(evt) {
var ev = evt || window.event;
rubber.style.left = (evt.clientX - pt.x) + 'px';
rubber.style.top = (evt.clientY - pt.y) + 'px';
}
(function() {
rubber = document.getElementById('rubberBand');
pic = document.getElementById('picture');
pic.addEventListener("mousedown", startRubber);
document.addEventListener("mouseup", stopRubber);
document.addEventListener("mousemove", moveRubber);
})();

Save mouse coordinate in an array

I want to get mouse coordinate in an array. Also I click anywhere I can't get mouse coordinate.
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>Google Maps</title>
<style>body {background-color: ivory;}</style>
</head>
<body>
<p id="results">result</p>
<script>
var x = document.getElementById("body");
var offsetX = x.offsetLeft;
var offsetY = x.offsetTop;
x.addEventListener('click', handleClick, false);
function handleClick(e) {
mouseX = parseInt(e.clientX - offsetX);
mouseY = parseInt(e.clientY - offsetY);
document.getElementById("results").innerHTML = "You clicked at: " + mouseX + "/" + mouseY;
}
</script>
</body>
</html>
There is no element within your HTML that has id="body". You can access the <body> element using document.body.
Also, the body is rather small since it only contains your one <p> element, so you may want to add some css so that you can click anywhere in the window and your event will fire:
html, body {
height: 100%;
}
To store the calculated coordinates in an array, just create a blank array:
var coords = [];
Then add coordinates to them:
coords.push([mouseX, mouseY]);
Here is a working example:
var x = document.body;
var offsetX = x.offsetLeft;
var offsetY = x.offsetTop;
x.addEventListener('click', handleClick, false);
var coords = [];
function handleClick(e) {
mouseX = parseInt(e.clientX - offsetX);
mouseY = parseInt(e.clientY - offsetY);
coords.push([mouseX, mouseY]);
document.getElementById("results").innerHTML = "You have clicked at: " + JSON.stringify(coords);
}
html, body {
height: 100%;
}
<p id="results">result</p>
This would be how I approach it.
You have no element with an id of body so I created one with an id of bodyEquivalent
If you want to get an actual tag, you need to use
getElementsByTagName('tag_name'); which returns an array of matching elements (you can grab the first element from the array)
or more simply: document.body for the body tag
var x = document.getElementById("bodyEquivalent");
// or
// var x = document.body;
var offsetX = x.offsetLeft;
var offsetY = x.offsetTop;
x.addEventListener('click', handleClick, false);
// array to store click coords
var clickCoords = [];
// a point coord
var ClickPoint = function(x, y) {
this.x = x;
this.y = y;
};
ClickPoint.prototype.toString = function(){
return "(" + this.x + ", " + this.y + ")";
}
function handleClick(e) {
mouseX = parseInt(e.clientX - offsetX);
mouseY = parseInt(e.clientY - offsetY);
// create click point and store it in array
var aClick = new ClickPoint(mouseX, mouseY);
clickCoords.push(aClick);
// update results
showArrayCoords(clickCoords);
}
function showArrayCoords(coords) {
var innerHtml = 'You clicked at:<br/>';
for (i = 0; i < coords.length; i++) {
innerHtml += coords[i] + "<br/>";
}
document.getElementById("results").innerHTML = innerHtml;
}
#bodyEquivalent {
background-color: ivory;
border: 1px solid black;
width: 400px;
height: 300px;
}
<div id="bodyEquivalent">
</div>
<p id="results">result</p>

Create and position divs relative to parent

I am trying to create(and position) rectangle divs on a parent div. The created div should be positioned relative. Here is a working jsfiddle example -> Just draw some rectangles by holding mouse button.
var newRect = null;
var offset = $('#page').offset();
function point(x, y) {
this.x = x;
this.y = y;
}
function rect(firstPoint) {
this.firstPoint = firstPoint;
this.div = document.createElement("div");
this.div.style.position = "relative";
this.div.style.border = "solid 1px grey";
this.div.style.top = this.firstPoint.y+"px";
this.div.style.left = this.firstPoint.x+"px";
this.div.style.width = "0px";
this.div.style.height = "0px";
$("#page").append(this.div);
}
$("#page").mousedown(function (e) {
if(e.which == 1) {
var x = e.pageX - offset.left;
var y = e.pageY - offset.top;
newRect = new rect(new point(x, y));
}
});
$("#page").mousemove(function (e) {
if(newRect) {
newRect.div.style.width = Math.abs(newRect.firstPoint.x-(e.pageX - offset.left))+"px";
newRect.div.style.height = Math.abs(newRect.firstPoint.y-(e.pageY - offset.top))+"px";
}
});
$("#page").mouseup(function (e) {
if(e.which == 1 && newRect != null) {
if(Math.abs(newRect.firstPoint.x-(e.pageX - offset.left)) < 10) {
$("#"+newRect.div.id).remove();
newRect = null;
return;
}
$("#"+newRect.div.id).on('mousedown', function (e) {
e.stopImmediatePropagation();
});
newRect = null;
}
});
#page{
width: 210mm;
height: 297mm;
border:solid 2px #6D6D6D;
cursor: crosshair;
background-color: white;
float:left;
background-repeat: no-repeat;
background-size: contain;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="page">
</div>
After drawing the first rectangle, which is positioned correctly, each rectangle is positioned false. I think that there is something wrong with the calculation of the position... maybe someone can give me a hint.
Change
this.div.style.position = "relative";
to
this.div.style.position = "absolute";
Bonus: Here's a version that allows you to draw in any direction: https://jsfiddle.net/g4z7sf5c/5/
I simply added this code to the mousemove function:
if (e.pageX < newRect.firstPoint.x) {
newRect.div.style.left = e.pageX + "px";
}
if (e.pageY < newRect.firstPoint.y) {
newRect.div.style.top = e.pageY + "px";
}

Creating Circles(div) and appending it to div#canvas

I am trying to create new circles as my pen hovers on window.
I am having issues where I cannot add circles to the page. It just hovers around. How would i be able to modify my code to add circles as it hovers.
<!doctype html>
<html>
<head>
<title> JavaScript Environment: Project </title>
<meta charset="utf-8">
<style>
html, body {
width: 100%;
height: 100%;
margin: 0px;
padding: 0px;
}
#canvas {
background-color: yellow;
width: 100%;
height: 100%;
}
.pen {
position: absolute;
background-color: lightblue;
width: 10px;
height: 10px;
border-radius: 5px;
}
</style>
<script>
window.onload = function() {
function Circle(x, y) {
this.x = x;
this.y = y;
}
var canvas = document.getElementById("canvas");
canvas.onmousedown = function() {
mouseDown();
};
canvas.onmouseup = function() {
mouseUp()
};
canvas.onmousemove = function() {
mouseMove(event)
};
function mouseDown (){
console.log ("mouse down");
}
function mouseUp (){
console.log ("mouse up");
}
function mouseMove(e) {
var canvas = document.getElementById("canvas");
var pen = document.createElement("div");
var x = e.clientX;
var y = e.clientY;
var coor = "Coordinates: (" + x + "," + y + ")";
pen.setAttribute("class", "pen");
pen.style.left = x + "px";
pen.style.top = y + "px";
document.getElementById("canvas").innerHTML = coor;
canvas.appendChild(pen);
addCircles(x, y);
console.log("location # " + x + " : " + y);
}
function addCircles(x, y) {
var canvas = document.getElementById("canvas");
var circle = document.createElement("div");
circle.setAttribute("class", "pen");
circle.style.left = x + "px";
circle.style.top = y + "px";
canvas.appendChild(circle);
}
canvas.addEventListener("mouseMove", mouseMove, false);
};
</script>
</head>
<body>
<div id="canvas"></div>
</body>
</html>
The problem is in the line document.getElementById("canvas").innerHTML = coor;
Try adding a span <span id="canvasText"></span> inside of your canvas div and then changing the above line to document.getElementById("canvasText").innerHTML = coor;.
As it stands, you "reset" the contents of the canvas every time the mouse moves, so the circles are instantly removed from it. Reset only the span inside the canvas to keep the circles around.

Categories