https://codepen.io/smiller0727/pen/Poqvqdg
In the pen provided above, I have a div, div#main
, with a descendant div, div#net
.
div#net
can move with left and right arrow keys so as long as there is focus to document.body
.
This is made possible by adding a “keydown” event listener to the document
to invoke function motion
(which is a property of netInst
which was initialized to a constructed object by function net
) upon occurrence of said event.
2 problems:
1.) When I keep a left or right arrow key down, div#net
moves left or right as it should however, after holding down for a second or two, div#net
's rate of motion appears to double. I’m using setInterval
s to style div#net
by modifying its left
css property by 5px per 1ms. Why does this happen, and how would I go about preventing its rate of motion from doubling?
2.) In order to stop div#net
in place, I added two “keyup” event listeners to the document
to invoke separate functions to clear each of the aforementioned intervals correspondingly. The problem is however, is that I had to add them respectively to functions moveLeft
(which nests interval _setLeft
) and moveRight
(which nests interval _setRight
), and this causes countless “keyup” event listeners to be added to the document which is not preferable. Here are both moveLeft
and moveRight
functions:
function moveLeft() {
let _setLeft = setInterval(function() {
// code that styles the `left` css
// property of `div#net`
}, 1);
document.addEventListener("keyup", function() {
clearInterval(_setLeft);
});
}
function moveRight() {
let _setRight = setInterval(function() {
// code that styles the `left` css
// property of `div#net`
}, 1);
document.addEventListener("keyup", function() {
clearInterval(_setRight);
});
}
I’ve tried making _setLeft
and _setRight
global and un-nesting document.addEventListener
s from both functions so that each “keyup” event need only be added once to the document
however, this causes the motion of div#net
to move very apparently buggy. Why does this happen, and if possible, how would I go about clearing both intervals by adding both said event listeners to the document
once while preventing the buggy motion of div#net
.
I’ve pasted the entire code below. You can also follow the codepen link above. Thanks for reading and for any input anyone would like to provide in advance.
<!-- HTML -->
<body>
<div id="main"></div>
</body>
/* CSS */
html, body {
width: calc(100% - 50px);
height: calc(100% - 50px);
}
body {
display: flex;
justify-content: center;
align-items: center;
}
#main {
width: 90%;
height: 90%;
border: 1px solid rgb(0, 0, 0);
position: relative;
}
// JS
let _css = function(objs, props) {
for(var i = 0; i < objs.length; i++) {
for(var prop in props) {
objs[i].style[prop] = props[prop];
}
}
};
let main = document.querySelector("#main");
function net(mcw, mch) {
this.display = "inline-block";
this.width = 19;
this.height = 5.333;
this.background = (function() {
let rSpect = function() { return Math.floor(Math.random() * 255); };
return `rgba(${rSpect()}, ${rSpect()}, ${rSpect()}, ${Math.random()})`;
})();
this.css_position = "absolute";
this.grid_position = {
lPos: (mcw / 2) - (((mcw) * (this.width / 100)) / (2)),
tPos: ((mch) - ((mch) * (this.height / 100))) - ((mch) * (2 / 75))
};
this.motionPace = 5;
this.motion = function(e) {
function moveLeft() {
let _setLeft = setInterval(function() {
_css([Net], {
left: (netInst.grid_position.lPos -= netInst.motionPace) + "px"
});
if(netInst.grid_position.lPos < 0) {
netInst.grid_position.lPos = 0;
_css([Net], { left: netInst.grid_position.lPos + "px" });
}
}, 1);
document.addEventListener("keyup", function() { clearInterval(_setLeft); });
}
function moveRight() {
let _setRight = setInterval(function() {
_css([Net], {
left: (netInst.grid_position.lPos += netInst.motionPace) + "px"
});
if(netInst.grid_position.lPos > (mcw) - ((mcw) * (netInst.width / 100))) {
netInst.grid_position.lPos = ((mcw) - ((mcw) * (netInst.width / 100)));
_css([Net], { left: netInst.grid_position.lPos + "px" });
}
}, 1);
document.addEventListener("keyup", function() { clearInterval(_setRight); });
}
let _key = e.key;
switch(_key) {
case "ArrowLeft":
moveLeft();
break;
case "ArrowRight":
moveRight();
}
};
return this;
}
function loader() {
this.netLoad = function(netObj) {
let n = document.createElement("DIV");
n.setAttribute("id", "net");
_css([n], {
display: netObj.display,
width: netObj.width + "%",
height: netObj.height + "%",
background: netObj.background,
position: netObj.css_position,
left: netObj.grid_position.lPos + "px",
top: netObj.grid_position.tPos + "px"
});
main.appendChild(n);
document.addEventListener("keydown", netObj.motion);
}
return this;
}
const MAIN_WIDTH = main.clientWidth;
const MAIN_HEIGHT = main.clientHeight;
let netInst = new net(MAIN_WIDTH, MAIN_HEIGHT);
let Loader = new loader();
Loader.netLoad(netInst);
let Net = document.querySelector("#net");