I create a div element with fixed position and size. Then I set it's top
and left
style properties via js in the mousemove
event handler.
const mouse = document.getElementById('mouse');
window.addEventListener("mousemove", e => {
mouse.style.left = e.offsetX + 'px';
mouse.style.top = e.offsetY + 'px';
console.log(e.offsetX, e.offsetY);
});
https://jsfiddle.net/xqa91b23/4/ (wiggle your mouse around to see the bug)
It appears that about half of the assignments work, the rest of the time the css properties end up being set to 0px. I am logging the mouse position as passed into the mousemove
event handler, and it does not correspond to the values which end up being assigned to the element's style
attribute. The strangest part of this is that if I add transform: translate(-50px, -50px)
to the element then the incorrect assignments incorporate this offset, ending up as 50px. This occurs in both chrome and firefox.
Some of the things I have tried:
element.style.setProperty
, with and without important
absolute
and relative
fixed
, absolute
and relative
with 100% width and heightevent.offset
's (despite them showing as whole numbers in the console)This one has me banging my head against the wall. I have dynamically set offset properties in the past with no problem. My suspicion is that it has something to do with the number to string conversion applied by + 'px'
, but that doesn't explain the strange behavior when adding a translation.
The issue is because of the use of offsetX
and offsetY
properties of the event. These parameters are relative to event target, not the window i.e. when mousemove
event triggers offsetX
and offsetY
are calculated based on #mouse
. To fix this you need to use e.clientX
and e.clientY
.
const mouse = document.getElementById('mouse');
window.addEventListener("mousemove", e => {
mouse.style.left = e.clientX + 'px';
mouse.style.top = e.clientY + 'px';
console.log(e.clientX, e.clientY);
});
#mouse {
position: fixed;
width: 100px;
height: 100px;
outline: 1px solid red;
}
<div id="mouse"></div>