Using JavaScript Animation to Move Rectangle With Arrow Keys - javascript

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!

Related

Javascript/CSS: How to start animation from cursor position

I've already asked this question but it did not solve my problem (JavaScript / CSS - How can I start an animation, creating new Divs from cursor position?).
I've found a solution but it doesn't seem to work properly on Mozilla and Opera. Also, when I click multiple times, the div starts flashing, which is not what I want. I need to have more than one div at the same time, so to have multiple animations simultaneously. Here's an example from an existing game: http://www.cram.com/flashcards/games/stellar-speller/gre-hit-parade-group-1-320949 Please don't use jQuery, just normal Javascript. Thank you!
<!DOCTYPE html>
<html>
<head>
<style>
#table{
height:300px;
width:900px;
background:red;
}
#ball {
width: 25px;
height: 25px;
position: absolute;
background-color: white;
border-radius:50px;
display:none;
z-index:11;
}
</style>
<script> function animation(){ var elem =
document.getElementById("ball");
document.getElementById("ball").style.display ='block';
document.getElementById("ball").disabled = true;
var x = event.clientX;
var y = event.clientY;
var id = setInterval(frame, 2);
function frame() {
if (x == 900) {
clearInterval(id);
}
else {
x++;
elem.style.top = y + 'px';
elem.style.left = x + 'px';
}
}
}
</script>
</head>
<body>
<div id="table" onclick="animation()">
<div id="ball"></div>
</body>
</html>
few issues in your code. First you have to clone or create a new ball each time you click (be aware that cloning an element won't copy attached events). Don't mix HTML and Javascript and use addEventListener, which let you have event as argument
document.getElementById('table').addEventListener("click",animation);
function animation(event){
var ball = document.getElementById("ball");
//clone element or create another one (you should set a class in you css)
var elem = ball.cloneNode(true);
document.getElementById("table").appendChild(elem);
elem.style.display ='block';
// document.getElementById("ball").disabled = true;
var x = event.clientX;
var y = event.clientY;
var id = setInterval(frame, 2);
function frame() {
if (x == 900) {
clearInterval(id);
}
else
{
x++;
elem.style.top = y + 'px';
elem.style.left = x + 'px';
}
}
}
#table{
height:300px;
width:900px;
background:red;
}
#ball {
width: 25px;
height: 25px;
position: absolute;
background-color: white;
border-radius:50px;
display:none;
z-index:11;
}
<div id="table">
<div id="ball"></div>
</div>
You're reusing the same #ball element for every animation, it can't be in two places at once. To create a new element each time, use document.createElement. Then you'll have to place that element somewhere with appendChild, and remove it with removeChild when the animation's finished.
And some smaller things:
If you will have more than one ball in the document, use a class instead of an ID - IDs are only supposed to be used once.
Your <div>s aren't closed with </div> in the HTML, which is probably Firefox's problem. Do people still use Opera?
You should use requestAnimationFrame here instead of setInterval.
And you should try to use addEventListener instead of onclick.
Good luck!

Transition a circle from one point to another given x, y position with a pause at every point

I have code JSFiddle to transition a circle from point A to point B. But, how do I modify code to make it work if the 'move' method is called like below and also circle has to pause for a second at every point. Please help.
myBall.move(50,300).move(150,400).move(100,200).move(130,230);
After a bit of playing around I think I've managed to come up with what you were looking for, this creates a queue of move events which is pushed to each time move is called, this sequence of events is then run in order by the run function (note that I've added a .move(0,0) at the beginning, something strange happens running this in an SO snippet, this also adds a brief delay on SO, but it seems to work fine on JSFiddle without it):
function ball() {
const elem = document.getElementById("ball");
var q = [];
var running = false;
var me = this;
this.move = function(x, y) {
q.push([x, y]);
if (!running) {
running = true;
me.run();
}
return this;
}
this.run = function() {
if (q.length == 0) {
running = false;
} else {
var pos = q.shift();
elem.style.transform = `translate(${pos[0]}px, ${pos[1]}px)`;
setTimeout(me.run, 2000);
}
}
}
let myBall = new ball();
myBall.move(0, 0).move(50, 300).move(150, 400).move(100, 200).move(130, 230);
#ball {
width: 100px;
height: 100px;
border: 1px solid black;
border-radius: 50%;
transition: transform 2s;
}
<div id="ball">
</div>

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);

Making a 'div' go in a circle

I am working on a bit of code to have a dot circle around your cursor on a webpage, but I am having trouble getting the 'div' to follow the path I want; in fact, the object is not moving at all and I cannot figure out why my code does not work. Here is the code that is causing me trouble from what I've narrowed down:
<!DOCTYPE HTML>
<head>
<title>TEST SPACE</title>
<script src="jquery-1.10.2.min.js"></script>
</head>
<body>
<div id="test"></div>
<style>
#test {
background-color: black;
height: 10px;
width: 10px;
border-radius: 100%;
position: absolute;
top: 50%;
left: 50%;
}
</style>
<script>
const omega = Math.PI / 2000;
function dotRotation() {
var time = 0;
var x = 20*(Math.sin(omega*time));
var y = 20*(Math.cos(omega*time));
document.getElementById("test").style.marginLeft = x;
document.getElementById("test").style.marginTop = y;
time += 25;
};
$(document).ready(function() {
setInterval('dotRotation()',25);
});
</script>
</body>
JSFiddle
Two things are wrong
You need to move your time variable outside of the function
You need to give a unit to the value you pass to the margins so add +'px' after the variables .marginTop = y + 'px';
So altogether
const omega = Math.PI / 2000;
var time = 0;
function dotRotation() {
var x = 20*(Math.sin(omega*time));
var y = 20*(Math.cos(omega*time));
var style = document.getElementById("test").style;
style.marginLeft = x +'px';
style.marginTop = y +'px';
time += 25;
};
Demo at http://jsfiddle.net/mWC63/
Also you can cache references to the dom to avoid the searching
Your fiddle is set to run onload, it should be set up to run in the head. [drop down on left under jQuery selection.]
time is declared inside of the function so it is reset back to zero every single time it is called. Move it outside of dotRotation
var time = 0;
function dotRotation() {
var x = 20*(Math.sin(omega*time));
var y = 20*(Math.cos(omega*time));
$("#test").css({"marginLeft" : x + "px", "marginTop" : y + "px"});
time += 25;
};
$(function() {
setInterval(dotRotation,25);
});

How to compare positions of two elements in javascript

I have been trying to make this work since the beginning of this week but couldn't figure it out. I have two elements in my HTML file. They are on the same vertical lane, element1 is moving 60ems to the left horizontally with each button click. I have to compare the positions of these two elements and detect whether element1 has passed the element2 with an if/else statement. When it passes I want to move the element1 to its initial position and start over. But if statement never shoots, it always jumps to else statement.
I have tried comparing following properties:
$('#elemet1').position();
$('#elemet1').position().left;
$('#elemet1').offset();
$('#elemet1').offsetLeft;
$('#elemet1').css("position");
$('#elemet1').css("left");
$('#elemet1').css("margin");
$('#elemet1').left;
I tried to compare the positions like below:
$(function () {
$("button").click(function () {
var position1 = $('#element1').css("left");
var position2 = $('#element2').css("left");
if (position1 <= position2) {
$("#element1").animate({left:'+=240em'}, 600);
}
else {
$("#element1").animate({left:'-=60em'}, 600);
}
});
});
If you can give me an answer or direct me to another post I will appreciate it. Thank you in advance.
EDIT: The style I use is below:
.element2 {
position: relative;
width: 60em;
height: 40em;
bottom: 8em;
background: rgba(242, 210, 139, 0.6);
border-radius: 1.2em;
z-index: 1;
overflow: hidden;
#element1 {
position: absolute;
margin-left: 180em;
width: 60em;
height: 40em;
z-index: 1;
}
And I should have mentioned this at the beginning: element1 is inside element2:
<div class="element2">
<img id="element1" src="image/bg1.png" />
</div>
This will give you the current position of an element:
$('#element').position().left;
If you need position relative to the document (instead of relative to a parent element) you can use:
$('#element').offset().left;
You should just be able to compare the return values of these for the different elements directly. Here's some sample code that works for me, note there is no need to parse since they always return pixel values.
var pos = Math.max($(w).scrollTop(), 38),
top = $(ballon).position().top,
dist = Math.abs(pos-top),
time = dist > 1000 ? 2000 : dist / 0.15;
if (pos + $(w).height() >= pHeight) {
pos = pHeight - bHeight - gHeight;
$(ballon).animate({'top': pos}, time, 'easeInOutSine');
}
else if (dist > 150 || pos < 100) {
$(ballon).animate({'top': pos}, time, 'easeInOutBack');
}

Categories