JS Drag and Drop to target without knowing its position - javascript

I am creating a simple app which allows for the dragging of multiple img's to a target div on a page. When the img is dragged and release on the target div the img's properties are noted.
Unfortunately my web page is built on percentages and I am wondering if there is anyway way this can be done without knowing the top, left etc positions of the target area. In other words, without working with absolutes.
I've gotten the dragging part working fine it's just simulating the detection which I am finding tricky.
I think I've gotten pretty close using the mouseover event on the target div but of course the dragging img blocks the event firing. When I release my image it resets to its normal position and gives a brief time for the mouseover to seem suitable.
However in tests it would seem that this time gap doesn't give the mouseover enough time to fire (if that is even possible). I believe this is the case because I put an alert right after the dragged image stops blocking the target div and the img's properties are succesfully printed to my console log.
img.style.position = "relative";
img.style.left = "0px";
img.style.top = "0px";
var startDrag = function(e){
initialMouseX = e.clientX;
initialMouseY = e.clientY;
initialElementX = initialElementY = "0px";
img.style.zIndex = 1000;
document.addEventListener("mouseup", removeDrag, true);
document.addEventListener("mousemove",movement,true);
document.getElementById("drag-area").addEventListener("mouseover",
readPeriod,true); //mouseover event starts when the user presses the img
};
var removeDrag = function(e){
document.removeEventListener("mousemove",movement,true);
img.style.left="0px";
img.style.top="0px";
img.style.zIndex = 0;
//an alert at this point gives the mouseup time to fire
img.removeEventListener("mouseup", removeDrag, true);
//mouseover ends after the img has stopped blocking the mouse
};
var movement = function(e){
/*Code which moves the dragging img by style.left/top*/
};
var readPeriod = function(e){
console.log(img.name); //Point of simulated on target div
};
img.addEventListener("mousedown",startDrag,true);
So in summary I am trying to simulate the image dropping onto the target since its impossible to deduce the target div by its location on screen.
(Unfortunately I am unable to use a js library to aid me in this situation.)

You should probably use jQuery UI's Droppable. Things would be much simpler and you won't need to solved problems like this.
People invested many hours in making this work correctly. You shouldn't waste your time again and solve all these bugs again.
On top of that, you would be able to mark the drop target by ID and won't need to deal with coordinates

Related

How to increase speed of mousemove/clientX/Y and applying a transform?

I have built a WordPress theme. I came across a website that created a div to follow the user's cursor. The div was enlarged smoothly when the user hovers over a button or a link.
I want to add this nice functionality as an optional feature.
I added a div to the web page, #ambition_cursor and added some basic styling. The div now shows like a blue circle. The circle has position fixed to the top left corner of the site. The position can be changed by adding a CSS translate property.
I managed to make it work with the following code:
var ambition_cursor = document.getElementById("ambition_cursor");
function ambition_mouse(e) {
var ambition_cursor_x = e.clientX; // Get the horizontal coordinate
var ambition_cursor_y = e.clientY; // Get the vertical coordinate
var ambition_cursor_pos = `translate(${ambition_cursor_x}px, ${ambition_cursor_y}px)`;
ambition_cursor.style.transform = ambition_cursor_pos;
}
window.addEventListener('mousemove', ambition_mouse);
The big downside here is the lag (?). There's quite a big delay, especially when moving the mouse around very fast. You can try it out on this site. I also put the situation in a JSFiddle; although the delay doesn't really happen there.
I didn't apply yet much styling (the default cursor is visible, so you can get a better idea of the real position). I first want this to work better, before I spent much time on that.
How can I increase the speed of this, so that the div position follows the mouse more accurately? I'm a beginner, so I don't really know which JavaScript optimisations I should make.
Current code is JavaScript, but jQuery is also an option.
Many thanks in advance!
Update: example how it looks on my computer.
All elements on the page have a transition applied. Remove/override this style and the delay goes away (tested).
As an alternative to the great answer of Joseph Atkinson:
var ambition_cursor = document.getElementById("ambition_cursor");
function ambition_mouse(e) {
ambition_cursor.style.left = e.clientX + 'px'; // Get the horizontal coordinate
ambition_cursor.style.top = e.clientY + 'px' ; // Get the vertical coordinate
}
window.addEventListener('mousemove', ambition_mouse);
See: https://levelup.gitconnected.com/use-javascript-to-make-an-element-follow-the-cursor-3872307778b4
I visited the site example, cracked open the dev console, and found throttled(20, ambition_mouse) It is not a performance issue, and the solution is to not throttle the events. It was too smooth to be a performance issue, which gave me the first clue it had to be an accidental/deliberate effect.

Dragging elements

Im just wondering whether its possible to drag images/elements (whether inside a div or not) where the image/element is dragged to the far left and comes in from the right side of the screen - therefore dragging the image/element left to get the same result, or vice versa.
Similar to the google maps (on zoom level 1) the user can continuously drag the image left or right, and those images are on a continuous loop.
If so, what languages would you recommend using? javascript?
I hope this makes sense.
Many thanks
This is certainly possible using Javascript. Just have two copies of the image, and as you slide the images left, move the second copy to the right side. (Or vice versa if sliding right).
You can add event handlers to any element, including your images, that execute code while dragging. I apologize for not providing a complete working solution, I am pressed for time, I hope this helps as a starting point
var myGlobals = {
state: {
dragging: false;
}
};
$('.carouselImg').on('mousedown', function(e){
myGlobals.state.dragging = true;
});
$(window).on('mouseup', function(e){
// stop movement even if mouseup happens somewhere outside the carousel
myGlobals.state.dragging = false;
});
$(window).on('mousemove', function(e){
// allow user to drag beyond confines of the carousel
if(myGlobals.state.dragging == true){
recalculateCarouselPosition(e);
}
});
function recalculateCarouselPosition(e){
// These fun bits are left as an exercise for the reader
// the event variable `e` gives you the pixel coordinates where the mouse is
// You will have to do some math to determine what you need to do after this drag.
// You may want to store the coordinates of the initial click in
// `myGlobals.dragStart.x, .y` or similar so you can easily compare them
// You will probably set a negative CSS margin-left property on some element
// of your carousel.
// The carousel will probably have overflow:hidden.
// You will also have to manipulate the DOM, by adding a duplicate image to the
// opposite end and deleting the duplicates once they have scrolled out of view
};

Mouse tracking of page - and displaying it

Basically I am trying to create a little image at the top corner of a webpage, which would stay in the same position even if the page is scrolled and would show the position of the mouse.
The point is to have a large webpage that would extend down and right, and navigation of this large page would be easier if I had a little image that indicated where exactly the visitor is on this page (as the browser window is smaller than the page). I wanted to to just track the browser window position on the web page, but I cannot find anything that would help me do it, so I thought I might do it with just the mouse movement. The problem is that I know about nothing about java, so does anyone know how I could track the mouse position on the page (not the browser) and display it at the same time on a small image on the upper corner of the browser?
This would work, but only in modern browsers that support css3 transforms (scale):
JsFiddle
It works by copying the whole page that should be in the .actual-page div into a .thumbnail div which is positioned on the top left of the page. Then I scale the cloned page with css transforms and use javascript to replicate mouse movements into the little box, here's the script:
var TinyNav = function() {
this.init = function() {
var clone = $('.actual-page').clone();
$('.thumbnail').append(clone);
$('.actual-page').on('mousemove', function(e) {
var posX = e.offsetX;
var posY = e.offsetY;
$('.thumbnail .cursor').css({
top: posY / 10,
left: posX / 10
});
});
}
this.init();
}
var tinyNav = new TinyNav();
Another way of doing it would be using canvas, but browser support isn't the best with that either..
Hope this helps

Error when mousemove arrow on image in javascript?

I am a demo here
function mouseTagObject() {
var x = document.getElementsByTagName("img")[0];
x.addEventListener('mouseover', function(){document.getElementById('arrow').style.display = 'none';}, false);
x.addEventListener('mouseout', function(){document.getElementById('arrow').style.display = 'block';}, false);
}
function mousemoveDiv(e) {
document.getElementById('arrow').style.top = e.pageY - 10 + "px";
document.getElementById('arrow').style.left = e.pageX - 15 + "px";
mouseTagObject();
}
document.addEventListener('mousemove', mousemoveDiv, false);
And html
When I mousemove on image tag (slowly), <div> tag not hide, how to fix it ?
I'll admit, it gave me the slip for a minute. But the slow vs. fast thing is what did it. Imagine, why would it not work when moving slowly? Well, look at your mouse. If you move very quickly, the button gets out from under the mouse. But if you move slowly, the button stays under the mouse the whole time, meaning that it never actually enters the image. Get rid of that button or put it next to the cursor, not under it.
Also, why are you adding the event listeners from within the mousemove handler? You're going to re-add those listeners every time the mouse moves.

Custom cursor outside of browser window

I have a element on my website which is freely resizable. This is done by 4 handles on the edges. On hovering these handles and while resizing the element I want to show the respective resize arrows.
Currently I implemented this behavior by setting the css cursor style of the body/root to these arrows. The problem about it is the limit to the client area of the browser window. It would be visually more consistent and less confusing, if the arrow cursor would be visible everywhere while the mouse is hold down.
Google Maps is doing the same thing with their hand cursor while moving the map. So my question is how to achive this effect on my own.
My current (relevant) source:
function startObjectScaling(e){
e.stopPropagation();
e.preventDefault();
document.documentElement.style.cursor = this.style.cursor;
window.addEventListener("mouseup", stopObjectScaling, false);
}
function stopObjectScaling(e){
e.stopPropagation();
document.documentElement.style.cursor = '';
window.removeEventListener("mouseup", stopObjectScaling);
}
[...]
var tg = document.getElementById("transformGadget");
var handle = tg.firstChild.nextSibling;
for(var i=0;i<4;i++){
handle.addEventListener("mousedown", startObjectScaling, false);
handle = handle.nextSibling;
}
There is a special function implemented in the more modern browsers for this purpose. The name is setCapture(). It redirects all mouse input to the object the method was called on. Now a simple css cursor definition on that element is enough to archive the desired effect. After mouse release this effect stops (for security for sure). It can also be stopped manually by calling releaseCapture
example:
<style type="text/css">
#testObj {
/* this cursor will also stay outside the window.
could be set by the script at the mousedown event as well */
cursor: hand;
}
</style>
[...]
document.getElementById('testObj').onmousedown = function(e){
// these 2 might be useful in this context as well
//e.stopPropagation();
//e.preventDefault();
// here is the magic
e.target.setCapture();
}
if the arrow cursor would be visible everywhere while the mouse is hold down.
You're relying on a potential OS quirk to create your behavior. This is not something you can ASSUME will always hold true. However, once you start a mousedown, the cursor at that point will normally stay the same, no matter where you move the mouse to, UNTIL something else (another window that you may mouse over? the desktop? a system-interrupt?) changes the cursor.
In other words, don't rely on this behavior. Find something else that will work for you. If you must do this, re-examine your business requirements.

Categories