Situation: I'm using HTML5 drag-and-drop to place tiles in a game I'm writing. I'd like to add an effect where the two tiles that I'm about to drop a new tile between move slightly apart to indicate that this is where you're dropping (similar to the Mac OS dock).
My Approach: I have a flexbox
into which I'm dropping these tiles. I wrote a function that essentially returns one period of a sine wave and I'm using it to update the dropped tiles' right:
and top:
CSS properties (the tiles are position: relative;
) based on their original position relative to the mouse during drag
.
// Update occupant style for desired effect
occupants.forEach(function(occupant, index) {
$(occupant).css({'right' : -10 * nudgeSine(occupantsMouseOffset[index] * 10) + 'px',
'top' : -10 * Math.abs(nudgeSine(occupantsMouseOffset[index] * 10)) + 'px',
'opacity' : 1 - Math.abs(nudgeSine(occupantsMouseOffset[index])) });
});
// Function to return 1 period of a sine wave
function nudgeSine(x) {
if (x < -3.14159 || x > 3.14159) {
return 0;
} else {
return Math.sin(x);
}
}
Problem: In Chrome (but not in Firefox), at some mouse positions, which I can't find a pattern in, the tile is jumping back-and-forth. See the .gif below:
In Chrome (left) and in Firefox (right):
I even console.log
ged the element's calculated right:
property, and while it is shown jumping around on screen, it outputs as a constant value.
What I've Tried/Thought About:
console.log(event.clientX)
outputting a constant value, the tile will jump around. event.clientX
might be changing imperceptibly, so I'm basing my calculations on Math.trunc(event.clientX)
to no avail. element.getBoundingClientRect()
in my calculations, which I'm not very familiar with, and I think it may be the root cause of my problem.I made this CodePen, but wasn't able to completely replicate the issue. Still, I think someone may be able to spot what's happening.
Edit: I've put this up on a github page to fully replicate. This link may not work for future readers of the question, but I'll keep it up for the foreseeable future. To demonstrate the issue, view in Chrome and Firefox.
Thank you.
Complete HTML/CSS Course 2022 Now HTML 5 came up with a Drag and Drop (DnD) API that brings native DnD support to the browser making it much easier to code up. HTML 5 DnD is supported by all the major browsers like Chrome, Firefox 3.5 and Safari 4 etc.
setData() The DataTransfer. setData() method sets the drag operation's drag data to the specified data and type. If data for the given type does not exist, it is added at the end of the drag data store, such that the last item in the types list will be the new type.
HTML Drag and Drop interfaces enable applications to use drag-and-drop features in browsers. The user may select draggable elements with a mouse, drag those elements to a droppable element, and drop them by releasing the mouse button.
Perhaps I can expand my answer later, but for now:
Related questions: How to keep child elements from interfering with HTML5 dragover and drop events? 'dragleave' of parent element fires when dragging over children elements
This is what happens: - you start dragging the operator - operator moves over the box, existing operators move along nicely - you move the operator over one of the existing operators - at this point the browser enters a kind of infinite loop thingy, because each time the elements move the position of the elements have to be updated again (because new events are triggered)
Since you need the click event on the existing operators you can't just set them to pointer-events: none;
like in the related question, but you can add a class when you start dragging and apply this style to the operators while you're dragging.
Another solution would be to use a library, in the comments of an answer I found the library https://bensmithett.github.io/dragster/, I use draggable by shopify.
update
I wasn't able to find the exact term of this behavior, perhaps we could go with "cyclic case" or "undefined behaviour". See my examples:
:root {
/*colors by clrs.cc*/
--navy: #001f3f;
--blue: #0074D9;
--red: #FF4136;
font-family: sans-serif;
}
.animated {
transition: all .5s;
}
h2 {
color: var(--red);
}
div {
height: 160px;
width: 160px;
padding: 20px;
background: var(--blue);
margin-bottom: 20px;
}
.box1 {
border-right: 20px solid var(--navy);
}
.box1:hover {
border-right: 0px solid var(--navy);
}
.box2:hover {
border-radius: 100px;
}
<div class="box1 animated">hover your mouse over my border on the right →</div>
<div class="box2 animated">hover your mouse over an edge of this box</div>
<h2>Warning, the following boxes have no animations, flashes are expected:</h2>
<div class="box1">hover your mouse over my border on the right →</div>
<div class="box2">hover your mouse over an edge of this box</div>
When the user moves the mouse onto the border the following happens in a loop:
box1
is being hoveredbox1
isn't being hoveredbasically for the moment the CSS doesn't really evaluate, because as soon as it evaluates the evaluation is invalid. This is exactly what happens in your example. I don't know whether the CSS standard has rules that define how browsers should handle this. If the expected behavior is defined, either FF or Chrome is wrong and you can file a bug after you find out which browser's behavior is wrong. If no expected behavior is defined and the implementation is left open to browsers then both browsers are right.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With