"parseInt from form" and "clearing canvas on start()" - javascript

Greeting Everyone,
I already asked for some help with this assignment but the help I got was rather fruitless..
hope this time some1 would be to assist me :( ..
I have to draw on an id'd canvas everytime i click on a button,
however after some modification I get the result on my screen but I lost some functionalties,
parsing integer wont work since I get an error:
Uncaught ReferenceError: pGame is not defined
Although it is identified and it used to work at an early stage.
another issue is clearing the canvas everytime I click start:
function start()
{
//tried making a counter, if its the first time to click
//start then do nothing else restore
// context.restore();
if (shouldClear==0) {
setInterval(rotateShape, 30);
var degrees = 0.0;
shouldClear = 1;
}
else{
rotateShape();
shouldClear-1;
}
}
For reference pursposes here is my full code:
<!DOCTYPE HTML>
<html>
<head><title>Rectangles</title></head>
<body>
<script>
var i = 0;
var rectArrayStartX,rectArrayStartY,rectArrayDimY, rectArrayDimX;
var RotatingRectangle = function(x, y, width, height, rot, r,g,b){
var rotation = rot;
var rotationState = 0;
this.draw = function(ctx){
rotationState += rotation;
ctx.save();
ctx.translate(x+(width/2), y+(height/2));
ctx.rotate(rotationState);
var randomRed = Math.floor( Math.random() * 256 );
var randomGreen = Math.floor( Math.random() * 256 );
var randomBlue = Math.floor( Math.random() * 256 );
ctx.fillStyle = "rgb(" + randomRed + ", " + randomGreen + ", " + randomBlue +")";
ctx.fillRect(0-(width/2), 0-(height/2), width, height);
ctx.restore();
}
}
var shouldClear = 0;
function start()
{
//tried making a counter, if its the first time to click
//start then do nothing else restore
// context.restore();
if (shouldClear==0) {
setInterval(rotateShape, 30);
var degrees = 0.0;
shouldClear = 1;
}
else{
rotateShape();
shouldClear-1;
}
}
function construct()
{
var count = 25;
var count = parseInt(pGame.box.value);
var allShapes = [];
for (i=0; i < count; ++i) {
var rotation = Math.random()*.10
var x = Math.floor(Math.random() * 640);
var y = Math.floor(Math.random() * 480);
var randomRed = Math.floor( Math.random() * 256 );
var randomGreen = Math.floor( Math.random() * 256 );
var randomBlue = Math.floor( Math.random() * 256 );
var rect = new RotatingRectangle(x, y, 50, 50, rotation, "rgb(" + randomRed + ", " + randomGreen + ", " + randomBlue +")");
allShapes.push(rect);
}
return allShapes;
}
var allShapes = construct();
function rotateShape()
{
var canvas = document.getElementById('gameId');
if (canvas.getContext) {
var ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, 640, 480);
for (i=0; i < allShapes.length; ++i) {
allShapes[i].draw(ctx);
}
if (shouldClear==1) {
var ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, 640, 480);
for (i=0; i < allShapes.length; ++i) {
allShapes[i].draw(ctx);
}
}
}
}
</script>
<div id="rectangles" STYLE = "background-color: #fff68f; width: 600px; height: 420px;
border-style: outset;position: absolute;">
<form name="pGame">
<center>
<b>Canvas Application</b><br>
<input type= "button" value= "Start" onclick= "start()" />
<input id="box" type="text" size="2" value="10" style="border-style:inset;
color:red; background-color: black" />
</center>
</form>
<canvas id="gameId" width="598" height="300"
STYLE = "border:1px solid; background-color: #fff68f; position: absolute;">
</canvas>
</div>
</body>
</html>

The form pGame hasn't been created when you try to access it.
Place your script under the form so that the form will be created before the script is executed or call your script when the DOMContentLoaded event triggers.

Related

Change canvas size on an html page using javascript

The following question is based on an adaption I wish to make of this codepen:
Here is a Pen
I have the following html for displaying the canvas (I want it to be only in a section on the html page and not take up the whole page)
<div class="container">
<canvas id="c"></canvas>
</div>
The javascript for the canvas which shows an animation is below.
<script>
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
var H = window.innerHeight;
var W = window.innerWidth;
canvas.height = H;
canvas.width = W;
var NBR_PARTICLES = 100;
var INTENSITY = 55;
var BLUE_RATIO = 5;
particles = [];
for (var i = 0; i < NBR_PARTICLES; i++) {
particles.push( new particle(i) );
};
function particle(i){
this.size = rand(0, 1.4);
this.x = W / 2;
this.y = H / 2;
this.vx = rand(-1, 1);
this.vy = rand(-1, 1);
this.decay = rand(0.9, 1);
this.c = 0;
}
function draw(){
for (var i = 0; i < NBR_PARTICLES; i++) {
p = particles[i];
ctx.fillStyle = color(p.size);
ctx.beginPath();
ctx.arc(p.x, p.y, p.size, Math.PI*2, false);
ctx.fill();
p.size *= p.decay;
p.x += p.vx;
p.y += p.vy;
p.vx += rand(-.2, .2);
p.vy += rand(-.2, .2);
p.c++;
if(p.size < .2){
particles[i] = new particle(i);
}
};
}
function color(i){
value = 255 - Math.round( (i * (255 / NBR_PARTICLES)) * INTENSITY);
return "rgba(" + value + ", 0, " + Math.round((NBR_PARTICLES - i) / BLUE_RATIO) + ", .75)";
}
setInterval(draw, 33);
/*************************
CONSTRUCT FUNCTIONS
**************************/
function rand(min, max){
value = min + Math.random() * ( max - min );
return value;
}
function cd(args){ // FOR DEBUG
console.dir(args);
}
</script>
I want the canvas size to be a rectangular banner across the page rather than the whole page as it is now.
I have tried changing these variables
var H = window.innerHeight;
var W = window.innerWidth;
canvas.height = H;
canvas.width = W;
to
canvas.height = 200;
canvas.width = 800;
but that doesn't render the animation at all but does appear to resize the canvas.
The CSS here appears to override the existing body as the whole animation takes over the page and my existing content is no longer displayed.
body, html{
margin: 0;
padding: 0;
overflow: hidden;
background-color: #ddd;
}
I tried removing the body from the css but that didn't work at all.
I also, as you can see above, added a div container, hoping that would isolate the canvas but that hasn't worked either.
<div class="container">
<canvas id="c"></canvas>
</div>
How do I adapt this code to make the canvas only render on a portion (width and height of the canvas decided by me) on the screen.
Setting directly the height H and width W , will show canvas correctly at center :
below snippet you can see result centred annilation correctly
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
// set here canvas width and height directly
var H = 200;
var W = 200;
canvas.height = H;
canvas.width = W;
var NBR_PARTICLES = 100;
var INTENSITY = 55;
var BLUE_RATIO = 5;
particles = [];
for (var i = 0; i < NBR_PARTICLES; i++) {
particles.push( new particle(i) );
};
function particle(i){
this.size = rand(0, 1.4);
this.x = W / 2;
this.y = H / 2;
this.vx = rand(-1, 1);
this.vy = rand(-1, 1);
this.decay = rand(0.9, 1);
this.c = 0;
}
function draw(){
for (var i = 0; i < NBR_PARTICLES; i++) {
p = particles[i];
ctx.fillStyle = color(p.size);
ctx.beginPath();
ctx.arc(p.x, p.y, p.size, Math.PI*2, false);
ctx.fill();
p.size *= p.decay;
p.x += p.vx;
p.y += p.vy;
p.vx += rand(-.2, .2);
p.vy += rand(-.2, .2);
p.c++;
if(p.size < .2){
particles[i] = new particle(i);
}
};
}
function color(i){
value = 255 - Math.round( (i * (255 / NBR_PARTICLES)) * INTENSITY);
return "rgba(" + value + ", 0, " + Math.round((NBR_PARTICLES - i) / BLUE_RATIO) + ", .75)";
}
setInterval(draw, 33);
/*************************
CONSTRUCT FUNCTIONS
**************************/
function rand(min, max){
value = min + Math.random() * ( max - min );
return value;
}
function cd(args){ // FOR DEBUG
console.dir(args);
}
body, html{
margin: 0;
padding: 0;
overflow: hidden;
background-color: #ddd;
text-align:center
}
canvas {
border : 1px solid gray;
}
<canvas id="c"></canvas>

Code crashes because object's .rad property becomes undefined

I am creating an ecosystem with my code consisting of plants, herbivores, and carnivores being represented through circles. For some reason, my code has been crashing after a certain amount of time ranging from 30 seconds to 8 minutes but no more than that.
After doing some digging I have found out that the crash is a result of my object's .rad property becoming undefined for some reason. It's probably a result of me improperly setting up my functions but I haven't been able to find a solution.
var plantSpawn = 5;
var herbSpawn = 3;
var carnSpawn = 2;
var myPlants = new Array();
var myCarns = new Array();
var myHerbs = new Array();
//////////////PLANTS//////////////////
function createPlants() {
reproducePlants();
setInterval(reproducePlants, 5000);
}
function reproducePlants() {
for(var p=0; p<plantSpawn; p++){
var rr = Math.round(Math.random() * 150);
var gg = Math.round(Math.random() * 255);
var bb = Math.round(Math.random() * 150);
var plant = new Object();
plant.x = Math.random() * canvas.width;
plant.y = Math.random() * canvas.height;
plant.rad = 2 + Math.random()*2;
plant.skin = 'rgba('+rr+','+gg+','+bb+', 1)';
myPlants.push(plant);
}
}
function drawPlants(){
var plantAmt = myPlants.length;
for(var j=0; j<plantAmt; j++) {
if (myPlants[j].x + myPlants[j].rad >= canvas.width) {
myPlants[j].x -= 10;
}
if (myPlants[j].y + myPlants[j].rad >= canvas.height) {
myPlants[j].y -= 10;
}
context.beginPath();
context.arc(myPlants[j].x, myPlants[j].y, myPlants[j].rad, 0, Math.PI*2, false);
context.closePath();
context.fillStyle = myPlants[j].skin;
context.fill();
}
}
function killPlants() {
plantDeath();
setInterval(plantDeath, 30000); //play with inc
}
function plantDeath() {
myPlants.splice(0,5);
}
//////////////HERBS//////////////////
function herbsLife(){
reproduceHerbs();
setInterval(reproduceHerbs, 10000);
herbsDeath();
setInterval(herbsDeath, 90000); //1.5 minutes
setInterval(herbsStarve, 10000); //10 seconds
}
function reproduceHerbs() {
for (var h=0; h<herbSpawn; h++){
var gg = Math.round(Math.random() * 100);
var bb = Math.round(Math.random() * 255);
var herbivore = new Object();
herbivore.x = Math.random() * canvas.width;
herbivore.y = Math.random() * canvas.height;
herbivore.rad = 5 + Math.random()*3;
herbivore.skin = 'rgba(0,'+gg+','+bb+', 1)';
herbivore.speedH = -3 + Math.random()*1.2;
herbivore.speedV = -3 + Math.random()*1.2;
herbivore.dirH = 1;
herbivore.dirV = 1;
myHerbs.push(herbivore);
}
}
function drawHerbs() {
var herbAmt = myHerbs.length;
for(var j=0; j<herbAmt; j++) {
var hX = myHerbs[j].x;
var hY = myHerbs[j].y;
//HERB MOVEMENT//
myHerbs[j].x += myHerbs[j].dirH * myHerbs[j].speedH;
if (myHerbs[j].x > canvas.width + myHerbs[j].rad || myHerbs[j].x < 0){
myHerbs[j].dirH *= -1;
}
myHerbs[j].y += myHerbs[j].dirV * myHerbs[j].speedV;
if (myHerbs[j].y > canvas.height + myHerbs[j].rad || myHerbs[j].y < 0){
myHerbs[j].dirV *= -1;
}
context.beginPath();
context.arc(myHerbs[j].x, myHerbs[j].y, myHerbs[j].rad, 0, Math.PI*2, false);
context.closePath();
context.fillStyle = myHerbs[j].skin;
context.fill();
}
}
function herbsDeath() {
myHerbs.splice(0,3);
}
function herbsEat() {
for (var k=0; k<myPlants.length; k++){
var pX = myPlants[k].x;
var pY = myPlants[k].y;
for (var h=0; h<myHerbs.length; h++){
var hX = myHerbs[h].x;
var hY = myHerbs[h].y;
var eX = hX - pX;
var eY = hY - pY;
var dist = Math.sqrt(Math.pow(eX,2) + Math.pow(eY,2));
if (dist < myPlants[k].rad*2) {
myPlants.splice(k,1);
myHerbs[h].rad += 1;
}
}
}
}
function herbsStarve() {
for (var s=0; s<myPlants.length; s++){
myHerbs[s].rad -= 1;
if (myHerbs[s].rad <= 2) {
myHerbs.splice(s,1);
}
}
}
//////////////CARNS//////////////////
function carnsLife() {
reproduceCarns();
setInterval(reproduceCarns, 20000); //20 seconds
carnsDeath();
setInterval(carnsDeath, 60000); //50 seconds
setInterval(carnsStarve, 7500); //10 seconds
}
function reproduceCarns() {
for (var c=0; c<carnSpawn; c++){
var rr = Math.round(Math.random() * 255);
var gg = Math.round(Math.random() * 100);
var carnivore = new Object();
carnivore.x = Math.random() * canvas.width;
carnivore.y = Math.random() * canvas.height;
carnivore.rad = 7 + Math.random()*3;
carnivore.skin = 'rgba('+rr+','+gg+',0, 1)';
//bigger random = slower//
carnivore.speedH = -3 + Math.random()*2;
carnivore.speedV = -3 + Math.random()*2;
carnivore.dirH = 1;
carnivore.dirV = 1;
myCarns.push(carnivore);
}
}
function drawCarns() {
var carnAmt = myCarns.length;
for(var j=0; j<carnAmt; j++) {
//CARN MOVEMENT//
myCarns[j].x += myCarns[j].dirH * myCarns[j].speedH;
if (myCarns[j].x > canvas.width + myCarns[j].rad || myCarns[j].x < 0){
myCarns[j].dirH *= -1;
}
myCarns[j].y += myCarns[j].dirV * myCarns[j].speedV;
if (myCarns[j].y > canvas.height + myCarns[j].rad || myCarns[j].y < 0){
myCarns[j].dirV *= -1;
}
context.beginPath();
context.arc(myCarns[j].x, myCarns[j].y, myCarns[j].rad, 0, Math.PI*2, false);
context.closePath();
context.fillStyle = myCarns[j].skin;
context.fill();
}
}
function carnsDeath() {
myCarns.splice(0,2);
}
function carnsEat() {
for (var k=0; k<myCarns.length; k++){
var cX = myCarns[k].x;
var cY = myCarns[k].y;
for (var h=0; h<myHerbs.length; h++){
var hX = myHerbs[h].x;
var hY = myHerbs[h].y;
var eX = cX - hX;
var eY = cY - hY;
var dist = Math.sqrt(Math.pow(eX,2) + Math.pow(eY,2));
if (dist < myCarns[k].rad*1.2 && myCarns[k].rad > myHerbs[h].rad) {
myHerbs.splice(h,1);
myCarns[k].rad += 1;
}
}
}
}
function carnsStarve() {
for (var q=0; q<myPlants.length; q++){
myCarns[q].rad = myCarns[q].rad - 1;
if (myCarns[q].rad <= 5) {
myCarns.splice(q,1);
}
}
}
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title> Ecosystem </title>
<!-- import external .js scripts here -->
<script type="text/javascript" src="Creatures.js" ></script>
<!-- modify CSS properties here -->
<style type="text/css">
body,td,th {
font-family: Monaco, "Courier New", "monospace";
font-size: 14px;
color: rgba(255,255,255,1);
}
body {
background-color: rgba(0,0,0,1);
}
#container {
position: relative;
text-align: left;
width: 95%;
height: 800px;
}
#fmxCanvas {
position: relative;
background-color:rgba(255,255,255,1);
border: rgba(255,255,255,1) thin dashed;
cursor: crosshair;
display: inline-block;
}
</style>
</head>
<body>
<div id="container">
<!-- START HTML CODE HERE -->
<canvas id="fmxCanvas" width="800" height="800"></canvas>
<div id="display"></div>
<!-- FINISH HTML CODE HERE -->
</div>
<script>
///////////////////////////////////////////////////////////////////////
// DECLARE requestAnimFrame
var rAF = window.requestAnimFrame ||
window.mozRequestAnimFrame ||
window.webkitRequestAnimFrame ||
window.msRequestAnimFrame;
var fps = 30;
window.requestAnimFrame = (
function(callback) {
return rAF ||
function(callback) {
window.setTimeout(callback, 1000 / fps);
};
})();
///////////////////////////////////////////////////////////////////////
// DEFINE GLOBAL VARIABLES HERE
var canvas;
var context;
canvas = document.getElementById("fmxCanvas");
context = canvas.getContext("2d");
var canvas1;
var context1;
canvas1 = document.createElement("canvas");
context1 = canvas1.getContext("2d");
canvas1.width = canvas.width;
canvas1.height = canvas.height;
var display;
display = document.getElementById('display');
var counter;
///////////////////////////////////////////////////////////////////////
// DEFINE YOUR GLOBAL VARIABLES HERE
///////////////////////////////////////////////////////////////////////
// CALL THE EVENT LISTENERS
window.addEventListener("load", setup, false);
//////////////////////////////////////////////////////////////////////
// ADD EVENT LISTENERS
canvas.addEventListener("mousemove", mousePos, false);
//////////////////////////////////////////////////////////////////////
// MOUSE COORDINATES
var stage, mouseX, mouseY;
function mousePos(event) {
stage = canvas.getBoundingClientRect();
mouseX = event.clientX - stage.left;
mouseY = event.clientY - stage.top;
}
/////////////////////////////////////////////////////////////////////
// INITIALIZE THE STARTING FUNCTION
function setup() {
/////////////////////////////////////////////////////////////////////
// DECLARE STARTING VALUES OF GLOBAL VARIABLES
counter = 0;
mouseX = canvas.width/2;
mouseY = canvas.height/2;
/////////////////////////////////////////////////////////////////////
// CALL SUBSEQUENT FUNCTIONS, as many as you need
createPlants();
killPlants();
herbsLife();
carnsLife();
clear(); // COVER TRANSPARENT CANVAS OR CLEAR CANVAS
draw(); // THIS IS WHERE EVERYTHING HAPPENS
}
////////////////////////////////////////////////////////////////////
// CLEAR THE CANVAS FOR ANIMATION
// USE THIS AREA TO MODIFY BKGD
function clear() {
context.clearRect(0,0,canvas.width, canvas.height);
context1.clearRect(0,0,canvas.width, canvas.height);
// clear additional contexts here if you have more than canvas1
}
////////////////////////////////////////////////////////////////////
// THIS IS WHERE EVERYTHING HAPPENS
function draw() {
counter += 0.1; // EASIER FOR SINE COSINE FUNCTIONS
//if (counter > Math.PI*200) { counter = 0; } // RESET COUNTER
clear(); // USE THIS TO REFRESH THE FRAME AND CLEAR CANVAS
////////////////////////////////////////////////////////////////////
// >>>START HERE>>>START HERE>>>START HERE>>>START HERE>>>START HERE
drawPlants();
drawHerbs();
drawCarns();
herbsEat();
carnsEat();
// <<<END HERE<<<END HERE<<<END HERE<<<END HERE<<<END HERE<<<END HERE
///////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////
// HTML DISPLAY FIELD FOR TESTING PURPOSES
display.innerHTML =
// mouseX + " || " + mouseY +
" || Minutes = " + Math.trunc(counter/180) +
" || Seconds = " + Math.round(counter/3) +
"<br><br>" +
"Plants = " + myPlants.length +
"<br>" +
"Herbivores = " + myHerbs.length +
"<br>" +
"Carnivores = " + myCarns.length;
/////////////////////////////////////////////////////////////////
// LAST LINE CREATES THE ANIMATION
requestAnimFrame(draw); // CALLS draw() every nth of a second
}
</script>
</body>
</html>

Creating rain using canvas. I can create an individual droplet that falls or random drops across the top but I how do I combine these two effects?

I am trying to create a rain effect using canvas. Within the code I have added comments "POINT 1", "POINT 2" and "POINT 3" to help you understand what part I'm talking about.
"POINT 1" creates multiple droplets with a random x-axis and a y-axis of 0.
"POINT 3" (commented out) creates a single droplet which correctly increases the y-axis so that the droplet falls.
I need "POINT 3" to be applied to every droplet that is create in "POINT 1". "POINT 2" is part of my attempt to do this but instead it creates a new droplet that is lower rather than lowering the droplet that was previously created.
Any help is very much appreciated,
Steve.
I have create a JS Fiddle for this here: https://jsfiddle.net/xrainbowuk/qaws59uz/10/
/* ///// ///// ///// ///// */
var canvas = document.querySelector("canvas");
var c = canvas.getContext("2d");
var canvasWidth = window.innerWidth;
var canvasHeight = window.innerHeight;
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
//RAIN DROP CONSTRUCTOR FUNCTION
function Rain(rainDropStandardX, rainDropStandardY, opacity) {
this.rainDropStandardX = rainDropStandardX;
this.rainDropStandardY = rainDropStandardY;
this.opacity = opacity;
var dropTipX = rainDropStandardX + 0;
var dropTipY = rainDropStandardY + 0;
var dropBottomLeftX = rainDropStandardX - 15;
var dropBottomLeftY = rainDropStandardY + 40;
var dropBottomRightX = rainDropStandardX + 15;
var dropBottomRightY = rainDropStandardY + 40;
this.droplet = function() {
c.beginPath();
c.moveTo(dropTipX, dropTipY); // line on the right
c.bezierCurveTo(dropBottomLeftX, dropBottomLeftY, dropBottomRightX, dropBottomRightY, dropTipX, dropTipY);
c.fillStyle = "rgba(43, 173, 255, " + this.opacity + ")";
c.fill();
}
}
/* POINT 1 - This piece of code produces multiple droplets but their "y-axis" value never increases */
var rngPosY = 0;
setInterval(function() {
var rngPosX = Math.random() * canvasWidth;
var rngOpacity = Math.random() * (1 - 0.1) + 0.1;
var rainDrop = new Rain(rngPosX, rngPosY, rngOpacity);
rainDrop.droplet();
//rngPosY += 10; /* POINT 2 - This will make the next droplet lower (increase y-axis). Not lower the individual droplets */
}, 500);
/* POINT 3 - A single droplet is created and then the "y-axis" value increases */
/*
var rngPosY = 0;
var rngPosX = Math.random() * canvasWidth;
var rngOpacity = Math.random() * (1 - 0.1) + 0.1;
setInterval(function() {
c.clearRect(0, 0, canvasWidth, canvasHeight);
var rainDrop = new Rain(rngPosX, rngPosY, rngOpacity);
rainDrop.droplet();
rngPosY += 5;
}, 1);
*/
* {
box-sizing: border-box;
margin: 0px;
padding: 0px;
}
body {
height: 100%;
width: 100%;
}
canvas {
background-color: #000;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Canvas Rain</title>
<link href="css/RG5.css" rel="stylesheet" type="text/css">
</head>
<body>
<canvas>
Your browser does not support HTML canvas.
</canvas>
<script src="js/RG5.js"></script>
</body>
</html>
You will need an array where to save your drops. In my code this array is: var rain. Also you will need a method to update every drop.
Another important think is a way to remove drops from the array if the y position is > canvasHeight.
if (d.rainDropStandardY > canvasHeight) {
rain.splice(i, 1);
}
var canvas = document.querySelector("canvas");
var c = canvas.getContext("2d");
var canvasWidth = (canvas.width = window.innerWidth);
var canvasHeight = (canvas.height = window.innerHeight);
// an array where to save the drops of rain
var rain = [];
//RAIN DROP CONSTRUCTOR FUNCTION
function Rain(rainDropStandardX, rainDropStandardY, opacity) {
this.rainDropStandardX = rainDropStandardX;
this.rainDropStandardY = rainDropStandardY;
this.opacity = opacity;
// the speed of the drop: a different one for every drop
this.v = {
x: .5 + Math.random(),
y: .5 + Math.random() * 10
};
//console.log(this.v)
this.droplet = function() {
var dropTipX = this.rainDropStandardX + 0;
var dropTipY = this.rainDropStandardY + 0;
var dropBottomLeftX = this.rainDropStandardX - 15;
var dropBottomLeftY = this.rainDropStandardY + 40;
var dropBottomRightX = this.rainDropStandardX + 15;
var dropBottomRightY = this.rainDropStandardY + 40;
c.beginPath();
c.moveTo(dropTipX, dropTipY); // line on the right
c.bezierCurveTo(
dropBottomLeftX,
dropBottomLeftY,
dropBottomRightX,
dropBottomRightY,
dropTipX,
dropTipY
);
c.fillStyle = "rgba(43, 173, 255, " + this.opacity + ")";
c.fill();
};
// a method to update the position of the drop
this.update = function() {
this.rainDropStandardX += this.v.x;
this.rainDropStandardY += this.v.y;
this.droplet();
};
}
/* This piece of code produces multiple droplets but their "y-axis" value never increases */
var rngPosY = 0;
setInterval(function() {
var rngPosX = Math.random() * canvasWidth;
var rngOpacity = Math.random() * (1 - 0.1) + 0.1;
// you create a new drop and push it in the array
rain.push(new Rain(rngPosX, rngPosY, rngOpacity));
//rngPosY += 10; /*This will make the next droplet lower (increase y-axis). Not lower the individual droplets */
}, 500);
function frame() {
window.requestAnimationFrame(frame);
c.clearRect(0, 0, canvasWidth, canvasHeight);
// for every drop in the array
rain.forEach((d, i) => {
//you update the position and redraw the drop
d.update();
// if the trop is out of the canvas you remove the drop from the array
if (d.rainDropStandardY > canvasHeight) {
rain.splice(i, 1);
}
});
}
frame();
* {
box-sizing: border-box;
margin: 0px;
padding: 0px;
}
body {
height: 100%;
width: 100%;
}
canvas {
background-color: #000;
}
<canvas>Your browser does not support HTML canvas.
</canvas>
I hope this helps.

Having problems with making explosions on Canvas with javascript

I am new here and a student in an informatics degree program. I am having trouble with some parts of one of my projects due next week. We were asked to do a project that contained all of these requirements.
fullscreen and webapp enabled
touch and mouse events
appropriately use arrays and functions
use event locations (pageX & pageY) to impact the x and y behavior of your canvas elements
must continually generate visuals -- no 'end of animation' permitted
So i chose to do some sort of fireworks show in which a certain amount of generated balls of different sizes were going to come in from the bottom of the canvas page and fly up towards around 1/3 from the top then they would get spliced out and an explosion would go on at the same time. While the circle would explode a new one would be generated at the bottom of the canvas and it would continue and so forth.
So i need help doing the explosion(creating tiny circles that shoot away from the center of the circle which disappear(exploded)) when they get to 1/3 of the top as well as adding mouse events / touch events to prematurely make the circles explode. Any help would be great thanks.
<html>
<head>
<meta name="apple-mobile-web-app-capable" content="yes"/>
<meta name="apple-mobile-web-app-status-bar-style" content="black"/>
<meta content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0' name='viewport' />
<title>basic_canvas</title>
<style>
#mycanvas {
margin: 0 auto;
background-color: black;
}
body {
margin: 0
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script>
//global variables
var mycanvas;
var ctx;
//make an array of balls shooting from the bottom of the page to the middle of the page
var Balls = [];
var fireworks = [];
//make a ready handler for our page to tirgger my javascript
$(document).ready(function () {
mycanvas = document.getElementById('mycanvas');
// mycanvas = $('#mycanvas');
ctx = mycanvas.getContext('2d');
mycanvas.width = window.innerWidth;
mycanvas.height = window.innerHeight;
setInterval(draw, 33);
//make the balls here
for (var i = 0; i < 30; i++) {
Balls[i] = new Ball(getRandomFloat(0, mycanvas.width), mycanvas.height, getRandomFloat(20, 70), getRandomFloat(0.1, 1));
}
// event listeners here
});
function draw() {
ctx.clearRect(0, 0, mycanvas.width, mycanvas.height);
for (var i = 0; i < Balls.length; i++) {
Balls[i].makeCirc();
Balls[i].moveCirc();
}
}
function degToRad(deg) {
radians = (deg * Math.PI / 180) - Math.PI / 2;
return radians;
}
function getRandomFloat(min, max) {
return Math.random() * (max - min) + min;
}
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
//make my flying balls here
//ball(x start value, y start value, radius, speed)
function Ball(xin, yin, radin, spin) {
//make all the variables for the Ball
var x = xin;
var y = yin;
var r = radin;
var sp = spin;
//generating random colors for the circles
var c = 'rgb(' +
getRandomInt(0, 255) +
',' +
getRandomInt(0, 255) +
',' +
getRandomInt(0, 255) +
')';
//draw the circle
this.makeCirc = function () {
ctx.fillStyle = c;
ctx.beginPath();
ctx.arc(x, y, r, 0, Math.PI * 2);
ctx.fill();
}
this.moveCirc = function () {
y -= sp;
if (y + r < mycanvas.height / 3) {
// fireworks[fireworks.length] = new Fireworks(x,y,2);
Balls.splice(Balls.indexOf(this), 1);
}
}
}
// function Firework(xin,yin,rin){
// var x = xin;
// var y = yin;
// var r = rin;
//
// }
</script>
</head>
<body>
<canvas id="mycanvas"></canvas>
</body>
</html>
So i was able to fix my project. Just in case someone else ever needs something similar i am posting the fixed code.
<html>
<head>
<meta name="apple-mobile-web-app-capable" content="yes"/>
<meta name="apple-mobile-web-app-status-bar-style" content="black"/>
<meta content='width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0' name='viewport' />
<title>Balloon_Fireworks</title>
<style>
#mycanvas {
margin: 0 auto;
background-color: black;
}
body {
margin: 0
}
#score_card {
position:absolute;
top:25px;
left:25px;
padding-top:25px;
padding-left:25px;
width:100px;
height:75px;
background-color: rgb(112,200,112);
color:rgba(50,50,50,0.5);
font-size:50px;
font-family: sans-serif;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script>
//global variables
var mycanvas;
var ctx;
//make an array of balls shooting from the bottom of the page to the middle of the page
var Balls = [];
var Fireworks = [];
//global keep track of where i click
var mouseX;
var mouseY;
//Counts the number of fireworks popped
var point_counter = 0;
//make a ready handler for our page to tirgger my javascript
$(document).ready(function () {
mycanvas = document.getElementById('mycanvas');
// mycanvas = $('#mycanvas');
ctx = mycanvas.getContext('2d');
mycanvas.width = window.innerWidth;
mycanvas.height = window.innerHeight;
mycanvas.addEventListener('mousedown', explodeThis);
mycanvas.addEventListener('touchstart', explodeThis);
setInterval(draw, 33);
//make the balls here
//new Ball( x, y, rad, speedx, speedy);
for (var i = 0; i < 30; i++) {
Balls[i] = new Ball(getRandomFloat(0, mycanvas.width), mycanvas.height, getRandomFloat(50, 70), getRandomFloat(-3, -1));
}
// event listeners here
});
function draw() {
ctx.clearRect(0, 0, mycanvas.width, mycanvas.height);
for (var i = 0; i < Balls.length; i++) {
Balls[i].makeCirc();
Balls[i].moveCirc();
}
for (var i = 0; i< Fireworks.length; i++){
Fireworks[i].drawFire();
Fireworks[i].moveFire();
}
}
function explodeThis(e){
e.preventDefault();
mouseX = e.pageX || e.targetTouches[0].pageX;
mouseY = e.pageY || e.targetTouches[0].pageY;
for (var i = 0; i< Balls.length; i++){
Balls[i].hit();
}
}
function degToRad(deg) {
radians = (deg * Math.PI / 180) - Math.PI / 2;
return radians;
}
function getRandomFloat(min, max) {
return Math.random() * (max - min) + min;
}
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
//make my flying balls here
//ball(x start value, y start value, radius, speed)
function Ball(xin, yin, radin, spyin, spxin, cin){
//make all the variables for the Ball
var x = xin;
var y = yin;
var r = radin;
var spy = spyin;
var spx = spxin || 0;
//make a gravity for me
var g = getRandomFloat(.0001,.05);
//generating random colors for the circles
var c = cin || 'rgb(' +
getRandomInt(0, 255) +
',' +
getRandomInt(0, 255) +
',' +
getRandomInt(0, 255) +
')';
//draw the circle
this.makeCirc = function () {
ctx.fillStyle = c;
ctx.beginPath();
ctx.arc(x,y,r,0,Math.PI * 2);
ctx.fill();
};
this.moveCirc = function () {
y += spy;
x += spx;
// At 1/3 from the top the balls will explode
if (y+r < mycanvas.height/3) {
}
};
this.gravityMe = function () {
spy += g;
};
this.hit = function () {
var d = Math.sqrt( (x-mouseX)*(x-mouseX) + (y-mouseY)*(y-mouseY) );
if (d < r){
//when it hits
spy = 0;
//make a new set of fireworks using the last place
Fireworks[Fireworks.length] = new Firework (x, y, r, c);
//access that last one you just made, and add in particles
Fireworks[Fireworks.length-1].makeFire();
c = 'rgba(255,255,255,0)';
r = 0;
point_counter ++;
// console.log(point_counter);
document.getElementById('score_card').innerHTML = point_counter;
//make a new one
Balls[Balls.length] = new Ball(getRandomFloat(0, mycanvas.width), mycanvas.height+70, getRandomFloat(50, 70), getRandomFloat(-5, -2));
}
};
}
// make the circles that explode out
//firework(x value, y value, radius)
function Firework(xin,yin,rin, cin){
var x = xin;
var y = yin;
var r = rin;
var color = cin;
//make an array
var particles = new Array(getRandomInt(10,30));
this.makeFire = function () {
for ( var i = 0; i < particles.length; i++){
particles[i] = new Ball(getRandomFloat(x-r,x+r), getRandomFloat(y-r, y+r), getRandomInt(2,10), getRandomFloat(-1,1), getRandomFloat(-3, 3), color);
}
};
this.drawFire = function () {
for ( var i = 0; i < particles.length; i++){
particles[i].makeCirc();
}
};
this.moveFire = function () {
for ( var i = 0; i < particles.length; i++){
particles[i].moveCirc();
particles[i].gravityMe();
}
};
}
</script>
</head>
<body>
<canvas id="mycanvas"></canvas>
<div id = "score_card"></div>
</body>
</html>

javascript svg animation

How would I write script that would move a shape in svg linearly with javascript. I want to use requestanimframe.
Here is an example using canvas. I just want to do the same thing except with svg.
The script obtains a context to the canvas then it uses javascript to draw a shape with the properties of the context. Then it manages the animation of the shape on the canvas in a linear motion. I just want to use svg for the shape instead of the canvas context properties.
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
#myCanvas {
border: 1px solid #9C9898;
}
</style>
<script>
window.requestAnimFrame = (function(callback){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback){
window.setTimeout(callback, 1000 / 60);
};
})();
function animate(lastTime, myRectangle){
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
// update
var date = new Date();
var time = date.getTime();
var timeDiff = time - lastTime;
var linearSpeed = 100; // pixels / second
var linearDistEachFrame = linearSpeed * timeDiff / 1000;
var currentX = myRectangle.x;
if (currentX < canvas.width - myRectangle.width - myRectangle.borderWidth / 2) {
var newX = currentX + linearDistEachFrame;
myRectangle.x = newX;
}
lastTime = time;
// clear
context.clearRect(0, 0, canvas.width, canvas.height);
// draw
context.beginPath();
context.rect(myRectangle.x, myRectangle.y, myRectangle.width, myRectangle.height);
context.fillStyle = "#8ED6FF";
context.fill();
context.lineWidth = myRectangle.borderWidth;
context.strokeStyle = "black";
context.stroke();
// request new frame
requestAnimFrame(function(){
animate(lastTime, myRectangle);
});
}
window.onload = function(){
var myRectangle = {
x: 0,
y: 50,
width: 100,
height: 50,
borderWidth: 5
};
var date = new Date();
var time = date.getTime();
animate(time, myRectangle);
};
</script>
</head>
<body onmousedown="return false;">
<canvas id="myCanvas" width="578" height="200">
</canvas>
</body>
Probably the easiest way to move an element in SVG with JavaScript is to modify the transform attribute of the element. This isn't the best method in terms of performance, but it is very readable and simple.
Most simply:
var el = document.getElementById( "mySVGElement" );
for( var i = 0; i < 100; i++ )
{
setTimeout( function( ) {
el.setAttribute( "transform", "translate( " + i + ", 0 )" );
}, 200 + i );
}
Or if you want a function to do it:
function translateElement( element, distance )
{
var x, y;
for( var i = 0; i < 100; i++ )
{
setTimeout( function( ) {
x = parseInt( distance.x * i / 100 );
y = parseInt( distance.y * i / 100 );
element.setAttribute( "transform", "translate( " + x + ", " + y + " )" );
}, 20 + i );
}
}
or per Erik's advice:
function translateElement( element, distance )
{
var x, y;
for( var i = 0; i < 100; i++ )
{
setTimeout( function( ) {
x = distance.x * i / 100;
y = distance.y * i / 100;
element.transform.baseVal.getItem( 0 ).setTranslate( x, y );
}, 20 + i );
}
}
Where element is the element you're moving and distance is an object of the form:
{
x: xOffset,
y: yOffset
}

Categories

Resources