Beginning of the nonsense: Some 404 pages add simple interactive effects for fun. Here in pureJSSimple implementation similar to 404 jump obstacles page, all with the contentcanvasCanvas implementation.

1. Effect display

Two, picture dismantling

1. Map the horizon

The horizon here is simply a line running through the screen.

2. Draw a red Sprite

Drawing the red Sprite is divided into two parts:

(1) Top circle

(2) The tangent line between the lower fixed point and the upper circle.

Drawing result:

Fill the color, and then draw small and medium-sized circles. The drawing result is as follows:

(3) Draw obstacles

This is a black rectangle drawn here. The final result:

Three, logical disassembly

1. Global timer controls canvas repainting

Example Create a global timer.

It has two specific tasks:

(1) Global timed refresh reset, the canvas timed erase the previous drawing results.

(2) Global timer refresh animation redraw new content.

2. Sprite jumping

In the case of receiving the keyboard “space” click, let the Sprite jump a certain height, reach the peak of the time to fall, of course, the design here is uniform speed.

3. Obstacle movement

With the timer, the redrawn obstacle moves from the right to the left.

4. Collision detection

When the obstacle moves to the Sprite position, collision detection is performed to determine whether the left and right vertices of the top of the obstacle are inside the Sprite.

5. Draw prompts

The prompt language is also drawn with canvas, and will be judged when the obstacle has moved to the left. If there is no collision in the jump process, it shows “perfect jump ~”, if there is a collision in the jump process, it shows “keep trying”.

Iv. Code explanation

1, the HTML
<! DOCTYPEhtml>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<script src="./wsl404.js"></script>
	</head>
	<body>
		<div id="content">
			<canvas id="myCanvas">
			</canvas>
		</div>
	</body>
	<script>
		elves.init();
	</script>
</html>
Copy the code
2, JS

(function WSLNotFoundPage(window) {
	var elves = {};// Sprite object
	elves.ctx = null;/ / the canvas
	elves.width = 0;// Screen width
	elves.height = 0;// Screen height
	elves.point = null;// The center of the fairy circle
	elves.elvesR = 20;// Sprite circle radius
	elves.runloopTargets = [];// Mission sequence (save jump only for now)
	elves.upDistance = 50;// The current center position is the height from the ground
	elves.upDistanceInitNum = 50;// The initial height between the center position and the ground
	elves.isJumping = false;// Whether to jump
	elves.jumpTarget = null;// Jump missions
	elves.jumpTop = false;// Whether to jump to the highest point
	elves.maxCheckCollisionWith = 0;// The maximum width size for collision detection
	elves.obstaclesMovedDistance = 0;// The distance the obstacle moves
	elves.isCollisioned = false;// Whether there was a collision
	elves.congratulationFont = 13;// Celebrate text size
	elves.congratulationPosition = 40;// Celebrate text displacement
	elves.isShowCongratulation = false;// Whether to display the celebration text
	elves.congratulationContent = "The Perfect leap.";
	elves.congratulationColor = "red";
	
	/ / initialization
	elves.init = function(){
		this.drawFullScreen("content");
		this.drawElves(this.upDistance);
		this.keyBoard();   
		this.runloop();
	}
	
	// Keyboard click events
	elves.keyBoard = function(){
		var that = this;
		document.onkeydown = function whichButton(event)
		{
		  if(event.keyCode == 32) {/ / spacethat.elvesJump(); }}}// Start running laps
	elves.runloop = function(){
		var that = this;
		setInterval(function(){
			// Clear the canvas
			that.cleareAll();
			// Draw obstacles
			that.creatObstacles();
			if(that.isJumping == false) {// Redraw sprites without jumping
				that.drawElves(that.upDistanceInitNum);
			}
			// Draw the ground
			that.drawGround();
			
			// Jump the task
			for(index in that.runloopTargets){
				let target = that.runloopTargets[index];
				if(target.isRun ! =null && target.isRun == true) {if(target.runCallBack){ target.runCallBack(); }}}// Collision detection
			that.checkCollision();
			// Display the celebration text
			if(that.isShowCongratulation == true){ that.congratulation(); }},10);
	}
	
	/ / the canvas
	elves.drawFullScreen = function (id){
		var element = document.getElementById(id);
		this.height = window.screen.height - 200;
		this.width = window.screen.width;
		element.style.width = this.width + "px";
		element.style.height = this.height + "px";
		element.style.background = "white";
		this.getCanvas("myCanvas".this.width,this.height);
	}
	
	elves.getCanvas = function(id,width,height){
		var c = document.getElementById(id);
		this.ctx = c.getContext("2d");
		// Serrated
		if (window.devicePixelRatio) {
		   c.style.width = this.width + "px";
		   c.style.height = this.height + "px";
		   c.height = height * window.devicePixelRatio;
		   c.width = width * window.devicePixelRatio;
		   this.ctx.scale(window.devicePixelRatio, window.devicePixelRatio); }};// Draw the ground
	elves.drawGround = function() {
		// Set the color of the line
		this.ctx.strokeStyle = 'gray';
		// Set the width of the line
		this.ctx.lineWidth = 1;
		// Draw a line
		this.ctx.beginPath();
		/ / starting point
		this.ctx.moveTo(0.this.height / 2.0 + 1);
		/ / the end
		this.ctx.lineTo(this.width,this.height / 2.0);
		this.ctx.closePath();
		this.ctx.stroke();
	}
	
	// Draw sprites
	elves.drawElves = function(upDistance){
		
		/ / draw circle
		var angle = Math.acos(this.elvesR / upDistance);
		this.point = {x:this.width / 3.y : this.height / 2.0 - upDistance};
		this.ctx.fillStyle = "#FF0000";
		this.ctx.lineWidth = 1;
		this.ctx.beginPath();
		this.ctx.arc(this.point.x,this.point.y,this.elvesR,Math.PI / 2 + angle,Math.PI / 2 - angle,false);
		
		// Draw the tangent line
		var bottomPoint = {x:this.width / 3.y : this.point.y + this.upDistanceInitNum};
		
		let leftPointY = this.height / 2.0 - (upDistance - Math.cos(angle) * this.elvesR);
		let leftPointX = this.point.x - (Math.sin(angle) * this.elvesR);
		var leftPoint = {x:leftPointX,y:leftPointY};
		
		let rightPointY = this.height / 2.0 - (upDistance - Math.cos(angle) * this.elvesR);
		let rightPointX = this.point.x + (Math.sin(angle) * this.elvesR);
		var rightPoint = {x:rightPointX,y:rightPointY};
		
		this.maxCheckCollisionWith = (rightPointX - leftPointX) * 20 / (upDistance - Math.cos(angle) * this.elvesR);
		this.ctx.moveTo(bottomPoint.x, bottomPoint.y);
		this.ctx.lineTo(leftPoint.x,leftPoint.y);
		this.ctx.lineTo(rightPoint.x,rightPoint.y);
		
		this.ctx.closePath();
		this.ctx.fill();
		
		// Draw a small circle
		this.ctx.fillStyle = "#FFF";
		this.ctx.lineWidth = 1;
		this.ctx.beginPath();
		this.ctx.arc(this.point.x,this.point.y,this.elvesR / 3.0.Math.PI * 2.false);
		this.ctx.closePath();
		this.ctx.fill();
	}
	
	// Clear the canvas
	elves.cleareAll = function(){
		this.ctx.clearRect(0.0.this.width,this.height);
	}
	
	// The genie jumps
	elves.elvesJump = function(){
		if(this.isJumping == true) {return;
		}
		this.isJumping = true;
		if(this.jumpTarget == null) {var that = this;
			this.jumpTarget = {type:'jump'.isRun:true.runCallBack:function(){
				let maxDistance = that.upDistanceInitNum + 55;
				if(that.jumpTop == false) {if(that.upDistance > maxDistance){
						that.jumpTop = true;
					}
					that.upDistance += 1;
				} else if(that.jumpTop == true) {
					that.upDistance -= 1;
					if(that.upDistance < 50) {
						that.upDistance = 50;
						that.jumpTop = false;
						that.jumpTarget.isRun = false;
						that.isJumping = false;
					}
				}
				that.drawElves(that.upDistance);
			}};
			this.runloopTargets.push(this.jumpTarget);
		} else {
			this.jumpTarget.isRun = true; }}// Draw obstacles
	elves.creatObstacles = function(){
		let obstacles = {width:20.height:20};
		if(this.obstaclesMovedDistance ! =0) {this.ctx.clearRect(this.width - obstacles.width - this.obstaclesMovedDistance + 0.5.this.height / 2.0 - obstacles.height,obstacles.width,obstacles.height);
		}
		this.obstaclesMovedDistance += 0.5;
		if(this.obstaclesMovedDistance >= this.width + obstacles.width) {
			this.obstaclesMovedDistance = 0; 
			// Resets whether a collision occurs
			this.isCollisioned = false;
		}
		this.ctx.beginPath();
		this.ctx.fillStyle = "# 000";
		this.ctx.moveTo(this.width - obstacles.width - this.obstaclesMovedDistance, this.height / 2.0 - obstacles.height);
		this.ctx.lineTo(this.width - this.obstaclesMovedDistance,this.height / 2.0 - obstacles.height);
		this.ctx.lineTo(this.width - this.obstaclesMovedDistance,this.height / 2.0);
		this.ctx.lineTo(this.width - obstacles.width - this.obstaclesMovedDistance, this.height / 2.0);
		this.ctx.closePath();
		this.ctx.fill();
	}
	
	// Check for collisions
	elves.checkCollision = function(){
		var obstaclesMarginLeft = this.width - this.obstaclesMovedDistance - 20;
		var elvesUpDistance = this.upDistanceInitNum - this.upDistance + 20;
		if(obstaclesMarginLeft > this.point.x - this.elvesR && obstaclesMarginLeft < this.point.x + this.elvesR && elvesUpDistance <= 20) {
			// The maximum range to be detected
			let currentCheckCollisionWith = this.maxCheckCollisionWith * elvesUpDistance / 20;
			if((obstaclesMarginLeft < this.point.x + currentCheckCollisionWith / 2.0 && obstaclesMarginLeft > this.point.x - currentCheckCollisionWith / 2.0) || (obstaclesMarginLeft + 20 < this.point.x + currentCheckCollisionWith / 2.0 && obstaclesMarginLeft + 20 > this.point.x - currentCheckCollisionWith / 2.0)) {this.isCollisioned = true; }}// Record the obstacle moving to the left of the Sprite
		if(obstaclesMarginLeft + 20 < this.point.x - this.elvesR && obstaclesMarginLeft + 20 > this.point.x - this.elvesR - 1) {if(this.isCollisioned == false) {// If the jump succeeds, the score is set to true to prevent repetition within the detection range, and then set to false before the next loop
				this.isCollisioned = true;
				/ / to celebrate
				if(this.isShowCongratulation == false) {
					this.congratulationContent = "The Perfect leap.";
					this.congratulationColor = "red";
					this.isShowCongratulation = true; }}else {
				/ / to encourage
				if(this.isShowCongratulation == false) {
					this.isShowCongratulation = true;
					this.congratulationColor = "gray";
					this.congratulationContent = "Keep up the good work."; }}}}// Celebrate drawing text
	elves.congratulation = function(){
		
		this.congratulationFont += 0.1;
		this.congratulationPosition += 0.1;
		if(this.congratulationFont >= 30) {/ / reset
			this.congratulationFont = 13;
			this.congratulationPosition = 30;
			this.isShowCongratulation = false;
			return;
		}
		this.ctx.fillStyle = this.congratulationColor;        
		this.ctx.font = this.congratulationFont + 'px "Microsoft Yahei";        
		this.ctx.textBaseline = "bottom";         
		this.ctx.textAlign = "center"; 
		this.ctx.fillText( this.congratulationContent, this.point.x, this.height / 2.0 - this.upDistanceInitNum - this.congratulationPosition);   
	}
	
	window.elves = elves; }) (window)

Copy the code

Fifth, summary and thinking

Logic comments are basically written in the code, some of the calculations inside may be a little round. Bad code, don’t laugh [fist][fist][Fist]