I'm still learning JS and I'm trying to move this div with arrows using Javascript but it moves only 1 step per click can someone please help me how to make it moves more steps
check my code please
let
div = document.getElementById("test");
function move(e){
if(e.keyCode ==40){
div.style.top = 10+"px"
}
if(e.keyCode ==38){
div.style.top = -10+"px" }
if(e.keyCode==39){
div.style.left = 10 +"px"
}
if(e.keyCode==37){
div.style.left = -10 +"px"
}
}
window.onkeydown = move;
div{
width: 200px;
height: 200px;
background-color: red;
position: absolute;
}
<!DOCTYPE html>
<html>
<head>
<title>index</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div id="test"></div>
<script src="test.js"></script>
</body>
</html>
Try this code, you need the current position
I use getBoundingClientRect
You might also look at code instead of keyCode
const div = document.getElementById("test");
function move(e) {
const pos = div.getBoundingClientRect()
let top = pos.top;
let left = pos.left;
const code = e.code;
switch (code) {
case "ArrowRight": left += 10; break;
case "ArrowLeft" : left -= 10; break;
case "ArrowUp" : top -= 10; break;
case "ArrowDown" : top += 10; break;
}
div.style.top = `${top}px`;
div.style.left = `${left}px`;
}
window.addEventListener("keydown",move);
div {
width: 200px;
height: 200px;
background-color: red;
position: absolute;
}
<div id="test"></div>
You can save the current position then move it again, set an offset and add/remove distance at every keydown
const div = document.getElementById("test");
let position = 0
const offset = 10;
function move(e) {
if (e.keyCode == 40) {
position += offset;
div.style.top = position + "px"
}
if (e.keyCode == 38) {
position -= offset;
div.style.top = position + "px"
}
if (e.keyCode == 39) {
position += offset;
div.style.left = position + "px"
}
if (e.keyCode == 37) {
position -= offset;
div.style.left = position + "px"
}
}
document.onkeydown = move;
div {
width: 200px;
height: 200px;
background-color: red;
position: absolute;
}
<!DOCTYPE html>
<html>
<head>
<title>index</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div id="test"></div>
<script src="test.js"></script>
</body>
</html>
You are setting its offset to a fixed value of 10 or -10.
You need to store the current position somehow and offset the new position based on the current one.
//Intiate once at the beginning of the script
let currentVerticalPosition = 0;
if(e.keyCode ==40){
currentVerticalPosition += 10;
div.style.top = currentVerticalPosition +"px";
}
Related
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>
I have created three circles and made it bounce off the wall without using HTML canvas. Now I want two circles to collide with each other and move those circles in the opposite direction. I tried to detect the collision by checking it's position but it doesn't work. I don't know where I went wrong.
Here's my code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Bounce Ball</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.circle{
height: 50px;
width: 50px;
position: absolute;
border-radius: 50%;
}
.container {
height: 300px;
width: 300px;
background-color: skyblue;
position: relative;
}
</style>
</head>
<body>
<div class ="container" id ="container">
<div class="circle" id = "circle1" style="background-color:black;
height: 50px; width: 50px;top:0; left:0"></div>
<div class="circle" id ="circle2" style="background-color:rgb(197, 100,
100);height: 50px; width: 50px;top:200px;left: 150px"></div>
<div class="circle" id ="circle3" style="background-color:brown;height:
50px;width: 50px;top:50px;left: 640px"></div>
</div>
<script>
var container = document.getElementById("container");
container.style.width="700px";
container.style.height = "300px";
var balls = document.getElementsByClassName("circle");
for(var i=0; i <balls.length; i++){
var speed={x:3,y:-3}
setInterval(draw, 50 , balls[i], speed);
}
function draw(ball, speed) {
if(parseInt(ball.style.left) > (parseInt(container.style.width)-
parseInt(ball.style.width)) || (parseInt(ball.style.left) <0) ){
speed.x = -speed.x;
}
ball.style.left = parseInt(ball.style.left) + speed.x + 'px';
if(parseInt(ball.style.top) > (parseInt(container.style.height)-
parseInt(ball.style.height)) || (parseInt(ball.style.top) <0)){
speed.y = -speed.y;
}
ball.style.top = parseInt(ball.style.top) + speed.y + 'px';
//for colliding two circles
for(var i =0 ; i <= balls.length-1; i++){
for(var j = i + 1; j < balls.length; j++){
if(parseInt(balls[i].style.left) +
parseInt(balls[i].style.width) ==
parseInt(balls[j].style.left) ||
parseInt(balls[j].style.left) +
parseInt(balls[j].style.width) ==
parseInt(balls[i].style.left) &&
parseInt(balls[i].style.top) +
parseInt(balls[i].style.height) ==
parseInt(balls[j].style.top) || parseInt(balls[j].style.top)
+ parseInt(balls[j].style.height) ==
parseInt(balls[i].style.top)) {
speed.x = - speed.x;
speed.y = -speed.y;
}
ball[i].style.left = parseInt(ball[i].style.left) +
speed.x + 'px';
ball[j].style.left = parseInt(ball[j].style.left) +
speed.x + 'px';
ball[i].style.top = parseInt(ball[i].style.top) +
speed.y + 'px';
ball[j].style.top = parseInt(ball[j].style.top) +
speed.y + 'px';
}
}
}
</script>
</body>
</html>
I would recommend moving as much as possible into javascript variables so you don't need to consult the HTML for every parameter.
You had quite the number of typos, among them speed.x = - speed.x; where you meant speed.x = -speed.x; and your code was difficult to read without any comments or helper functions to explain what's going on.
I have fixed your typos and restructured your code in the snippet below. Try checking the developer console, typically by pressing F12, as this will show you code errors with line number and severity rating.
In my snippet below i have tried to move the parameters into JavaScript to show how that would work, while still leaving some on the HTML nodes:
//Basic properties
var width = 700;
var height = 300;
//Get container
var container = document.getElementById("container");
// Set dimensions
container.style.width = width + "px";
container.style.height = height + "px";
//Load balls
var balls = Array.prototype.slice.call(document.getElementsByClassName("circle"))
.map(function(ball) {
return {
HTMLNode: ball,
xPos: parseInt(ball.style.left),
yPos: parseInt(ball.style.top),
xAcc: 3,
yAcc: -3,
size: 50
};
});
//Utility functions
function angleBetween(x1, y1, x2, y2) {
return Math.atan2(y2 - y1, x2 - x1);
}
function distanceBetween(x1, y1, x2, y2) {
return Math.abs(y2 - y1) + Math.abs(x2 - x1);
}
//Draw function
function draw() {
//Loop through balls
for (var ballIndex1 = 0; ballIndex1 < balls.length; ballIndex1++) {
var ball1 = balls[ballIndex1];
//Collide with horisontal wall
if (ball1.xPos > width - ball1.size || ball1.xPos < 0) {
ball1.xAcc = -ball1.xAcc;
}
//Collide with vertical wall
if (ball1.yPos > height - ball1.size || ball1.yPos < 0) {
ball1.yAcc = -ball1.yAcc;
}
//Collide with other balls
for (var ballIndex2 = ballIndex1 + 1; ballIndex2 < balls.length; ballIndex2++) {
var ball2 = balls[ballIndex2];
//Test within collision distance
if (distanceBetween(ball1.xPos, ball1.yPos, ball2.xPos, ball2.yPos) > ball1.size) {
continue;
}
//Get angle of collision
var angle = angleBetween(ball1.xPos, ball1.yPos, ball2.xPos, ball2.yPos);
//Apply force to acceleration
ball1.xAcc = -Math.cos(angle) * 3;
ball2.xAcc = -ball1.xAcc;
ball1.yAcc = -Math.sin(angle) * 3;
ball2.yAcc = -ball1.yAcc;
}
//Apply acceleration to position
ball1.yPos += ball1.yAcc;
ball1.xPos += ball1.xAcc;
//Apply to node
ball1.HTMLNode.style.left = ball1.xPos + "px";
ball1.HTMLNode.style.top = ball1.yPos + "px";
}
}
//Start simulation
setInterval(draw, 1000 / 60);
.circle {
position: absolute;
border-radius: 50%;
height: 50px;
width: 50px;
}
.container {
height: 300px;
width: 300px;
background-color: skyblue;
position: relative;
}
<div class="container" id="container">
<div class="circle" id="circle1" style="background-color:black;
top:0; left:0"></div>
<div class="circle" id="circle2" style="background-color:rgb(197, 100,
100);top:200px;left: 150px"></div>
<div class="circle" id="circle3" style="background-color:brown;top:50px;left: 640px"></div>
</div>
I'm trying to create my own click and drag function in JavaScript without the use of jquery. I know that jquery is easy to implement, but I prefer my own code. What I have, as i click the div, then move the mouse, the div moves to the same spot and doesn't implement a "dragging" look to it. I'm not sure why this is. I want my outcome to be able to move the div over the image that way I can "crop" the image based on the div, etc. My code is:
index.js
function _(element) {
return document.getElementById(element);
}
index.css
body {
background-color: rgb(33, 66, 99);
margin: 0px;
padding: 0px;
}
img {
position:absolute;
}
.selection {
width: 200px;
height: 200px;
background-color: rgb(255,255,255);
position: absolute;
}
index.php
<!DOCTYPE html>
<html>
<head>
<meta charset = "UTF-8"/>
<title>Image Cropping</title>
<link rel = "stylesheet" href = "index.css"/>
<script src = "index.js"></script>
</head>
<body>
<div class = "image">
<img src = "model.jpg" alt = "Model" id = "theImage"/>
<div class = "selection" id = "selection"/>
</div>
<script>
_("theImage").ondragstart = function() { return false; };
var m = _("selection");
m.addEventListener("mousedown", mouseDown, false);
window.addEventListener("mouseup", mouseUp, false);
function mouseUp() {
window.removeEventListener("mousemove", move, true);
}
function mouseDown(e) {
window.addEventListener("mousemove", move, true);
}
function move(e) {
var x = m.style.left;
var y = m.style.top;
var mouseX = e.clientX;
var mouseY = e.clientY;
m.style.top += (mouseX - x) + "px";
m.style.left += (mouseY - y) + "px";
// Also tried: m.style.top = (mouseX - x) + "px";
// And : m.style.left = (mouseY - y) + "px";
}
</script>
</body>
</html>
To add the "dragging look to it", you can:
change the cursor (cursor: move;)
keep the cursor's offset relative to the mouse
For the second one, I reused a function I created for one of my projects, for which I implemented drag and drop for mobile, not wanting to use a big library:
/*
* Returns the given element's offset relative to the document.
*/
function realOffset(elem) {
var top = 0, left = 0;
while (elem) {
top = top + parseInt(elem.offsetTop, 10);
left = left + parseInt(elem.offsetLeft, 10);
elem = elem.offsetParent;
}
return { top: top, left: left };
}
Using this function, the math becomes simple:
m.style.left = (mouseX - offset.left) + "px";
m.style.top = (mouseY - offset.top) + "px";
Full demo
_("theImage").ondragstart = function () { return false; };
var m = _("selection"), offset;
m.addEventListener("mousedown", mouseDown, false);
window.addEventListener("mouseup", mouseUp, false);
function mouseUp() { window.removeEventListener("mousemove", move, true); }
function mouseDown(e) {
// SAVE THE OFFSET HERE
offset = {
left: e.pageX - realOffset(m).left,
top: e.pageY - realOffset(m).top
};
window.addEventListener("mousemove", move, true);
}
function move(e) {
// REUSE THE OFFSET HERE
m.style.left = (e.pageX - offset.left) + "px";
m.style.top = (e.pageY - offset.top) + "px";
}
/*
* Returns the given element's offset relative to the document.
*/
function realOffset(elem) {
var top = 0, left = 0;
while (elem) {
top = top + parseInt(elem.offsetTop, 10);
left = left + parseInt(elem.offsetLeft, 10);
elem = elem.offsetParent;
}
return { top: top, left: left };
}
function _(element) { return document.getElementById(element); }
body {
background-color: rgb(33, 66, 99);
margin: 0px;
padding: 0px;
}
img {
position:absolute;
}
.selection {
width: 200px;
height: 200px;
background-color: rgba(255,255,255,.5);
position: absolute;
cursor: move;
}
<div class="image">
<img src="http://i.imgur.com/vxkljMP.jpg" alt="Model" id="theImage" />
<div class="selection" id="selection"></div>
</div>
So now I've tried to implement sideways movement:
<!DOCTYPE html>
<html>
<head>
<title>Animation Bullshit</title>
<link rel="stylesheet" href="animation.css"/>
</head>
<body>
<div id="div">
</div>
<script type="text/javascript">
div = document.getElementById("div")
div.onmouseover = move, left;
div.onmouseout = up;
var cHeight = div.style.height | 150;
var cLeft = div.style.marginLeft | 0;
function move() {
if (cHeight < 300) {
cHeight += 10;
div.style.height = cHeight + "px";
setTimeout (move, 20);
}
}
function slide() {
if (cLeft < 400) {
cLeft += 10;
div.style.marginLeft = cLeft + "px";
setTimeout (slide, 20);
}
}
function up() {
if (cHeight > 150) {
cHeight -= 10;
div.style.height = cHeight + "px";
setTimeout (up, 20);
}
}
</script>
</body>
</html>
Everything loads, but when I mouse over the div, nothing happens. It doesn't even expand down. Suggestions?
It's telling me to add more details... Uh... The div is black, with an initial margin-left of 0px.
I just used your code.
Is this what you are looking for?
http://jsfiddle.net/tz2vcote/
I think its because you have not declared variable div with var. you should have checked firebug console.
checkout the updated one
http://jsfiddle.net/tz2vcote/2/
click on the div for slide effect.
I am trying to mimic something that I have seen a few different times. There is usually a banner with a nav bar below and when the page is scrolled it moves until it touches the top then stops and stays fixed. I am not completely sure how to accomplish this. I have seen a few different things that just dont work.
After looking around I figured out it will work something like this but I can seem to get it to work. I think I am missing some stuff
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<style type="text/css">
<!--
#Table_01 {
position:relative;
left:0px;
top:0px;
width:1020px;
height:854px;
text-align: left;
margin-right: auto;
margin-left: auto;
}
body {
font-family: Verdana, Geneva, sans-serif;
font-size: 12px;
color: #a4c639;
text-align: center;
margin: 0px;
}
-->
</style>
<script type='text/javascript'>
var topPos = 120;
var updatedPos;
window.onscroll = navPos;
if (!topPos) {
topPos = 120;
}
function navPos() {
var pos = window.scrollY;
if (!topPos) {
topPos = 120;
}
var st = document.getElementById('navTest');
if (st) {
if (pos < topPos && updatedPos != 'absolute') {
st.style.position = 'absolute';
st.style.top = topPos + 'px';
updatedPos = 'absolute';
//alert('Switched to absolute');
} else if (pos >= topPos && updatedPos != 'fixed') {
st.style.position = 'fixed';
st.style.top = '0';
updatedPos = 'fixed';
//alert('Switched to fixed');
}
}
}
navPos();
</script>
</head>
<body>
<div id="Table_01">
<div id='navTest' style='position:absolute;z-index:999;top:120px;left:0; height:50px;width:100%; background-color:#000;' width='100%'>
</div>
</div>
</body>
</html>
All references to a non-existant navTopPos variable should be changed to reference the topPos variable. Your JS code should now be:
var topPos;
var updatedPos;
window.onscroll = navPos;
if (!topPos) {
topPos = 120;
}
function navPos() {
var pos = window.scrollY;
if (!topPos) {//this line was changed
topPos = 120;//this line was changed
}
var st = document.getElementById('navTest');
if (st) {
if (pos < topPos && updatedPos != 'absolute') {
st.style.position = 'absolute';
st.style.top = topPos + 'px';//this line was changed
updatedPos = 'absolute';
//alert('Switched to absolute');
} else if (pos >= topPos && updatedPos != 'fixed') {
st.style.position = 'fixed';
st.style.top = '0';
updatedPos = 'fixed';
//alert('Switched to fixed');
}
}
}
navPos();
The interpreter died somewhere here:
if (!topNavPos) {
topNavPos = 120;
}
Updated JSFiddle with the necessary changes.