How can I make canvas element act as a background? - javascript

I want to use the canvas element as the background for my page.
How can I make "We craft brand experiences for companies and nonprofits making a difference." show up on top of the background?
<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<title>Confetti Party</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">
</head>
<body>
<canvas id="canvas"></canvas>
<script src="js/index.js"></script>
<h1>we craft brand experiences for companies and nonprofits making a difference. </h1>
</body>
</html>
As you can see, my h1 tag is not on top of background.

If I understand your question correctly, then you effectively want to make the canvas your page's background. This is rather trivial can be done by taking advantage of the CSS z-index property:
///////////////////////////////////////////////
// configurables
///////////////////////////////////////////////
// background color
// var bg = [159, 240, 167]
var bg = [255, 255, 225]
// maximum number of particles present at any time
var num_particles = 150
// chace of split
var chance_birth = 0.37
// chance of termination/death
var chance_death = 0.38
var cols = ['#FF5722', '#FF9800', '#FF9800', '#FF9800', '#FF9800', '#B71C1C', '#00BCD4', '#00BCD4', '#009688']
///////////////////////////////////////////////
// the other stuff
///////////////////////////////////////////////
//var canvas = document.createElement("canvas")
//document.getElementsByTagName("body")[0].appendChild(canvas)
var canvas = document.getElementById("canvas")
var ctx = canvas.getContext("2d")
var particles = []
var step = 0
var step_max = 360
setup()
window.addEventListener("resize", setup)
function setup() {
canvas.width = window.innerWidth
canvas.height = window.innerHeight
fill(1)
}
function fill(amt) {
ctx.beginPath();
ctx.rect(0, 0, canvas.width, canvas.height)
ctx.fillStyle = `rgba(${bg[0]}, ${bg[1]}, ${bg[2]}, ${amt})`
ctx.fill()
}
setInterval(animate, 1000/60)
// window.requestAnimationFrame(animate);
function animate() {
fill(0.01)
step = (step + 1) % step_max
draw()
// window.requestAnimationFrame(function(){animate()})
}
function getRandCol () {
return cols[Math.floor(Math.random() * cols.length)]
}
function draw() {
var pad = 0.02
var p
if (particles.length < num_particles && step % 2 === 0) {
var x = (Math.random() * (1 - pad * 2) + pad) * canvas.width
var y = canvas.height + Math.random()*10 //(Math.random() * (1 - pad * 2) + pad) * canvas.height
p = new Particle(x, y, ctx)
particles.push(p)
}
var i
for (i = 0; i < particles.length; i++) {
particles[i].update()
particles[i].draw()
// branch-birth
if (step % 4 === 0 && Math.random() < chance_birth && particles.length < num_particles) {
var x = particles[i].x
var y = particles[i].y
p = new Particle(x, y, ctx)
p.color = particles[i].color
particles.push(p)
}
}
// death
for (i = particles.length -1 ; i >= 0; i--) {
p = particles[i]
if ((step % 4 === 0 && Math.random() < chance_death) || p.y < -20 || p.x < -20 || p.x > canvas.width + 20) {
particles.splice(i, 1)
}
}
// draw links
var dist_max = 60
for (i = particles.length -1 ; i >= 0; i--) {
p = particles[i]
}
}
function Particle (x, y, ctx) {
this.x = x
this.y = y
this.px = x
this.py = y
this.dx_min = -20
this.dx_max = 20
this.dy_min = -1
this.dy_max = -25
this.s = 0.8
this.ctx = ctx
this.color = getRandCol() //"#ee9977"
this.update = function () {
this.px = this.px * this.s + this.x * (1 - this.s)
this.py = this.py * this.s + this.y * (1 - this.s)
var dxy = this.dxy()
this.x = this.s * this.x + (Math.random() * dxy.dx + this.x) * (1 - this.s)
this.y = this.s * this.y + (Math.random() * dxy.dy + this.y) * (1 - this.s)
}
this.draw = function () {
// var v = Math.min(this.vsq(), 500)
ctx.lineWidth = 2 //Math.sqrt(v)/3
ctx.beginPath()
ctx.moveTo(this.px, this.py)
ctx.strokeStyle = this.color
ctx.lineTo(this.x, this.y)
ctx.lineCap = "round"
ctx.stroke()
}
this.dxy = function () {
var dx = (this.dx_max - this.dx_min) * Math.random() + this.dx_min
var dy = (this.dy_max - this.dy_min) * Math.random() + this.dy_min
return {dx, dy}
}
this.vsq = function () {
var x = this.px - this.x
var y = this.py - this.y
return x * x + y * y
}
}
canvas{
/* Move the canvas to a low z-index (background) */
z-index: -1;
}
.wrapup{
/* This class creates a div that is positioned on top of everything outside of it */
width:100%;
height:100%;
z-index:100;
display:block;
overflow:hidden;
margin:0;
border:0;
padding:0;
position:absolute;
top:0;
bottom:0;
right:0;
left:0;
}
body {
/* Just some stuff to clean up the look by filling page and removing scrollbars */
width:100%;
height: 100%;
overflow: hidden;
}
<!DOCTYPE html>
<html >
<head>
<meta charset="UTF-8">
<title>Confetti Party</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">
</head>
<body>
<canvas id="canvas"></canvas>
<script src="js/index.js"></script>
<div class="wrapup">
<h1>we craft brand experiences for companies and nonprofits making a difference. </h1>
</div>
</body>
</html>
As for how you decide to position the h1 on the page, that is up to you, but anything you place inside of the wrapup div will appear atop the canvas.

Change <h1> to
<h1 style="position:fixed; top:500px; left:300px;">
You can adjust the 500px and 300px values to move it to a different position on the screen. You can also use a combination of % and margin to automatically center the element, for example:
top:50%; margin-top:-6em;
If you want the text to scroll down with the page, use position:absolute instead.

Related

How to organize circles into coherent "glob"

Here's my code:
<!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">
<title>Johnny's Potential Homepage</title>
<style type="text/css">
#font-face {
font-family: Abel Regular;
src: url("fonts/Abel-Regular.ttf");
}
body {
margin: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script type="text/javascript">
class Circle {
constructor(x, y, radius) {
this.x = x;
this.y = y;
this.destinationX = x;
this.destinationY = y;
this.originalRadius = radius;
this.radius = radius/2;
this.contentAlpha = 0;
this.displayDelay = 50;
this.displayDelayTicker = 0;
}
update() {
var offset = Math.sqrt(Math.sqrt(Math.pow(this.x-mouseX, 2)+(Math.pow(this.y-mouseY, 2))));
var angle = -Math.atan2(this.x-mouseX, this.y-mouseY) - Math.PI/2;
this.destinationX = canvas.width / 2 + offset * Math.cos(angle);
this.destinationY = canvas.height / 2 + offset * Math.sin(angle);
this.fixCollisions();
this.x += (this.destinationX - this.x) / 10;
this.y += (this.destinationY - this.y) / 10;
this.radius += (this.originalRadius - this.radius) / 10;
if (this.displayDelayTicker >= this.displayDelay) {
this.contentAlpha += (1 - this.contentAlpha) / 10;
}
this.displayDelayTicker = Math.min(this.displayDelay, this.displayDelayTicker+1);
}
draw() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2);
ctx.fillStyle = "#000";
ctx.filter = "blur(120px)";
ctx.fill();
ctx.filter = "blur(0px)";
ctx.fillStyle = "rgba(0, 0, 0, 0.8)";
ctx.fill();
}
fixCollisions() {
for (var i = 0; i < circles.length; i++) {
if (circles[i] != this) {
var angle = getAngle([this.x, this.y], [circles[i].x, circles[i].y]);
var dist = ((this.radius + circles[i].radius)/2 + padding);
// Distribute
this.destinationX += Math.cos(-angle) * dist;
this.destinationY += Math.sin(-angle) * dist;
}
}
}
}
class Centerpiece extends Circle {
constructor(x, y, radius) {
super(x, y, radius);
this.time = 0;
this.readTime = "";
this.readSeconds = "";
}
update() {
super.update();
var date = new Date();
var destTime = date.getHours()*3600 + date.getMinutes()*60 + date.getSeconds();
if (this.displayDelayTicker >= this.displayDelay) {
this.time += (destTime - this.time) / 10;
}
var hours = Math.floor(this.time / 3600);
if (hours > 12) {
hours -= 12;
}
var minutes = (this.time/60) % 60;
minutes = Math.floor(minutes);
if (minutes < 10) {
minutes = "0" + minutes;
}
var seconds = (this.time) % 60;
seconds = Math.floor(seconds);
if (seconds < 10) {
seconds = "0" + seconds;
}
this.readTime = hours + ":" + minutes;
this.readSeconds = seconds;
}
draw() {
super.draw();
ctx.font = "14px Abel Regular";
var secondsWidth = ctx.measureText(this.readSeconds).width;
ctx.font = "21px Abel Regular";
var timeWidth = ctx.measureText(this.readTime).width;
ctx.textAlign = "center";
ctx.fillStyle = "rgba(255, 255, 255, " + this.contentAlpha + ")";
ctx.fillText(this.readTime, this.x - secondsWidth/2 -1, this.y);
ctx.font = "14px Abel Regular";
ctx.fillText(this.readSeconds, this.x + timeWidth/2 + 1, this.y);
}
}
var canvas = document.getElementById("canvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var ctx = canvas.getContext("2d");
var circles = [];
var mouseX = canvas.width/2;
var mouseY = canvas.height/2;
var scale = 1.0;
var scrollAmount = 0;
var padding = Math.sqrt(getDistance([0, 0], [canvas.width/2, canvas.height/2]));
circles.push(new Centerpiece(canvas.width/2, canvas.height/2, 120));
circles.push(new Centerpiece(canvas.width/2, canvas.height/2, 100));
circles.push(new Centerpiece(canvas.width/2, canvas.height/2, 80));
circles.push(new Centerpiece(canvas.width/2, canvas.height/2, 90));
window.onresize = function() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var padding = Math.sqrt(getDistance([0, 0], [canvas.width/2, canvas.height/2])) + 10;
}
window.onmousemove = function(e) {
mouseX = e.clientX;
mouseY = e.clientY;
}
window.onwheel = function(e) {
scrollAmount -= Math.min(Math.max(-0.5, e.deltaY), 0.5);
scale = (Math.log10(Math.min(2, Math.max(0.5, scrollAmount + 1)))) + 1;
console.log(scrollAmount + " " + scale);
}
function getDistance(a, b) {
return (Math.sqrt((b[0]-a[0])*(b[0]-a[0])-(b[1]-a[1])*(b[1]-a[1])));
}
function getAngle(a, b) {
return Math.atan2(b[1] - a[1], b[0] - a[0]);
}
function loop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (var i = 0; i < circles.length; i++) {
circles[i].update();
}
for (var i = 0; i < circles.length; i++) {
circles[i].draw();
}
requestAnimationFrame(loop);
}
loop();
</script>
</body>
</html>
My goal is to have the circles "glob" together in the middle, yet not collide. Take a look at the fixCollisions() function and see if there's a way to update things so the circles spread evenly across the x and y axis.
Also, I'm not sure why it bugs out at the beginning.
I think this does what you need, if I understood correctly. I commented out some lines and changed some others. I removed the mouse following part because I did not get to fix that and it causes a problem by resetting the position of the blobs every time it updates.
Then I changed the way the blobs are made to be attracted to each other but not allowing them to overlap.
I also simplified the way the sines and cosines are calculated. You don't actually need to first find the angle and the take the cosine and sine of the angle since you already have these when dividing the x and y displacements by the distance. That is in actual fact dividing the opposite and the adjacent sides by the hypotenuse, which is actually the definition of a sine and cosine.
<!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">
<title>Johnny's Potential Homepage</title>
<style type="text/css">
#font-face {
font-family: Abel Regular;
src: url("fonts/Abel-Regular.ttf");
}
body {
margin: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script type="text/javascript">
class Circle {
constructor(x, y, radius) {
this.x = x;
this.y = y;
this.destinationX = x;
this.destinationY = y;
this.originalRadius = radius;
this.radius = radius/2;
this.contentAlpha = 0;
this.displayDelay = 50;
this.displayDelayTicker = 0;
}
update() {
var offset = Math.sqrt(Math.sqrt(Math.pow(this.x-mouseX, 2)+(Math.pow(this.y-mouseY, 2))));
var angle = -Math.atan2(this.x-mouseX, this.y-mouseY) - Math.PI/2;
//this.destinationX = canvas.width / 2 + offset * Math.cos(angle);
//this.destinationY = canvas.height / 2 + offset * Math.sin(angle);
this.fixCollisions();
this.x += (this.destinationX - this.x) / 10;
this.y += (this.destinationY - this.y) / 10;
// removed this.radius += (this.originalRadius - this.radius) / 10;
// changed
this.x += Math.min( 1 * ( canvas.width / 2 - this.x ),1 );
this.y += Math.min( 1 * ( canvas.height / 2 - this.y ),1 );
if (this.displayDelayTicker >= this.displayDelay) {
this.contentAlpha += (1 - this.contentAlpha) / 10;
}
this.displayDelayTicker = Math.min(this.displayDelay, this.displayDelayTicker+1);
}
draw() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.radius, 0, Math.PI*2);
ctx.fillStyle = "#000";
ctx.filter = "blur(120px)";
ctx.fill();
ctx.filter = "blur(0px)";
ctx.fillStyle = "rgba(0, 0, 0, 0.8)";
ctx.fill();
}
fixCollisions() {
for (var i = 0; i < circles.length; i++)
{
if (circles[i] != this) {
//var angle = getAngle([this.x, this.y], [circles[i].x, circles[i].y]);
//var dist = ((this.radius + circles[i].radius)/2 + padding);
var minDist = ((this.radius + circles[i].radius));
var dist = Math.sqrt( (this.x-circles[i].x)*(this.x-circles[i].x) + (this.y-circles[i].y)*(this.y-circles[i].y) )
// Distribute
if ( dist < minDist) // overlapping so push away
{
this.destinationX += 100 * (( this.x - circles[i].x) / minDist ) / ( dist + 1 );
this.destinationY += 100 * (( this.y - circles[i].y) / minDist ) / ( dist + 1 );
}
if ( dist > minDist) // overlapping so push away
{
this.destinationX += -0.001 * (( this.x - circles[i].x) / minDist ) * dist;
this.destinationY += -0.001 * (( this.y - circles[i].y) / minDist ) * dist;
}
}
}
}
}
class Centerpiece extends Circle {
constructor(x, y, radius) {
super(x, y, radius);
this.time = 0;
this.readTime = "";
this.readSeconds = "";
}
update() {
super.update();
var date = new Date();
var destTime = date.getHours()*3600 + date.getMinutes()*60 + date.getSeconds();
if (this.displayDelayTicker >= this.displayDelay) {
this.time += (destTime - this.time) / 10;
}
var hours = Math.floor(this.time / 3600);
if (hours > 12) {
hours -= 12;
}
var minutes = (this.time/60) % 60;
minutes = Math.floor(minutes);
if (minutes < 10) {
minutes = "0" + minutes;
}
var seconds = (this.time) % 60;
seconds = Math.floor(seconds);
if (seconds < 10) {
seconds = "0" + seconds;
}
this.readTime = hours + ":" + minutes;
this.readSeconds = seconds;
}
draw() {
super.draw();
ctx.font = "14px Abel Regular";
var secondsWidth = ctx.measureText(this.readSeconds).width;
ctx.font = "21px Abel Regular";
var timeWidth = ctx.measureText(this.readTime).width;
ctx.textAlign = "center";
ctx.fillStyle = "rgba(255, 255, 255, " + this.contentAlpha + ")";
ctx.fillText(this.readTime, this.x - secondsWidth/2 -1, this.y);
ctx.font = "14px Abel Regular";
ctx.fillText(this.readSeconds, this.x + timeWidth/2 + 1, this.y);
}
}
var canvas = document.getElementById("canvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var ctx = canvas.getContext("2d");
var circles = [];
var mouseX = canvas.width/2;
var mouseY = canvas.height/2;
var scale = 1.0;
var scrollAmount = 0;
var padding = Math.sqrt(getDistance([0, 0], [canvas.width/2, canvas.height/2]));
circles.push(new Centerpiece(0.27 * canvas.width, 0.67 * canvas.height/2, 120));
circles.push(new Centerpiece(0.98 * canvas.width, 0.23 * canvas.height/2, 100));
circles.push(new Centerpiece(0.46 * canvas.width, 0.15 * canvas.height/2, 80));
circles.push(new Centerpiece(0.37 * canvas.width, 0.29 * canvas.height/2, 90));
window.onresize = function() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var padding = Math.sqrt(getDistance([0, 0], [canvas.width/2, canvas.height/2])) + 10;
}
window.onmousemove = function(e) {
mouseX = e.clientX;
mouseY = e.clientY;
}
window.onwheel = function(e) {
scrollAmount -= Math.min(Math.max(-0.5, e.deltaY), 0.5);
scale = (Math.log10(Math.min(2, Math.max(0.5, scrollAmount + 1)))) + 1;
console.log(scrollAmount + " " + scale);
}
function getDistance(a, b) {
return (Math.sqrt((b[0]-a[0])*(b[0]-a[0])-(b[1]-a[1])*(b[1]-a[1])));
}
function getAngle(a, b) {
return Math.atan2(b[1] - a[1], b[0] - a[0]);
}
function loop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (var i = 0; i < circles.length; i++) {
circles[i].update();
}
for (var i = 0; i < circles.length; i++) {
circles[i].draw();
}
requestAnimationFrame(loop);
}
loop();
</script>
</body>
</html>

Uncaught TypeError: ctx.clearReact is not a function at animate

Im pretty new here and in coding, and Im trying to finish this tutorial:
https://www.youtube.com/watch?v=d620nV6bp0A&ab_channel=Frankslaboratory
const canvas = document.getElementById('canvas1');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
let particlesArray;
let mouse = {
x: null,
y: null,
radius: (canvas.height/80) * (canvas.width/80)
}
window.addEventListener('mousemove',
function(event){
mouse.x = event.x;
mouse.y = event.y;
}
);
class Particle {
constructor(x, y, directionX, directionY, size, color){
this.x = x;
this.y = y;
this.directionX = directionX;
this.directionY = directionY;
this.size = size;
this.color = color;
}
draw() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2, false );
ctx.fillStyle = '#8C5523';
ctx.fill();
}
update() {
if(this.x > canvas.width || this.x <0 ){
this.directionX = - this.directionX;
}
if(this.y > canvas.height || this.y < 0){
this.directionY = - this.directionY;
}
let dx = mouse.x - this.x;
let dy = mouse.y - this.y;
let distance = Math.sqrt(dx * dx + dy * dy)
if (disance < mouse.radius + this.size){
if(mouse.x < this.x && this.x <canvas.width - this.size * 10){
this.x += 10;
}
if(mouse.x >this.x && this.x > this.size *10){
this.x -=10;
}
if(mouse.y < this.y && this.y < canvas.height - this.size * 10){
this.y += 10;
}
if(mouse.y > this.y && this.y > this.size * 10){
this.y -= 10;
}
}
this.x += this.directionX;
this.y += this.directionY;
this.draw();
}
}
function init() {
particlesArray = [];
let numberOfParticles = (canvas.height * canvas.width) / 9000;
for (let i = 0; i < numberOfParticles *2 ; i++){
let size = (Math.random() * 5 ) + 1;
let x = (Math.random() * ((innerWidth - size * 2) - (size * 2)) + size * 2);
let y = (Math.random() * ((innerHeight - size * 2) - (size * 2)) + size * 2);
let directionX = (Math.random() * 5) - 2.5;
let directionY = (Math.random() * 5) - 2.5;
let color = '#8C5523';
particlesArray.push(new Particle(x, y ,directionX, directionY, size, color));
}
}
function connect(){
let opacityValue = 1;
for( let a=0; a < particlesArray.length; a++ ){
for(let b = a; b < particlesArray.length; b++){
let distance = (( particlesArray[a].x - particlesArray[b].x)
* (particlesArray[a].x - particlesArray[b].x))
+ ((particlesArray[a].y - particlesArray[b].y) *
(particlesArray[a] .y - particlesArray[b].y));
if(distance < (canvas.width/7) * (canvas.height/7)){
opacityValue = 1 - (distance/20000);
ctx.strokeStyle='rgba(140,85,31,' + opacityValue + ')';
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo(particlesArray[a].x, particlesArray[a].y);
ctx.lineTo(particlesArray[b].x, particlesArray[b].y);
ctx.stroke();
}
}
}
}
function animate(){
requestAnimationFrame (animate);
ctx.clearReact(0, 0, innerWidth, innerHeight)
for (let i = 0; i < particlesArray.length; i++) {
particlesArray[i].update();
}
connect();
}
window.addEventListener('resize',
function(){
canvas.width = innerWidth;
canvas.height = innerHeight;
mouse.radius = ((canvas.height/80) * (canvas.height/80));
init();
}
);
window.addEventListener('mouseout',
function(){
mouse.x = undefined;
mouse.x = undefined;
}
)
init();
animate();
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
#canvas1 {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: radial-gradient(#ffc38c,#ff9b40);
}
<!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">
<title>MyWebsitePLAX</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<canvas id="canvas1"></canvas>
<script src="script.js"></script>
</body>
</html>
I am making progress up to this point and then I have a lot of errors in my console stacking and saying: "Uncaught TypeError: ctx.clearReact is not a function
at animate"
When I open this project nothing is rendering on website. I Find out that here is some kind of problem
function animate(){
requestAnimationFrame (animate);
ctx.clearReact(0, 0, innerWidth, innerHeight)
for (let i = 0; i < particlesArray.length; i++) {
particlesArray[i].update();
}
connect();
}
Could some1 possible help to solve this problem and explain some part of it to :)?

Why HTML canvas collision is not happening for the ball and the paddle?

I am building my ping pong game with javascript, Canvas and HTML So here is my Javascript code below to create the paddle and the ball. I want to know how to make the collision happen between paddle and ball. Below are my javascript and HTML
Below is my HTML code. Here I am declaring the canvas element
var c = document.getElementById("frame");
c.width = window.innerWidth * 0.31;
c.height = window.innerHeight * 0.55;
var ctx = c.getContext("2d");
var x = 10;
var y = 10;
var rx = 10;
var ry = 400;
var height = 70;
var width = 12;
var radius = 10;
var vx = Math.floor(Math.random() * 2);
var vy = Math.floor(Math.random() * 4);
drawPad(rx, ry, height, width);
function drawPad(rx, ry, height, width) {
ctx.fillStyle = "#f2a34b";
ctx.fillRect(rx, ry, height, width);
}
function drawCircle() {
ctx.beginPath();
ctx.arc(x, y, radius, 0, 2 * Math.PI);
ctx.closePath();
ctx.stroke();
ctx.fill();
}
function moveCircle() {
requestAnimationFrame(moveCircle);
if ((x + radius > 500) || (x - radius < 0)) {
vx = 0 - vx;
}
if ((y + radius > 420) || (y - radius < 0)) {
vy = 0 - vy;
}
x = x + vx;
y = y + vy;
ctx.clearRect(0, 0, 500, 500);
drawPad(rx, ry, height, width);
drawCircle();
}
moveCircle();
window.onkeydown = function(event) {
if (event.keyCode == 37 && rx > 20) {
rx = rx - 20;
} else if (event.keyCode == 39 && rx <= 420) {
rx = rx + 20;
}
ctx.clearRect(0, 0, 500, 500);
drawPad(rx, ry, height, width);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style type="text/css">
canvas {
border: 1px solid #c7c7c7;
background-color: rgb(175, 166, 166);
}
</style>
</head>
<body>
<canvas id="frame"></canvas>
<script src="canvas.js"></script>
</body>
</html>
I only see you verify the collision with the borders in your code, but not with the paddle itself.
You just need to add some condition to detect its collision with the paddle. If a collision happened then the ball will move up otherwise it moves down
if(y+radius>=ry)
{
moveUp = true;
moveDown = false;
}
if(y+radius<=0)
{
moveUp = false;
moveDown = true;
}
and later tell the programe how it will happen
if(moveUp){
//x = x + vx;
y = y - vy;
}
if(moveDown){
//x = x - vx;
y = y + vy;
}
which gives you something like that if i am not mistaken :
var c = document.getElementById("frame");
c.width = window.innerWidth * 0.31;
c.height = window.innerHeight * 0.55;
var ctx = c.getContext("2d");
var x = 10;
var y = 10;
var rx = 10;
var ry = (window.innerHeight*0.55)-10;
var height = 70;
var width = 12;
var radius = 10;
var vx = Math.floor(Math.random() * 2);
var vy = Math.floor(Math.random() * 4);
let moveUp = false;
let moveDown = true;
drawPad(rx, ry, height, width);
function drawPad(rx, ry, height, width) {
ctx.fillStyle = "#f2a34b";
ctx.fillRect(rx, ry, height, width);
}
function drawCircle() {
ctx.beginPath();
ctx.arc(x, y, radius, 0, 2 * Math.PI);
ctx.closePath();
ctx.stroke();
ctx.fill();
}
function moveCircle() {
requestAnimationFrame(moveCircle);
/*if ((x + radius > 500) || (x - radius < 0)) {
vx = 0 - vx;
}*/
if((x+radius>=rx)&&(y+radius>=ry))
{
moveUp = true;
moveDown = false;
}
if(y+radius<=0)
{
moveUp = false;
moveDown = true;
}
/*if ((y + radius > 420) || (y - radius < 0)) {
vy = 0 - vy;
}*/
if(moveUp){
//x = x + vx;
y = y - vy;
}
if(moveDown){
//x = x - vx;
y = y + vy;
}
ctx.clearRect(0, 0, 500, 500);
drawPad(rx, ry, height, width);
drawCircle();
}
moveCircle();
window.onkeydown = function(event) {
if (event.keyCode == 37 && rx > 20) {
rx = rx - 20;
} else if (event.keyCode == 39 && rx <= 420) {
rx = rx + 20;
}
ctx.clearRect(0, 0, 500, 500);
drawPad(rx, ry, height, width);
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style type="text/css">
canvas {
border: 1px solid #c7c7c7;
background-color: rgb(175, 166, 166);
}
</style>
</head>
<body>
<canvas id="frame"></canvas>
<script src="canvas.js"></script>
</body>
</html>

how to decrease speed of canvas animation?

I am creating an animation using java script & canvas. I am using a fiddle as a reference, currently object are generating randomly & falling from top right corner to bottom left corner which is okay. but the issue is speed the objects are generating & falling in high speed. I want to make animation flow little slow & smooth.
I am new canvas programming, any help will be very useful.
(function() {
var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame ||
function(callback) {
window.setTimeout(callback, 1000 / 60);
};
window.requestAnimationFrame = requestAnimationFrame;
})();
var particleArr = [],
canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d"),
flakeCount = 700,
mouseX = -100,
mouseY = -100,
xMultiplier = 0.015
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
function getRandomColor() {
// Random Color Generate
const colorArr = ["rgba(215,88,69, 1)", "rgba(117, 161, 199, 1)"]; // Blue & Orange Color
const randomColor = colorArr[Math.floor(Math.random() * colorArr.length)];
return randomColor;
}
function flow() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (var i = 0; i < flakeCount; i++) {
var flake = particleArr[i],
x = mouseX,
y = mouseY,
minDist = 150,
x2 = flake.x,
y2 = flake.y;
var dist = Math.sqrt((x2 - x) * (x2 - x) + (y2 - y) * (y2 - y)),
dx = x2 - x,
dy = y2 - y;
if (dist < minDist) {
var force = minDist / (dist * dist),
xcomp = (x - x2) / dist,
ycomp = (y - y2) / dist,
deltaV = force / 2;
flake.velX -= deltaV * xcomp;
flake.velY -= deltaV * ycomp;
} else {
flake.velX *= .98;
if (flake.velY <= flake.speed) {
flake.velY = flake.speed
}
flake.velX += Math.cos(flake.step += .05) * flake.stepSize;
}
ctx.fillStyle = getRandomColor();
flake.y += flake.velY;
flake.x += flake.velX;
if (flake.y >= canvas.height || flake.y <= 0) {
reset(flake);
}
if (flake.x >= canvas.width || flake.x <= 0) {
reset(flake);
}
ctx.beginPath();
ctx.arc(flake.x, flake.y, flake.size, 0, Math.PI * 2);
ctx.fill();
}
requestAnimationFrame(flow);
};
function reset(flake) {
let temp = (Math.random() * 1) + 0.5;
flake.x = canvas.width;
flake.y = 50;
flake.size = (Math.random() * 3) + 5;
flake.speed = (Math.random() * 7) + 0.5;
flake.velY = flake.speed;
flake.velX = -xMultiplier * canvas.width * temp;
// flake.opacity = (Math.random() * 0.5) + 0.3;
}
function init() {
for (var i = 0; i < flakeCount; i++) {
var x = canvas.width,
y = 50,
size = (Math.random() * 3) + 5,
// speed = (Math.random() * 1) + 0.5;
speed = 0;
// opacity = (Math.random() * 0.5) + 0.3;
particleArr.push({
speed: speed,
velY: speed,
velX: -xMultiplier * canvas.width * speed,
x: x,
y: y,
size: size,
stepSize: (Math.random()) / 30,
step: 0,
angle: 360
// opacity: opacity
});
}
flow();
};
canvas.addEventListener("mousemove", function(e) {
mouseX = e.clientX,
mouseY = e.clientY
});
window.addEventListener('resize', onWindowResize, false);
function onWindowResize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
init();
canvas {
background-color: #000000 !important;
}
body {
margin: 0;
overflow: hidden;
}
<canvas id="canvas"></canvas>
Could not work out what it was you wanted to slow down as there are several FX and interactions in the code.
I rewrote from the ground up as your code is a little old school.
Rather than play with the constants you had OI added the global variable rate (at the ver top of the source) is used to control the rate at which the animation plays, including the user interaction.
I have added two button to slow or speed up the animation.
Hope this helps :)
var rate = 1;
slower.addEventListener("click", () => rate *= 1 / 1.2);
faster.addEventListener("click", () => rate *= 1.2);
const flakes = [], flakeCount = 700, xMultiplier = 0.015;
const minDist = 150, minDistSqr = minDist * minDist;
const colors = ["#F99","#F83","#AF9","#ED9","#AC8","#FA9" ];
const ctx = canvas.getContext("2d");
const mouse = {x: -100, y: -100};
const randPick = (arr, len = arr.length) => arr[Math.random() * len | 0];
Math.rand = (min, range) => Math.random() * range + min;
function Flake() {
this.reset();
this.stepSize = Math.random() / 30;
this.step = 0;
}
Flake.prototype = {
reset() {
this.x = canvas.width;
this.y = 50;
this.size = Math.rand(5, 3);
this.speed = Math.rand(0.5, 7);
this.velY = this.speed;
this.velX = -xMultiplier * canvas.width * Math.rand(0.5, 1);
this.col = randPick(colors);
},
draw() {
ctx.fillStyle = this.col;
const s = this.size, sh = -s / 2;
ctx.fillRect(this.x + sh, this.y + sh, s, s);
},
update(w, h) {
const f = this;
const dx = f.x - mouse.x;
const dy = f.y - mouse.y;
const distSqr = dx * dx + dy * dy;
if (distSqr < minDistSqr) {
const deltaV = 2 * minDist * rate / distSqr ** 1.5;
f.velX -= deltaV * dx;
f.velY -= deltaV * dy;
} else {
f.velX -= 0.1 * rate * f.velX;
if (f.velY <= f.speed ) { f.velY = f.speed }
f.velX += Math.cos(f.step += 0.05 * rate) * f.stepSize * rate;
}
f.y += f.velY * rate;
f.x += f.velX * rate;
if (f.y >= h || f.y <= 0 || f.x >= w || f.x <= 0) { this.reset() }
else { this.draw() }
}
};
init();
mainLoop();
function mainLoop() {
if (innerWidth !== canvas.width || innerHeight !== canvas.height) { resize() }
else { ctx.clearRect(0, 0, canvas.width, canvas.height) }
for (const f of flakes) { f.update(canvas.width, canvas.height) }
requestAnimationFrame(mainLoop);
}
function init() {
var i = flakeCount;
while (i--) { flakes.push(new Flake()) }
}
canvas.addEventListener("mousemove", e => { mouse.x = e.clientX; mouse.y = e.clientY });
function resize() { canvas.width = innerWidth; canvas.height = innerHeight }
canvas {
background-color: #000;
}
body {
margin: 0;
}
.buttons {
position: absolute;
top: 12px;
left: 12px;
color: #000;
background-color: #AAA;
}
.buttons > div {
margin: 3px;
padding: 3px;
background-color: #EEE;
cursor: pointer;
}
.buttons > div:hover {
background-color: #DEF;
}
<canvas id="canvas"></canvas>
<div class = "buttons">
<div id="slower">Slower</div>
<div id="faster">Faster</div>
</div>
That requestAnimationFrame() function that calls flow() every frame is designed to run as fast as possible for whoever's computer it's running on. I wouldn't mess with your actual render loop.
Try messing with the flake.speed or the xMultiplier. Those are two of the main variables affecting the speed of your particles. You can see how each time through the flow() loop you're adjusting each particle's position based on their velocity properties and position. Then finally rendering the arc with ctx.arc(flake.x, flake.y, flake.size, 0, Math.PI * 2);
So any variable passed to ctx.arc() affects the particle's position. And many of those variables are recalculated each time through the loop.
I'm no expert here, but maybe try fiddling with your variables.
https://codepen.io/nitwit/pen/XWXJNaJ
https://jsfiddle.net/z6r8h5de/
if the issue is there are too many flakes on the screen, turn the count down from 700.
flakeCount = 100,

Remove objects in the canvas in certain coordinates

I would like to remove the balls already generated in the canvas on the click and decrease the counter on the bottom, but my function does not work. Here is my code concerning the part of the ball removal.
Is it possible to use a div to get the same result and to facilitate the removal of the balls? thank you
ball.onclick = function removeBalls(event) {
var x = event.clientX;
var y = event.clientY;
ctx.clearRect(x, y, 100, 50);
ctx.fillStyle = "#000000";
ctx.font = "20px Arial";
ctx.fillText("Balls Counter: " + balls.length - 1, 10, canvas.height - 10);
}
below I enclose my complete code
// GLOBAL VARIBLES
var gravity = 4;
var forceFactor = 0.3; //0.3 0.5
var mouseDown = false;
var balls = []; //hold all the balls
var mousePos = []; //hold the positions of the mouse
var ctx = canvas.getContext('2d');
var heightBrw = canvas.height = window.innerHeight;
var widthBrw = canvas.width = window.innerWidth;
var bounciness = 1; //0.9
window.onload = function gameCore() {
function onMouseDown(event) {
mouseDown = true;
mousePos["downX"] = event.pageX;
mousePos["downY"] = event.pageY;
}
canvas.onclick = function onMouseUp(event) {
mouseDown = false;
balls.push(new ball(mousePos["downX"], mousePos["downY"], (event.pageX - mousePos["downX"]) * forceFactor,
(event.pageY - mousePos["downY"]) * forceFactor, 5 + (Math.random() * 10), bounciness, random_color()));
ball
}
function onMouseMove(event) {
mousePos['currentX'] = event.pageX;
mousePos['currentY'] = event.pageY;
}
function resizeWindow(event) {
canvas.height = window.innerHeight;
canvas.width = window.innerWidth;
}
function reduceBounciness(event) {
if (bounciness == 1) {
for (var i = 0; i < balls.length; i++) {
balls[i].b = bounciness = 0.9;
document.getElementById("btn-bounciness").value = "⤽ Bounciness";
}
} else {
for (var i = 0; i < balls.length; i++) {
balls[i].b = bounciness = 1;
document.getElementById("btn-bounciness").value = " ⤼ Bounciness";
}
}
return bounciness;
}
function reduceSpeed(event) {
for (var i = 0; i < balls.length; i++) {
balls[i].vx = velocityX = 20 + c;
balls[i].vy = velocityY = 20 + c;
}
}
function speedUp(event) {
for (var i = 0; i < balls.length; i++) {
balls[i].vx = velocityX = 120 + c;
balls[i].vy = velocityY = 120 + c;
}
}
function stopGravity(event) {
if (gravity == 4) {
for (var i = 0; i < balls.length; i++) {
balls[i].g = gravity = 0;
balls[i].vx = velocityX = 0;
balls[i].vy = velocityY = 0;
document.getElementById("btn-gravity").value = "►";
}
} else {
for (var i = 0; i < balls.length; i++) {
balls[i].g = gravity = 4;
balls[i].vx = velocityX = 100;
balls[i].vy = velocityY = 100;
document.getElementById("btn-gravity").value = "◾";
}
}
}
ball.onclick = function removeBalls(event) {
var x = event.clientX;
var y = event.clientY;
ctx.clearRect(x, y, 100, 50);
ctx.fillStyle = "#000000";
ctx.font = "20px Arial";
ctx.fillText("Balls Counter: " + balls.length - 1, 10, canvas.height - 10);
}
document.getElementById("btn-gravity").addEventListener("click", stopGravity);
document.getElementById("btn-speed-up").addEventListener("click", speedUp);
document.getElementById("btn-speed-down").addEventListener("click", reduceSpeed);
document.getElementById("btn-bounciness").addEventListener("click", reduceBounciness);
document.addEventListener("mousedown", onMouseDown);
document.addEventListener("mousemove", onMouseMove);
window.addEventListener('resize', resizeWindow);
}
// GRAPHICS CODE
function circle(x, y, r, c) { // x position, y position, r radius, c color
//draw a circle
ctx.beginPath(); //approfondire
ctx.arc(x, y, r, 0, Math.PI * 2, true);
ctx.closePath();
//fill
ctx.fillStyle = c;
ctx.fill();
//stroke
ctx.lineWidth = r * 0.1; //border of the ball radius * 0.1
ctx.strokeStyle = "#000000"; //color of the border
ctx.stroke();
}
function random_color() {
var letter = "0123456789ABCDEF".split(""); //exadecimal value for the colors
var color = "#"; //all the exadecimal colors starts with #
for (var i = 0; i < 6; i++) {
color = color + letter[Math.round(Math.random() * 15)];
}
return color;
}
function selectDirection(fromx, fromy, tox, toy) {
ctx.beginPath();
ctx.moveTo(fromx, fromy);
ctx.lineTo(tox, toy);
ctx.moveTo(tox, toy);
}
//per velocità invariata rimuovere bounciness
function draw_ball() {
this.vy = this.vy + gravity * 0.1; // v = a * t
this.x = this.x + this.vx * 0.1; // s = v * t
this.y = this.y + this.vy * 0.1;
if (this.x + this.r > canvas.width) {
this.x = canvas.width - this.r;
this.vx = this.vx * -1 * this.b;
}
if (this.x - this.r < 0) {
this.x = this.r;
this.vx = this.vx * -1 * this.b;
}
if (this.y + this.r > canvas.height) {
this.y = canvas.height - this.r;
this.vy = this.vy * -1 * this.b;
}
if (this.y - this.r < 0) {
this.y = this.r;
this.vy = this.vy * 1 * this.b;
}
circle(this.x, this.y, this.r, this.c);
}
// OBJECTS
function ball(positionX, positionY, velosityX, velosityY, radius, bounciness, color, gravity) {
this.x = positionX;
this.y = positionY;
this.vx = velosityX;
this.vy = velosityY;
this.r = radius;
this.b = bounciness;
this.c = color;
this.g = gravity;
this.draw = draw_ball;
}
// GAME LOOP
function game_loop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (mouseDown == true) {
selectDirection(mousePos['downX'], mousePos['downY'], mousePos['currentX'], mousePos['currentY']);
}
for (var i = 0; i < balls.length; i++) {
balls[i].draw();
}
ctx.fillStyle = "#000000";
ctx.font = "20px Arial";
ctx.fillText("Balls Counter: " + balls.length, 10, canvas.height - 10);
}
setInterval(game_loop, 10);
* {
margin: 0px; padding: 0px;
}
html, body {
width: 100%; height: 100%;
}
#canvas {
display: block;
height: 95%;
border: 2px solid black;
width: 98%;
margin-left: 1%;
}
#btn-speed-up, #btn-speed-down, #btn-bounciness, #btn-gravity{
padding: 0.4%;
background-color: beige;
text-align: center;
font-size: 20px;
font-weight: 700;
float: right;
margin-right: 1%;
margin-top:0.5%;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Power Balls</title>
<link rel="stylesheet" type="text/css" href="css/style.css">
</head>
<body>
<canvas id="canvas"></canvas>
<input type="button" value="⤼ Bounciness" id="btn-bounciness"></input>
<input type="button" onclick="c+=10" value="+ Speed" id="btn-speed-up"></input>
<input type="button" value="◾" id="btn-gravity"></input>
<input type="button" onclick="c+= -10" value=" - Speed" id="btn-speed-down"></input>
<script src="js/main.js"></script>
</body>
</html>
I see two problems:
ball.onclick will not get triggered, as ball it is not a DOM object. Instead, you need to work with canvas.onclick. Check whether the user clicked on a ball or on empty space to decide whether to delete or create a ball.
To delete the ball, ctx.clearRect is not sufficient. This will clear the ball from the currently drawn frame, but the object still remains in the array balls and will therefore be drawn again in the next frame via balls[i].draw();. Instead, you need to remove the clicked ball entirely from the array, e. g. by using splice.
Otherwise, nice demo! :)
This cannot be done because the canvas is an immediate mode API. All you can do is draw over the top but this is not reliable.
https://en.wikipedia.org/wiki/Immediate_mode_(computer_graphics)
You will have to store each item in a separate data structure, then re-draw whenever a change occurs. In your case there is an array of balls, so you should remove the one that was clicked, before redrawing the entire array.
Each time you remove something, clear the canvas then re-draw each ball.
There are optimisations you can make if this is too slow.

Categories