How to move an element styled by CSS stylesheet? - javascript

I have an image that I want to move. I can move the element with javascript if I have the HTML below:
<html>
<head>
<title>Snake</title>
<script type="text/javascript" src="snake.js"></script>
<!-- <link type="text/css" href="snake.css"> -->
</head>
<body onKeyPress="ProcessKeypress(event);">
<p><img id="snake" style="z-index: 0; left: 300px; position: absolute; top: 250px"
float=top border=0 hspace=0 src="snake.gif"></p>
</body>
However I want to stye the image element using CSS. When I do this my code to move the image does not work. HTML and CSS below are what I would like to use.
<html>
<head>
<title>Snake</title>
<script type="text/javascript" src="snake.js"></script>
<link type="text/css" href="snake.css">
</head>
<body onKeyPress="ProcessKeypress(event);">
<p><img id="snake" src="snake.gif"></p>
</body>
#CHARSET "UTF-8";
img {
z-index: 0;
left: 300px;
position: absolute;
top: 250px;
float: top;
border: 0;
hspace: 0;
}
JavaScript below is what I am using to move the image. Any and all help appreciated.
function moveObj(name, Xpix, Ypix)
{
obj = document.getElementById(name);
px = parseInt(obj.style.left) + Xpix;
py = parseInt(obj.style.top) + Ypix;
obj.style.left = px;
obj.style.top = py;
}
function ProcessKeypress(e)
{
var myObj = 'snake';
var moveBy = 10;
if(e.keyCode === 97) {
moveObj(myObj, -moveBy, 0);
}
else if(e.keyCode === 100) {
moveObj(myObj, moveBy, 0);
}
else if(e.keyCode === 115) {
moveObj(myObj, 0, moveBy);
}
else if(e.keyCode === 119) {
moveObj(myObj, 0, -moveBy);
}
}

obj.style.left accesses the style properties defined in inline only.
UPDATE
Here is your pure JavaScript Solution
Function: getStyleProp() to get the current applied style [Source]
function getStyleProp(elem, prop){
if(window.getComputedStyle)
return window.getComputedStyle(elem, null).getPropertyValue(prop);
else if(elem.currentStyle) return elem.currentStyle[prop]; //IE
}
Function: moveObj()
function moveObj(obj, Xpix, Ypix) {
obj.style.left = parseInt(getStyleProp(obj,'left')) + Xpix+"px";
obj.style.top= parseInt(getStyleProp(obj,'top')) + Ypix + "px";
}
Function: ProcessKeypress()
function ProcessKeypress(e) {
var myObj = document.getElementById("snake");
var moveBy = 10;
switch(e.charCode) {
case 97: moveObj(myObj, -moveBy, 0); break;
case 100: moveObj(myObj, moveBy, 0); break;
case 115: moveObj(myObj, 0, moveBy); break;
case 119: moveObj(myObj, 0, -moveBy); break;
}
}
I also solved your case using jQuery: Demo
Function moveObj
function moveObj(obj, Xpix, Ypix) {
obj.css('left', parseInt(obj.css('left')) + Xpix);
obj.css('top', parseInt(obj.css('top')) + Ypix);
}
Function ProcessKeypress
function ProcessKeypress(e) {
var myObj = $("#snake"); //It will be better if it is cached
var moveBy = 10;
switch(e.charCode) { //used Switch for better manageability
case 97: moveObj(myObj, -moveBy, 0); break;
case 100: moveObj(myObj, moveBy, 0); break;
case 115: moveObj(myObj, 0, moveBy); break;
case 119: moveObj(myObj, 0, -moveBy); break;
}
}
Event Trigger attached to document instead
$(document).on('keypress', ProcessKeypress);

I'm not sure if your code was a copy-paste, but you need to close the link tag to link in your css.
<link rel="stylesheet" type="text/css" href="location" />
But that is beside the point. This is a repost so I'm going to flag it as that. Refer to Why is element.style.left returning NaN?
That should answer your question. It answered mine as I worked through your code and it made sense. Good luck.

Related

How can I diagonally move an element using Javascript?

I've created an article with a red background, you can move it using WASD keys, however, the real trouble comes in when I try to create a diagonal movement (for ex, if W and D are pressed, the article should go to the top right corner), it doesn't seem to work:
document.body.addEventListener('keypress', function(event) {
var oldLeft = getComputedStyle(document.body).left,
newLeft;
var oldTop = getComputedStyle(document.body).top,
newTop;
oldLeft = parseInt(oldLeft, 10);
oldTop = parseInt(oldTop, 10);
console.log(event);
if ( event.key == 'a') {
newLeft = oldLeft - 10;
}
else if ( event.key == 'd') {
newLeft = oldLeft + 10;
}
else if (event.key == 'w') {
newTop = oldTop - 10;
}
else if (event.key == 's') {
newTop = oldTop + 10;
}
//HERE
if ((event.key =='w') || (event.key == 'd')) {
newLeft = oldLeft + 10;
newTop = oldTop - 10;
}
document.body.style.left = newLeft + 'px';
document.body.style.top = newTop + 'px';
});
article {
width: 33.75em;
padding: 1.5em;
margin: 0 auto;
background: #f6be00;
/*border: 4px solid white;*/
border-radius: 1.25em;
position: relative;
left: 0;
}
body {
position: relative;
background: red;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="css/styles.css">
<title>Javascript</title>
</head>
<body>
<article class="article">
<ul id="browser">
</ul>
<ul id="user">
</ul>
</article>
<script src="javascript/main.js"></script>
</body>
</html>
It goes to the top right corner but that happens even when I don't press W and D at the same time.
Use keydown events to collect keys to an array, and keyup events to wait until all keys are un-pressed to execute the changes:
var clicked = {};
document.body.addEventListener('keydown', function(event) {
clicked[event.key] = false; // collect keys an init as false
});
document.body.addEventListener('keyup', function(event) {
clicked[event.key] = true; // change keys to true
// if not all keys are true don't execute anything
if (!Object.values(clicked).every(Boolean)) return;
var left = parseInt(getComputedStyle(document.body).left, 10);
var top = parseInt(getComputedStyle(document.body).top, 10);
// get the clicked keys
const keys = Object.keys(clicked);
// iterate them and change the values
keys.forEach(function(key) {
switch (key) {
case 'a':
{
left -= 10;
break;
}
case 'd':
{
left += 10;
break;
}
case 'w':
{
top -= 10;
break;
}
case 's':
{
top += 10;
break;
}
}
});
clicked = {}; // clear clicked keys
document.body.style.left = left + 'px';
document.body.style.top = top + 'px';
});
article {
width: 33.75em;
padding: 1.5em;
margin: 0 auto;
background: #f6be00;
/*border: 4px solid white;*/
border-radius: 1.25em;
position: relative;
left: 0;
}
body {
position: relative;
background: red;
}
<article class="article"></article>

How can I move this object with the arrow keys in Javascript?

I made an object out of a div in html and CSS to make a player for my game I am making and I can't get the player to move when I press the arrow keys. Does anyone know what is wrong with my code?
Here is the Javascript:
var player = document.getElementById("player");
var velocity = 5;
let player = {
height:20,
width:20,
x:200,
y:200
}
document.addEventListener("keydown", function(event){
if(event.keyCode === 37){
player.x -= velocity:
else if(event.keyCode ===38){
player.y -=velocity;
}
});
What is wrong?
Moving a div using simple Javascript just adding switch on keydown event on document and then customzing the css of div (player) top-left
var player = $('#player');
var velocity = 5;
$(document).keydown(function(e) {
switch (e.which) {
case 37:
player.css('left', player.offset().left - velocity);
break;
case 38:
player.css('top', player.offset().top - velocity);
break;
case 39:
player.css('left', player.offset().left + velocity);
break;
case 40:
player.css('top', player.offset().top + velocity);
break;
}
})
#player {
background: #ccc;
height: 50px;
width: 50px;
position: absolute;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<body>
<div id="player"></div>
</body>
</html>
With an addition to Ibnelaiq's answer, here's a way to make sure the players can move better -
var key = [];
function keys(db, e) {
var code = e.which || e.keyCode;
if (db == false && key.includes(code) === false) {
key.push(code);
} else if (db === true) {
key.splice(key.indexOf(code));
}
}
setInterval(() => {
console.log(key);
}, 30);
document.getElementsByClassName('game')[0].getContext('2d').fillText('Click here and press keys', 10, 10);
.game {
background-color: #f1f1f1;
outline: none;
border: 1px solid black;
}
<canvas class='game' tabindex='1' width='400px' height='290px' onkeydown='keys(false, event)' onkeyup='keys(true, event)'>
What this does:
<canvas> (not limited to <canvas> though) waits for keydown and adds event.keycode or event.which to the array. It also waits for keyup, and removes whatever event.keycode or event.which was released from the array.
The setInterval is just there to log the array into the console. The last line in the code is there to write text into <canvas>.
Of course, you can add his switch statement into the setInterval, but in there only.

location.reload(); is delayed on remote server (locally works instantly)

Everything works like a charm locally when red block hits black block, it refreshes instantly (coming to start position). I can't figure out why the website doesn't refresh after collision (game over) on the remote server. Sometimes it needs few seconds to react or it requires moving the player position.
Found a tip to replace
location.reload(true);
with
location.href = location.href;
but it doesn't work at all in my case.
Fiddle to inspect my code: https://jsfiddle.net/32o8q5gz/1/
Remote host: https://stacho163.000webhostapp.com/
HTML code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Obulis 2</title>
<link rel="stylesheet" type="text/css" href="gameStyle.css">
</head>
<body>
<div class="game-content">
<h1>Obulis 2</h1>
<canvas id="game-window">
</canvas>
</div>
<script src="gameScript.js"></script>
</body>
</html>
CSS code:
* {
margin: 0;
padding: 0;
}
body {
background-color: #000;
}
.game-content {
position: relative;
width: 100vw;
height: 100vh;
}
h1 {
position: absolute;
color: red;
font-size: 50px;
left: 50%;
top: 1.5%;
transform: translate(-50%);
}
#game-window {
position: absolute;
width: 90vw;
height: 90vw * 16/9;
top: 50%;
left: 50%;
transform: translate(-50%, -46%);
background-color: gray;
}
JS code:
// js game script //
let canvas = document.getElementById('game-window');
let ctx = canvas.getContext('2d');
ctx.canvas.width = window.innerWidth;
ctx.canvas.height = window.innerHeight;
let left = false;
let up = false;
let right = false;
let down = false;
let player = {
size: 50,
posX: (canvas.width / 2) - 25,
posY: (canvas.height / 2) - 25,
speed: 5
}
let obstacle = {
size: Math.round((Math.random() * 100) + 50),
posX: Math.round((Math.random() * 1200) + 50),
posY: -50,
speed: Math.round((Math.random() * 10) + 1)
}
function drawPlayer() {
ctx.fillStyle = "red";
ctx.fillRect(player.posX, player.posY, player.size, player.size);
}
function drawObstacle() {
ctx.fillStyle = "#000";
ctx.fillRect(obstacle.posX, obstacle.posY, obstacle.size, obstacle.size);
obstacle.posY += obstacle.speed;
}
function darknessCollision() {
if (player.posX < 0 ||
player.posY < 0 ||
player.posX > canvas.width - player.size ||
player.posY > canvas.height - player.size) {
location.reload(true);
}
}
function obstacleCollision() {
if (player.posX <= obstacle.posX + obstacle.size &&
player.posY <= obstacle.posY + obstacle.size &&
player.posX + player.size >= obstacle.posX &&
player.posY + player.size >= obstacle.posY) {
location.href = location.href;
}
}
function clearCanvas() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
function move() {
if (left) {
player.posX -= player.speed;
}
if (up) {
player.posY -= player.speed;
}
if (right) {
player.posX += player.speed;
}
if (down) {
player.posY += player.speed;
}
}
document.onkeydown = function (e) {
if (e.keyCode == 37) left = true;
if (e.keyCode == 38) up = true;
if (e.keyCode == 39) right = true;
if (e.keyCode == 40) down = true;
e.preventDefault();
}
document.onkeyup = function (e) {
if (e.keyCode == 37) left = false;
if (e.keyCode == 38) up = false;
if (e.keyCode == 39) right = false;
if (e.keyCode == 40) down = false;
e.preventDefault();
}
setInterval (function game() {
clearCanvas();
drawObstacle();
drawPlayer();
darknessCollision();
obstacleCollision();
move();
}, 10);
Thanks in advance for your tips! :)
This is a completely normal behavior.
When you refresh a local website, the only delay is the time spent reading the website again from your computer’s memory, and even that can get much faster for many reasons.
However, refreshing an online website, usually (if not cached), requires a “round trip time” from your computer to the server, which is sometimes costing few seconds.
If refreshing the page is for the sake of getting new updates, unfortunately there is no way to reduce the refreshing time. But, if you just need to start the website one more time, you can either use JavaScript history methods as mentioned, or have a JavaScript function that returns you to the first state without the need to refresh at all.
Hope this helps.
Two other options:
history.go(0);
And:
window.location.href = window.location.href;

How do I remove an already drawn image from HTML5 Canvas (just that one not other ones)

So, I have to make this project for school and I need to be able to remove one image specifically because when I do clearRect() it removes all images.
<!DOCTYPE html>
<html>
<head>
<title>Game</title>
<style type="text/css">
* { margin:0; padding:0; } /* to remove the top and left whitespace */
html, body { width:100%; height:100%; } /* just to be sure these are full screen*/
canvas { display:block; } /* To remove the scrollbars */
#gC {
position: relative;
left: 16vw;
top: 9vh;
margin: 0;
padding: 0;
}
body {
background-image: url('bg.jpeg') !important;
overflow: hidden !important;
}
</style>
</head>
<body> <canvas id="gC" width="1500" height="1000"></canvas>
<script type="text/javascript">
var canvas = document.querySelector("#gC");
var ctx = canvas.getContext("2d");
var team1 = new Image();
var bT = new Image();
var t1_x = 150;
var t1_y = 100;
var bT_x = 50;
var bT_y = 350;
var AI_I = 0;
team1.src = "team1.png";
bT.src = "bT.png";
function team1AI() {
ctx.clearRect(0, 0, canvas.height, canvas.width);
ctx.drawImage(bT, bT_x, bT_y);
ctx.drawImage(team1, t1_x, t1_y);
t1_x++;
}
var t1AI = setInterval(team1AI,10);
function t1AI_inter(){
if(AI_I >= 90){
clearInterval(t1AI);
}
AI_I++;
}
function leftArrowPressed(){
ctx.clearRect(0, 0, canvas.height, canvas.width);
ctx.drawImage(bT, bT_x, bT_y);
bT_x-=5;
}
function moveSelection(evt) {
switch (evt.keyCode) {
case 37:
leftArrowPressed();
break;
case 39:
rightArrowPressed();
break;
case 38:
upArrowPressed();
break;
case 40:
downArrowPressed();
break;
/*
case 32:
spaceKeyPress();
break;
*/
}
}
setInterval(t1AI_inter,10);
window.addEventListener('keydown', moveSelection);
</script>
Games are not (usually) based on events like "keydown". They are based on loops, one loop of frames. In every frame or iteration, you should, for example,
read the user input
update the status of every component of your game
draw the new frame
Anyway, if you want to remove just one image, just remove all of them and redraw just the ones that should be visible.
You could have an array with the status (visible or not) of every image or something like this:
var images = [
{visible: false},
{visible: true},
{visible: true}
];
You could also use a function "draw" which draws the images based in the previous array and another two functions called "hide" and "show", which could receive the index of the image to hide or show, update its status in the array and then call the draw function.
If you want to go ahead, read about game loops and specially about the requestAnimationFrame function, which is used in web game development.
I just figured it out! All I had to do is:
ctx.clearRect(t1_x,t1_y,canvas.height,canvas.width);

Using JavaScript Animation to Move Rectangle With Arrow Keys

I'm trying to move a rectangle in a canvas element, and haven't had any luck. This is my code so far. I want to do it in PURE JavaScript, not jQuery or any other library.
My JavaScript:
window.onload = beginningMovement; // load beginning movement
function beginningMovement() {
var elem = document.getElementById("rectangle");
var pos = 0;
var id = setInterval(frame, 8);
function frame() {
if (pos == 203) {
clearInterval(id);
//Color funcs
setTimeout(black, 0);
setTimeout(lightgray, 500);
setTimeout(black, 1000);
setTimeout(lightgray, 1500);
setTimeout(black, 2000);
setTimeout(lightgray, 2500);
function black() {
var color = document.getElementById('container').style.backgroundColor = "black";
}
function lightgray() {
var color = document.getElementById('container').style.backgroundColor = "lightgray";
}
//End of color funcs
} else {
pos++;
elem.style.top = pos + 'px';
elem.style.middle = pos + 'px';
}
}
}
//Arrow switching
var X = 40;
var Y = 20;
function switchKey(event) {
Key = event.keyCode;
myCanvas.fillstyle = "white";
myCanvas.filRect(X, Y, 50, 50);
}
switch(key) {
case 37: X -=5;
break;
case 37: Y -=5;
break;
case 37: X +=5;
break;
case 37: Y +=5;
}
myCanvas.fillstyle = "blue";
myCanvas.filRect(X, Y, 50, 50);
HTML:
<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
#container {
width: 450px;
height: 400px;
border: 5px solid black;
background: lightgray;
}
#rectangle {
height: 50px;
width: 150px;
background: cyan;
margin-left: 150px;
margin-top: 160px;
position: absolute;
}
</style>
</head>
<body onkeyup="switchKey(event)">
<div id="container">
<div id="rectangle">
</div>
</div>
</body>
</html>
I've been at this for hours and haven't had any luck. I would appreciate it if someone could help me, and get this done soon.
There were a lot of issues with you code and I eventually thought it would be easier to remake a simple version for you to look at. If you really want to stick with your version, please check any browser console for errors and you'll see the issues I'm seeing. Some functions aren't yet available onload, there is no key variable, yet there is a Key variable. There were other issues, too, regarding variable and function scope.
Here's a new version for you to look at: http://codepen.io/antibland/pen/ONwEBE
It's not my finest work, but it's a step in the right direction for you. Instead of setInterval, you should be using requestAnimationFrame to do the redraw. It's much more performant (more on that here if you're interested).
In my demo, a real <canvas> element is used. The smaller rectangle is added to it. I figured you intended to use the real canvas since you included a myCanvas variable in your code. If not, apologies. Either way, you'll probably want to add bounds checking in there, to keep the small rectangle from moving beyond the walls.
Good luck!

Categories