Issues with using JavaScript to increment the position of an element - javascript

A previous QUESTION I had has led me to construct the code below. What Im trying to do is increment the element up/down/left/right based on keyboard arrow selection
"<div id="test"></div>"
by 20 pixels (or however many I chose) at a time. I have the "left" and "right" direction working for the most part but something interesting keeps happening when I try and change directions. First off whichever direction I initially chose to go first does not work on the first key press, I have to hit the arrow key of either left or right twice to start transitioning. Then once the transitions do start working; if im traveling left and then want to change direction to the right; it goes left even though im hitting the right key at least once before it goes the correct direction corresponding to the key I chose. This is a bit difficult to explain by text so here is the code pen so you can see what I mean. CODEPEN (hit the left and right arrow keys a couple times so clearly see the issue)
Also the functions moveDown() and moveUp() dont even move the box positioning at all. To try and trouble shoot the problem I added console.log('moveUp') and console.log('moveDown') in order to see whether the console was recognizing the key code when I struck it, and it clearly does. It even recognizes when I strike the left or right key but still runs the incorrect direction at-least once before it starts going the correct direction on the left and right keys.
I have a feeling it make have to do with transitions not being cleared or maybe using an IF statement might not be the base way to read the key code?
Also thought about using switch case for JavaScript key code recognition but I am pretty sure the issue would still be the same and im not skilled enough to pull off switchcase yet.
ALL I WANT is the box to go the direction I tell it to go using the arrows on my keypad, I am close but as you can see I am missing some key concepts
document.addEventListener("keydown", keyBoardInput);
var left = 0;
var top = 0;
function moveUp() {
console.log('moveUp');
document.getElementById("test").style.top = top + "px";
top -= 20;
document.getElementById("test").style.transition = "all 1s";
};
function moveDown() {
console.log('moveDown');
document.getElementById("test").style.top = top + "px";
top += 20;
document.getElementById("test").style.transition = "all 1s";
};
function moveLeft() {
console.log('moveLeft');
document.getElementById("test").style.left = left + "px";
left -= 20;
document.getElementById("test").style.transition = "all 1s";
};
function moveRight() {
console.log('moveRight');
document.getElementById("test").style.left = left + "px";
left += 20;
document.getElementById("test").style.transition = "all 1s";
};
function keyBoardInput() {
var i = event.keyCode;
if (i == 38) {
moveUp()
};
if (i == 40) {
moveDown()
};
if (i == 37) {
moveLeft()
};
if (i == 39) {
moveRight()
};
};
#test {
position: relative;
width: 30px;
border: 1px solid blue;
height: 10px;
top: 0px;
left: 0px;
}
<div id="test"></div>

2 issues: You updated your globals too late, just do it before you use it on the element. And the variable name "top" is reserved, just use another one (see this blog post). Here the code:
document.addEventListener("keydown", keyBoardInput);
var left = 0;
var topx = 0;
function moveUp() {
console.log('moveUp');
topx -= 20;
document.getElementById("test").style.top = topx + "px";
document.getElementById("test").style.transition = "all 1s";
};
function moveDown() {
console.log('moveDown');
topx += 20;
document.getElementById("test").style.top = topx + "px";
document.getElementById("test").style.transition = "all 1s";
};
function moveLeft() {
console.log('moveLeft');
left -= 20;
document.getElementById("test").style.left = left + "px";
document.getElementById("test").style.transition = "all 1s";
};
function moveRight() {
console.log('moveRight');
left += 20;
document.getElementById("test").style.left = left + "px";
document.getElementById("test").style.transition = "all 1s";
};
function keyBoardInput() {
var i = event.keyCode;
if (i == 38) {
moveUp()
};
if (i == 40) {
moveDown()
};
if (i == 37) {
moveLeft()
};
if (i == 39) {
moveRight()
};
};
#test {
position: relative;
width: 30px;
border: 1px solid blue;
height: 10px;
top: 0px;
left: 0px;
}
<div id="test"></div>

You need to do the arithmetic for top and left before setting it in the CSS :)
function moveUp() {
console.log('moveUp');
top -= 20;
document.getElementById("test").style.top = top + "px";
document.getElementById("test").style.transition = "all 1s";
};
function moveDown() {
console.log('moveDown');
top += 20;
document.getElementById("test").style.top = top + "px";
document.getElementById("test").style.transition = "all 1s";
};
function moveLeft() {
console.log('moveLeft');
left -= 20;
document.getElementById("test").style.left = left + "px";
document.getElementById("test").style.transition = "all 1s";
};
function moveRight() {
console.log('moveRight');
left += 20;
document.getElementById("test").style.left = left + "px";
document.getElementById("test").style.transition = "all 1s";
};
Here's a working fiddle: https://jsfiddle.net/x2yxexs9/

Related

Circle moving out of window

var circle = document.getElementById("circle");
function moveUp() {
var top = circle.offsetTop;
newTop = top - 10;
circle.style.top = newTop + "px";
console.log("moveUP Called")
}
function moveDown() {
var top = circle.offsetTop;
newTop = top + 10;
circle.style.top = newTop + "px";
console.log("moveDown Called")
}
function moveLeft() {
var left = circle.offsetLeft;
newLeft = left - 10;
circle.style.left = newLeft + "px";
console.log("moveLeft Called")
}
function moveRight() {
var left = circle.offsetLeft;
newLeft = left + 10;
circle.style.left = newLeft + "px";
console.log("moveRight Called")
}
window.addEventListener("keypress", (event) => {
if (event.key == 'w') {
moveUp();
} else if (event.key == 's') {
moveDown();
} else if (event.key == 'a') {
moveLeft();
} else if (event.key == 'd') {
moveRight();
}
})
body {
margin: 2px;
background-color: aquamarine;
}
#circle {
height: 100px;
width: 100px;
background-color: blue;
border-radius: 50%;
position: absolute;
}
In the above code where on key press circle moves, for example on 'w' it moves up, for 's' it moves down and so on.
But the problem is that the circle even moves out of the window, how do I fix it and what is the problem??
var circle = document.getElementById("circle");
console.log(window.innerWidth, window.innerHeight)
function moveUp() {
var top = circle.offsetTop;
console.log(top)
newTop = top - 10;
if(newTop < 0) {
newTop = 0;
}
circle.style.top = newTop + "px";
}
function moveDown() {
var top = circle.offsetTop;
var height = circle.offsetHeight + top;
if((height + 10) >= window.innerHeight) {
return;
}
newTop = top + 10;
circle.style.top = newTop + "px";
/* console.log("moveDown Called") */
}
function moveLeft() {
var left = circle.offsetLeft;
newLeft = left - 10;
if(newLeft<0) {
newLeft = 0;
}
circle.style.left = newLeft + "px";
}
function moveRight() {
var left = circle.offsetLeft;
newLeft = left + 10;
if(newLeft > window.innerWidth - 100 ) {
newLeft = window.innerWidth - 100 ;
}
circle.style.left = newLeft + "px";
}
window.addEventListener("keypress", (event) => {
if (event.key == 'w') {
moveUp();
} else if (event.key == 's') {
moveDown();
} else if (event.key == 'a') {
moveLeft();
} else if (event.key == 'd') {
moveRight();
}
})
body{
margin:2px;
background-color: aquamarine;
}
#circle{
height: 100px;
width: 100px;
background-color: blue;
border-radius: 50%;
position: absolute;
overflow: hidden;
}
<div id="circle">
</div>
Explaination
for moveup() if the position is a negative number that means the div is going out of the viewport. So with the if condition new position will be always set to 0 preventing the div to go negative position.
for moveDown() first you get the offsetTop which means how far is the box from top position along with the offsetHeight which represents the height of the box. So add these two to get the total height. Now simply check if this height is going over the innerHeight + the distance(10) you are going with each move. If it is more than the innerHeight simply return. otherwise move the box.
moveLeft() is same as moveUp().
moveRight() is also same as moveDown() but here we're calculating the innerWidth. Subtract it with the box width so it doesn't go outside the viewport. Now simple condition check and set the new right position.
hope it helped
What is the problem?
There is no problem. CSS does exactly what you told it to do.
For example, you can click on 'w' couple of times, which will set left property for your absolutely positioned circle to, let's say, -160px. This will instruct the browser to move your element to the left, away from the viewport, i.e. to position it -160px of the left edge of the initial containing block or nearest positioned ancestor. More about left property: https://developer.mozilla.org/en-US/docs/Web/CSS/left
I would not say that it is a problem, because it is exactly what left is used for - move elements to whatever position you like. Sometimes you can hide elements by setting their position: absolute; left: -10000px;
How do I fix it?
If you don't want your circle to move away from the viewport, you need to check if your circle is 'touching' the viewport. I will use example with the left, but the same logic can be applied to top, right and bottom.
So for the left, this will consist of two parts:
Check what is the initial distance from your circle to the left edge of the viewport.
Check if absolute value of your new left value is not greater than this distance.
For example, for the left method:
var elDistanceToLeft = window.pageXOffset + circle.getBoundingClientRect().left;
function moveLeft() {
let left = circle.offsetLeft;
newLeft = Math.abs(left - 10) <= elDistanceToLeft ? left - 10 : -elDistanceToLeft;
circle.style.left = newLeft + "px";
}
In this case your circle will move all way to the left (on pressing 'a') until it 'touches' the viewport (screen). Then it will stop.
Here is a code snippet
var elDistanceToLeft = window.pageXOffset + circle.getBoundingClientRect().left
function moveLeft() {
let left = circle.offsetLeft;
newLeft = Math.abs(left - 10) <= elDistanceToLeft ? left - 10 : -elDistanceToLeft;
circle.style.left = newLeft + "px";
}
window.addEventListener("keypress", (ev) => { if (ev.key == 'a') { moveLeft();} })
#circle {
height: 100px;
width: 100px;
background-color: blue;
border-radius: 50%;
position: absolute;
}
#parent {
position: relative;
padding: 200px;
}
<div id="parent">
<div id="circle"></div>
</div>

How can I make a car turn when I want to go the other way using arrows on the keyboard

Image1
Image2
On visual studio code I can move the car forth and back with the arrows on the keyboard. but it doesnt turn when I want to go opposite ways. Is there a way to do with animation. also it doesnt wanna move on the code snippet for some reason but it works on my visual studio code
var bodyEl = document.querySelector("body");
var boxEl = document.querySelector("div");
var left = 0;
var top = 180;
var speed = 10;
bodyEl.addEventListener ("keydown", moveBox);
function moveBox(e) {
if (e.keyCode === 37) {
left -= speed;
}
else if (e.keyCode === 39) {
left += speed;
}
else if (e.keyCode === 38) {
top -= speed;
}
else if (e.keyCode === 40) {
top += speed;
}
boxEl.style.top = top + "px";
boxEl.style.left = left + "px";
}
body {
background-image: url("https://i.stack.imgur.com/x1iaz.jpg");
cursor: none;
overflow: hidden;
}
div {
position: absolute;
top: 180px;
}
<div><img src="https://i.stack.imgur.com/9dPYr.png" height="300px" width="300px" ></div>
Try to add a custom class while the right arrow press and remove it while the left arrow press. you can do the same for up and down arrow keys.
Add CSS -
div.reverse img {
-webkit-transform: scaleX(-1);
transform: scaleX(-1);
}
Update function JS -
function moveBox(e) {
if (e.keyCode === 37) {
boxEl.classList.remove("reverse");
left -= speed;
}
else if (e.keyCode === 39) {
boxEl.classList.add("reverse");
left += speed;
}
else if (e.keyCode === 38) {
top -= speed;
}
else if (e.keyCode === 40) {
top += speed;
}
boxEl.style.top = top + "px";
boxEl.style.left = left + "px";
}

How to get an image to move up and down with javascript

Using html and javascript, i create variables in js to corrospond to the buttons i made in html, they are to make an image move left, right, up, and down.
the image move left and right just fine but i can't seem to get it to move up or down. i thought it should work similary to moving it left and right but it doesnt seem to work.
here is the code i have
leftButton.addEventListener("click", moveLeft);
rightButton.addEventListener("click", moveRight);
downButton.addEventListener("click", moveDown);
rocketPicture.style.position = "relative";
rocketPicture.style.left = '0px';
function moveLeft(){
rocketPicture.style.left = parseInt(rocketPicture.style.left ) - 10 + 'px';
}
function moveRight(){
rocketPicture.style.left = parseInt(rocketPicture.style.left ) + 10 + 'px';
}
function moveDown(){
rocketPicture.style.top = parseInt(rocketPicture.style.top) + 10 + 'px';
You have assigned an initial value - 0 - for style.left, but not for style.top, hence checking its value gives undefined.
Now, parseInt(undefined) returns NaN, and doing anything mathematical with NaN just puts more NaN in this world.
Solution: assign an initial value for style.top in the same way you did for style.left.
As a sidenote, it might be worthwhile to unify all those move functions in the same step func, like this:
function move(dir, delta) {
const prev = parseInt( rocketPicture.style[dir] );
// assert !Number.isNaN(prev)
rocketPicture.style[dir] = prev + delta + 'px';
}
function moveUp() { move('top', -10) }
function moveDown() { move('top', 10) }
function moveLeft() { move('left', -10) }
function moveRight() { move('left', 10) }
Why not use Element#getBoundingClientRect ? It provides information regarding your element including its top and left position without having to convert the values with parseInt.
It looks something like this:
{
"x": 50,
"y": 100,
"width": 124,
"height": 119.19999694824219,
"top": 100,
"right": 174,
"bottom": 219.1999969482422,
"left": 50
}
Working solution:
const box = document.getElementById("item");
function vertical(value){
const {top} = box.getBoundingClientRect();
box.style.top = `${top + value}px`;
}
function horizontal(value){
const {left} = box.getBoundingClientRect();
box.style.left = `${left + value}px`;
}
#item {
padding: 50px;
position: absolute;
background-color: purple;
color: white;
left: 50px;
top: 100px;
}
<div id="item">
box
</div>
<button onclick="vertical(-10)">Up</button>
<button onclick="vertical(10)">Down</button>
<button onclick="horizontal(-10)">Left</button>
<button onclick="horizontal(10)">Right</button>

I want to stop my div from moving

I have a code which causes the waterlevel in a bottle to go up or down by clicking a button. however, it can't stop without clicking on stop. I need it to basically reset when it empties, and that the div of the waterlevel doesn't go below a certain point (or above a certain point). If you're interested in what I'm making; I'm making an alcohol simulator. So you'll basically see the waterlevel of an alcohol drink going down (i.e. 100 px), and 100 px down means that you can see the waterlevel(alcogol level) in the stomach with i.e. 50 px, and that equals 20 px in the blood circulation and 10 px in the brains. (just to get an idea.)
But if I click on the button of going down, the div will just leave the bottle and will have an endless journey. (js please, not jquery)
here's my JS code:
function move_img(str) {
var step=2 ; // change this to different step value
switch(str){
case "down":
var x=document.getElementById('i1').offsetTop;
x= x + step;
document.getElementById('i1').style.top= x - 1 + "px";
break;
case "up":
var x=document.getElementById('i1').offsetTop;
x= x -step;
document.getElementById('i1').style.top= x + "px";
break;
case "left":
var y=document.getElementById('i1').offsetLeft;
y= y - step;
document.getElementById('i1').style.left= y + "px";
break;
case "right":
var y=document.getElementById('i1').offsetLeft;
y= y + step;
document.getElementById('i1').style.left= y + "px";
break;
}
}
function auto(str) {
myVar = setInterval(function(){ move_img(str); }, 2) ;
}
setTimeout(function( ) { clearInterval( myVar ); }, 1);
function nana(){
}
Your fiddle doesn't work. You'll need to specify the height as well as the top attribute, and I believe top has to be above bottom. I've made an example here. The changes to your examples are:
//javascript
if (str == 'up' || str == 'down') {
var top = el.offsetTop;
var height = el.offsetHeight; //get height to modify
console.log(height);
if (str == 'up') {
top -= step;
height += step; //adjust height
} else {
top += step;
height -=step; //adjust height
}
if (top_max >= top && top >= 0) { //make sure #i1 is inside #i
document.getElementById('i1').style.top = top + "px";
document.getElementById('i1').style.height = height + "px"; //modify height
} else {
clearInterval(myVar)
}
//css
#i1 {
width: 100px;
display: inline-block;
background:red;
position: absolute;
top: 150px; //initial top
bottom: 250px; //as as bottom of #i
height:100px; //initial height
}

Moving an image with 360° angle in Javascript

I am trying to make an image move 360° (not rotate) back it's course, but so far I was able to move only to a specific direction, if I add left & bottom course, then the image going diagonal to left & bottom. Here are the properties:
CSS
#circle{
background:red;
border-radius:100px;
height:100px; width:100px;
position:absolute;
}
JavaSript
(function() {
var speed = 10,
moveBox = function(){
var el = document.getElementById("circle"),
left = el.offsetLeft,
moveBy = 3;
el.style.left = left + moveBy + "px";
if(left > 200){
clearTimeout(timer);
}
};
var timer = setInterval(moveBox, speed);
}());
HTML:
<div id='circle'></div>
JsFiddle Online Demo
The problem is looping back the red circle, I want it to move to left > bottom > right > up
in a circular manner.
thanks for the help.
Using Math.sin and Math.cos to describe the circle: http://jsfiddle.net/E3peq/7/
(function() {
var speed = 10,
moveX = 0.1,
moveY = 0.1,
increment = 0.1,
amp = 10,
moveBox = function(){
var el = document.getElementById("circle"),
left = el.offsetLeft,
top = el.offsetTop;
moveX += increment;
moveY += increment;
var moveXBy = Math.cos(moveX) * amp;
var moveYBy = Math.sin(moveY) * amp;
el.style.left = (left + moveXBy) + "px";
el.style.top = (top + moveYBy) + "px";
if(left > 200){
clearTimeout(timer);
}
};
var timer = setInterval(moveBox, speed);
}());
Edit: Abraham's answer in the comments is actually a lot nicer looking than this...

Categories

Resources