CSS Left position scales image? - javascript

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.

Related

How to make drag event move in only one direction in javascript?

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>

Detect mouseMove of X pixels

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>

How to translate javascript mouse events into jquery mobile touch events?

I'm a newbie to mobile web applications. I tried to create some mouse draggable divs for a webpage. They work well on desktop. However, when I checked them on mobile devices, none of them works. I searched online for help, but the only thing I got is that I need to set touch events with jquery mobile. Some articles said something about using touchstart, touchmove and touchend, but no examples were ever provided.
Here's my script:
dragElement(document.getElementById("cn"));
dragElement(document.getElementById("ln"));
dragElement(document.getElementById("gn"));
dragElement(document.getElementById("sn"));
function dragElement(elmnt) {
var pos1 = 0,
pos2 = 0,
pos3 = 0,
pos4 = 0;
if (document.getElementById(elmnt.id + "header")) {
// if present, the header is where you move the DIV from:
document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown;
} else {
// otherwise, move the DIV from anywhere inside the DIV:
elmnt.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:
elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
}
function closeDragElement() {
// stop moving when mouse button is released:
document.onmouseup = null;
document.onmousemove = null;
}
}
I've tried to replace the mouse events with corresponding touch events. But it didn't work.
It appears that I have to rewrite the codes in another framework. Thanks in advance.
vmousecancel means mousecancel
vmousedown
vmousemove
vmouseout
vmouseover
vmouseup
for more examples : https://api.jquerymobile.com/category/events/
Before using, you have to get jquery.mobile library in to your workspace.

Using JavaScript with Angular Component: Cannot read property 'id' of null

I have successfully managed to connect my external JavaScript file to my angular component, however it doesn't work in some instances.
I connected my src/custom.js file to my app.component.html through angular.json, as illustrated below:
"styles": [
"node_modules/bootstrap/dist/css/bootstrap.css",
"src/styles.css"
],
"scripts": [
"node_modules/jquery/dist/jquery.js",
"node_modules/bootstrap/dist/js/bootstrap.js",
"src/custom.js"
]
Context:
The demo script is a simple alert saying hello that pops every time I connect to my localhost. As far as I'm aware there's no issue with the external js file being referenced.
My issue seems to come from more complex functions.
Here's the example that am trying to implement from w3schools.
And it's set up as follows:
<!-- app.component.html -->
<div id="mydiv">
<div id="mydivheader">Click here to move</div>
<p>Move</p>
<p>this</p>
<p>DIV</p>
</div>
// custom.js
dragElement(document.getElementById("mydiv"));
function dragElement(elmnt) {
var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
if (document.getElementById(elmnt.id + "header")) {
document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown;
} else {
elmnt.onmousedown = dragMouseDown;
}
function dragMouseDown(e) {
e = e || window.event;
e.preventDefault();
pos3 = e.clientX; pos4 = e.clientY;
document.onmouseup = closeDragElement;
document.onmousemove = elementDrag;
}
function elementDrag(e) {
e = e || window.event;
e.preventDefault();
pos1 = pos3 - e.clientX;
pos2 = pos4 - e.clientY;
pos3 = e.clientX;
pos4 = e.clientY;
elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
}
function closeDragElement() {
// stop moving when mouse button is released:
document.onmouseup = null;
document.onmousemove = null;
}
}
Error: Cannot read property 'id' of null at dragElement (custom.js:13) at custom.js:6
I have come across a similar error before.My suspicion is that it has something to do with loading the DOM vs running the js?
Unfortunately I'm very new to Angular, with no experience in setting up basic web pages.
Does anybody have any insight?
You can tag your DOM element using #someTag, then get it with #ViewChild('someTag').

How do I assign a drag function / listener to multiple elements?

I am creating a page with multiple draggable divs and am looking for a way to finesse my code.
The only way I would know how to apply this JS to each id is to copy & paste the whole block of JS code 4 times and change the id but I know there must be a more efficient way, however, I am not very familiar with JS.
My initial thought was doing something like this
dragElement(document.getElementById("draggable", "draggable2", "draggable3", "draggable4"));
But it doesn't work. How can I achieve what I want in a more efficient way?
Here is my code
<div id="draggable"><div id="draggableimg"></div></div>
<div id="draggable2"><div id="draggable2img"></div></div>
<div id="draggable3"><div id="draggable3img"></div></div>
<div id="draggable4"><div id="draggable4img"></div></div>
JS
//Make the DIV element draggable:
dragElement(document.getElementById("draggable"));
var _curDragEle = "";
function dragElement(elmnt) {
var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
if (document.getElementById(elmnt.id + "img")) {
/* if present, the header is where you move the DIV from:*/
document.getElementById(elmnt.id + "img").onmousedown = dragMouseDown;
} else {
/* otherwise, move the DIV from anywhere inside the DIV:*/
elmnt.onmousedown = dragMouseDown;
}
function dragMouseDown(e) {
e = e || window.event;
e.preventDefault();
_curDragEle = this;
// 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) {
_curDragEle.classList.remove("dragstart")
_curDragEle.className = _curDragEle.className + " dragstart";
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:
elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
}
function closeDragElement() {
var k = document.querySelectorAll(".dragstart")
for(var i=0; i < k.length;i++){
k[0].classList.remove("dragstart")
}
/* stop moving when mouse button is released:*/
document.onmouseup = null;
document.onmousemove = null;
}
}
Forget ids, they lead to exactly the type of problem you are facing. Instead, give all the draggable elements a common class. Then gather all the elements up and loop over them.
// Gather all the draggable elements up into a collection
let draggables = document.querySelectorAll(".draggable");
// Loop over the collection
draggables.forEach(function(el){
dragElement(el);
});
function dragElement(el){
console.log(el + " is now draggable!")
}
<div class="draggable"><div id="draggableimg"></div></div>
<div class="draggable"><div id="draggable2img"></div></div>
<div class="draggable"><div id="draggable3img"></div></div>
<div class="draggable"><div id="draggable4img"></div></div>
So I will simplify the question a bit and provide a simple answer that I think solves your issue. "How do I assign a drag function / listener to multiple elements?"
Basically, IDs must be unique, but you can get elements of the page in bulk by referencing their tags (i.e. "DIV") or class names. It's safer to use classnames. Here's an example that can help your issue.
HTML
<div class="draggable-div" id="div1"><img /></div>
<div class="draggable-div" id="div2"><img /></div>
<div class="draggable-div" id="div3"><img /></div>
<div class="draggable-div" id="div4"><img /></div>
<div class="draggable-div" id="div5"><img /></div>
JS
function onDragEventHandler(e) {
var div = e.target;
// event code to drag here
}
var divs = document.querySelectorAll('.draggable-div');
divs.forEach(function(elem,index) = {
elem.addEventListener('mousemove', onDragEventHandler)
})

Categories