Bouncing Shapes Background With Canvas
Krisztián Maurer
Posted on July 27, 2022
The goal of this project is to make a cool background with randomized shapes and to be customizable.
Demo: https://canvas-shapes-background.netlify.app/
Code: https://github.com/MaurerKrisztian/CanvasShapesBackground
Simple example usage:
https://codepen.io/maurerkrisztian/pen/rNdGerb
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type='text/javascript' src="https://canvas-shapes-background.netlify.app/bundle.js"></script>
</head>
<body>
<canvas id="myCanvas"></canvas>
<script>
createShapeCanvas("myCanvas", {
modelNumbers: 11,
colors: ['blue', 'red', 'green', 'yellow'],
backgroundColor: 'black', //'none',
enabledModels: ['Triangle', 'Circle', 'Rect'],
minSpeed: 11,
maxSpeed: 11,
lineWidth: 3,
sizeMultiplier: 2,
startPosition: 'random' // 'middle' | 'random',
isFullScreen: true,
})
</script>
</body>
</html>
I added a configurator with the demo: https://canvas-shapes-background.netlify.app/
- Easily test different configs and copy the configured settings.
"createShapeCanvas" has 2 arg
- canvas id
- config
config
- startPosition: 'middle' | 'random' initial model position
- enabledModels: thies shapes will be generated randomly
- modelNumbers: generate this amount of models from "enabledModels" array
- colors: pisck random color from this array for shapes
- backgroundColor: canvas background color, can be "none"
- minSpeed: shape min speed
- maxSpeed: shape max speed
- lineWidth: shape border line width
- sizeMultiplier: multiply the generated size with this
- isFullScreen: fullscreen or element size
How I made it?
I used HTML Canvas.
I wanted to be easily extendable, so abstracted some thing:
Animator:
- it is responsible for setup every frame and call the modell update()
Model:
- has 2 main responsibility:
- draw() - draw the shape,
- update()
- howto behave based on the current x,y position and
- xd, dy aka where to want to move and how fast. If you confused how dx, dy it works it basicly a vector. it has a direction (this will be the model direction) and a length (this will be the model speed).
Example model:
export class CircleModel implements IModel {
static MODEL_NAME = 'Circle'
color: string;
constructor(private x: number, private y: number, private dx: number, private dy: number, private radius: number, private lineWidth: number = Setup.CONFIG.lineWidth) {
this.color = Utils.pickRandomFromArray<string>(Setup.CONFIG.colors)
}
draw(context: CanvasRenderingContext2D) {
context.lineWidth = this.lineWidth;
context.beginPath();
context.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
context.strokeStyle = this.color;
context.stroke();
context.lineWidth = DEFAULT_LINE_WIDTH;
}
update(context: CanvasRenderingContext2D) {
if (this.x > Context.canvasWidth - this.radius || this.x < 0 + this.radius) {
this.dx = -this.dx;
}
if (this.y > Context.canvasHeight - this.radius || this.y < 0 + this.radius) {
this.dy = -this.dy;
}
this.x = this.x + this.dx;
this.y = this.y + this.dy;
this.draw(context);
}
}
I wanted to baunce of from the side of the canvas so
Good to know where is the canvas side.
So x(0) the left min position and x(canvasWidth) the right side posion, similarly with y.
if (this.x > Context.canvasWidth - this.radius || this.x < 0 + this.radius) {
this.dx = -this.dx;
}
If the current position (center of the circle) greather than canvas width - radius than change the x direction
Similarly with y.
At the end we need to set the new position:
this.x = this.x + this.dx;
this.y = this.y + this.dy;
I made 3 model: Cirle, Rect, Triangle.
But you can add easily your model:
- create a model
- add to ModelFactory
private static createRandomModel() {
const speed = Utils.generateRandom(Setup.CONFIG.minSpeed, Setup.CONFIG.maxSpeed)
const randoModelName = Utils.pickRandomFromArray(Setup.CONFIG.enabledModels)
switch (randoModelName) {
case CircleModel.MODEL_NAME:
return this.createRandomCircle(speed)
break;
case TriangleModel.MODEL_NAME:
return this.createRandomTriangle(speed)
break;
case RectModel.MODEL_NAME:
return this.createRandomRect(speed)
break;
default:
throw new Error(`Model not found with name: ${randoModelName}`)
}
}
Howto create importable script?
I just added the init function to the window so you can import the bundle script and call this function.
window.createShapeCanvas = createShapeCanvas
Future plans:
- add more models
- add more config options
- create a react component and publish to npm
Posted on July 27, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.