特效描述:html5 canvas 行星运动 轨迹动画特效。html5运动轨迹,行星动画特效
代码结构
1. 引入JS
2. HTML代码
Your browser doesn't support canvas
/**
* Constants
*/
const TWO_PI = Math.PI * 2;
const ALLOWED_CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
/**
* Simple settings objects so we can easily mutate these values using dat.gui
* @type { {spawnMass: number, pauseWhileAiming: boolean, amountOfPredictions: number}}
*/
const settings = {
spawnMass: 25,
pauseWhileAiming: false,
amountOfPredictions: 200
};
/**
* Application Class
* The heart of the application and responsible for initializing all objects and updating/rendering them
*/
class Application {
/**
* Application constructor
*/
constructor() {
this.canvas = document.getElementById("canvas");
this.context = this.canvas.getContext("2d");
this.width = this.canvas.width = window.innerWidth;
this.height = this.canvas.height = window.innerHeight;
this.center = {
x: this.width / 2,
y: this.height / 2
};
this.solarSystem = new SolarSystem();
this.planetLauncher = new PlanetLauncher(this.canvas, this.solarSystem);
//Resize listener for the canvas to fill the browser window dynamically
window.addEventListener('resize', () => this.resizeCanvas(), false);
}
/**
* Simple resize function. Reinitializing everything on the canvas while changing the width/height
* @return {void}
*/
resizeCanvas() {
//Recalculate the width and height of the canvas and thus the center of the canvas as well
this.width = this.canvas.width = window.innerWidth;
this.height = this.canvas.height = window.innerHeight;
this.center = {
x: this.width / 2,
y: this.height / 2
};
this.reset();
}
/**
* Updates the application and every child of the application
* @return {void}
*/
update() {
if (settings.pauseWhileAiming === false) {
this.solarSystem.update();
} else if (settings.pauseWhileAiming === true && this.planetLauncher.isMouseDown === false) {
this.solarSystem.update();
}
this.planetLauncher.update();
}
/**
* Renders the application and every child of the application
* @return {void}
*/
render() {
//Clear the entire canvas to make it empty for the new render loop
this.context.clearRect(0, 0, this.width, this.height);
this.solarSystem.render(this.context);
this.planetLauncher.render(this.context);
}
/**
* Update and render the application at least 60 times a second
* @return {void}
*/
loop() {
this.update();
this.render();
window.requestAnimationFrame(() => this.loop());
}
/**
* Throw all planets away and initialize a whole new array of planets
* @return {void}
*/
reset() {
this.solarSystem.planets = [];
this.solarSystem.initializePlanets(this.center);
}
}
/**
* SolarSystem class
* Is responsible for maintaining and updating all of it's planets
*/
class SolarSystem {
/**
* SolarSystem constructor
*/
constructor() {
this.planets = [];
}
/**
* Initialize the planets container by filling it with Planet objects
* @param center - An object containing the x and y variables that describe the center of the canvas
* @return {void}
*/
initializePlanets(center) {
this.planets.push(new Planet(center.x, center.y, 0, 0, 200));
this.planets.push(new Planet(center.x, center.y - 150, 1.1, 0, 25));
this.planets.push(new Planet(center.x + 70, center.y - 90, 1.45, Math.PI, 25));
this.planets.push(new Planet(center.x - 180, center.y + 160, 1, Math.PI / 1.4, 25));
this.planets.push(new Planet(center.x - 150, center.y + 100, 1.1, Math.PI * 2.4, 75));
}
/**
* Updates the application and every child of the application
* @return {void}
*/
update() {
//Keep an array of all destroyed planets, because we don't want to mutate the planets array while calculating all values
let destroyedPlanets = [];
for (let i = 0; i < this.planets.length; i++) {
//If the planet collides with another planet, don't bother continuing the gravity calculations for this planet
if (SolarSystem.collidesWithAnotherPlanet(this.planets[i], this.planets) === true) {
destroyedPlanets.push(i);
continue;
}
//Calculate the total gravitational pull from all the other planets in the solar system
let gravitationalPull = SolarSystem.gravitationalPullFromOtherPlanets(this.planets[i], this.planets);
//Update the current planet by changing it's position based on it's velocity
this.planets[i].accelerate(gravitationalPull);
this.planets[i].update();
}
//Remove all planets that should be destroyed, because they've hit something during this update loop
for (let i = 0; i < destroyedPlanets.length; i++) {
this.planets.splice(destroyedPlanets[i], 1);
}
}
/**
* Renders the SolarSystem and every child of the application
* @param context - The context of the canvas t