I'm using drag event for moving an element, but I didn't find a way to make it only move horizontally, it's there any clue for this? Thanks in advance!
There is three steps we need to do
first we get the current mouse x position
second we calculate the distance it has move and the direction by newX = oldX - e.clientX saying subtract old x with current mouse x this way we get something like -3 or 2 or -1 you see we have the distance the direction - or +
Third step we update the element horizontal position by element.style.left = (element.offsetLeft - newX) + "px"
There are more details in the comments in the code. let me know if its not clear
var oldX = 0, newX = 0; // for storing X (horizontal) positions
var element = document.getElementById("mydiv"); // The element you want to drag
// We do the dragging here
function elementDrag(e) {
e = e || window.event;
e.preventDefault();
newX = oldX - e.clientX; // to calculate how much we have moved
oldX = e.clientX; // store current value to use for next move
element.style.left = (element.offsetLeft - newX) + "px"; // update left position
}
// we do this so there is not multiple event handlers
function closeDragElement() {
document.onmouseup = null;
document.onmousemove = null;
}
// when mouse down on element attach mouse move and mouse up for document
// so that if mouse goes outside element still drags
function dragMouseDown(e) {
e = e || window.event;
e.preventDefault();
oldX = e.clientX; // store current value to use for mouse move calculation
document.onmouseup = closeDragElement;
document.onmousemove = elementDrag;
}
element.onmousedown = dragMouseDown;
#mydiv {
position: absolute;
z-index: 9;
background-color: #2196F3;
text-align: center;
border: 1px solid #d3d3d3;
padding: 10px;
cursor: move;
color: #fff;
}
<div id="mydiv">
Click here to move
</div>
Related
I want to make a mobile phone theme effect on the browser, and I need to make the icon get the current mouse position when it is dragged. In order to judge whether the user wants to insert the currently dragged icon at the mouse position, but I use the event object (#drag($event) ) of the drag method in the Firefox browser to get the mouse coordinates (event. pageX, event.screenX), it shows (0,0) or a fixed value, but when I use Google Chrome, the above situation does not occur, it immediately gives me the coordinates of the current mouse. Regarding the problem of the value of layerXY in the picture, this value will only be updated once at the beginning of dragging, and will not change at the rest of the time. Since I personally like to use the Firefox browser, I want to solve this problem, can anyone help me? Or give me some other suggestions to implement this function (my English is not very good, from google translate)
You could update the mouse coordinate on a global variable when the mouse moves so that it will be ready for you when mouse is down.
let drag = document.querySelector('.note');
var pageX, pageY
drag.onmousedown = function(e) {
let coord = getCoord(drag);
let shiftX = pageX - coord.left;
let shiftY = pageY - coord.top;
drag.style.position = 'absolute';
document.body.appendChild(drag);
moveNote(e);
drag.style.zIndex = 1000;
function moveNote(e) {
drag.style.left = pageX - shiftX + 'px';
drag.style.top = pageY - shiftY + 'px';
var position = {
x: drag.style.left,
y: drag.style.top
}
}
document.onmousemove = function(e) {
moveNote(e);
};
drag.onmouseup = function() {
document.onmousemove = null;
drag.onmouseup = null;
};
}
function getCoord(elem) {
let main = elem.getBoundingClientRect();
return {
top: main.top,
left: main.left
};
}
window.onload = function() {
document.addEventListener("mousemove", function(e) {
pageX = e.pageX
pageY = e.pageY
});
drag.style.position = 'absolute';
document.body.appendChild(drag);
drag.style.display = 'block'
}
.note {
width: 50px;
height: 50px;
background: red;
display: none;
}
<div class="note"></div>
I have a scrollable div that I want to scroll when dragging the mouse inside of it.
I have a very basic implementation in this code pen.
I can't however understand how to think of scrollLeft and clientX? I think I need 😵💫 to set the scrollLeft position to the clientX + the position of the scrollBar once the drag staretd. But they are somehow on different relative positions?
Resulting in a bit of "jumpy" feeling when starting to drag.
function mouseMove(event) {
if (!dragging) return;
const {scrollLeft} = initScroll;
// Even if I click exactly where the bar starts the positions are way off ...
div.scrollLeft = event.clientX + scrollLeft;
}
In this image I've just clicked at the start of the bar but the scrollLeft is at 548 and the clientX is at 282?
How can I make this a bit smoother?
You should reset the initPosition every time the mouse moves and is dragging, and instead of reassigning the scrollLeft, you can subtract from it the difference between the clientX and the initPosition:
var dragging = false;
var startX = 0;
var elem = document.querySelector('.draggable');
document.addEventListener('mousedown', (e) => (dragging = true,startX = e.clientX))
document.addEventListener('mouseup', () => (dragging = false))
document.addEventListener('mousemove', function(e) {
if (!dragging) return;
elem.scrollLeft -= e.clientX - startX;
startX = e.clientX;
})
.draggable {
overflow-y: auto;
}
.draggable .content {
width: 200%;
background-color: red;
height: 100px;
}
<div class="draggable">
<div class="content"></div>
</div>
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>
Oddly enough I cannot get the problem to be reproducable here however in my own project switching from an svg to a png seems to have fixed the issue, I had wanted to use an svg so that's a little inconvenient but not a huge thing overall.
I've been trying to get a draggable map and I've started messing around first with an svg image that is draggable and then cutoff by a div. My HTML looks like this
dragElement(document.getElementById("map"));
function dragElement(el) {
var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
if (document.getElementById(el.id + "header")) {
// if present, the header is where you move the DIV from:
document.getElementById(el.id + "header").onmousedown = dragMouseDown;
} else {
// otherwise, move the DIV from anywhere inside the DIV:
el.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:
el.style.top = (el.offsetTop - pos2) + "px";
el.style.left = (el.offsetLeft - pos1) + "px";
}
function closeDragElement() {
// stop moving when mouse button is released:
document.onmouseup = null;
document.onmousemove = null;
}
}
<div id="content" style=" width: auto; height: 100%; padding:5px 100px;"></div>
<div id="mapContainer" style="height: 500px; width: auto; overflow: hidden; position: relative;">
<img id="map" draggable="false" src="https://cdn.pixabay.com/photo/2013/07/12/12/54/world-map-146505_1280.png" style="position:absolute;"></img>
</div>
<
And I'm using some js from w3 to do the dragging:
The problem is I need position absolute on the image to move it but that renders the overflow hidden of it's parent div null and void so I have to set the parent div to relative but when I do that the y axis works perfectly but the x axis (left) scales the image? Is there a way to fix this? Or perhaps I should approach this in an entirely different way?
Leaflet.js (https://leafletjs.com/) is the best tool to use for what I'm trying to achieve.
I can dynamically position a div element, so that as the user moves the mouse the element follows, using jQuery:
inputFile.offset({
top: ev.pageY - 15,
left: ev.pageX - 160
});
I would prefer to not use jQuery. How would I accomplish the same using vanilla JavaScript?
Define div to use then create a function for the X and Y coordinates and one for the cursor then have div follow cursor.
var div = 'mydiv'; // div that will follow the mouse. Set position:absolute in CSS
var offset_X = 10; // X offset from mouse position
var offset_Y = 10; // Y offset from mouse position
function mouseX(evt) { // create function for x mouse event
if (!evt) evt = window.event;
if (evt.pageX) return evt.pageX;
else if (evt.clientX) return evt.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft);
else return 0;
}
function mouseY(evt) { // create function for Y mouse event
if (!evt) evt = window.event;
if (evt.pageY) return evt.pageY;
else if (evt.clientY) return evt.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop);
else return 0;
}
function follow(cursor) { // create function for cursor
var obj = document.getElementById(div).style;
obj.left = (parseInt(mouseX(cursor)) + offset_X) + 'px';
obj.top = (parseInt(mouseY(cursor)) + offset_Y) + 'px';
}
document.onmousemove = follow; // call function when user moves mouse
#mydiv {
position: absolute;
display: block;
background: #ccc;
height: 100px;
padding: 20px 50px;
}
<div id="mydiv"> </div>