First, technical thinking

Through F12’s observation of the Banner, the image is composed of multiple PNG images superimposed on each other. The deviation of the image is realized by monitoring the movement of the mouse, while the falling petals are realized by using canvas. Let’s give it a try.

Ii. Project directory structure

| bilibili - banner | | -- -- -- -- -- - the CSS style / / | + -- -- -- index. The CSS | | -- -- -- -- -- - | + image / / picture material -... | | -- -- -- -- -- - | js / / logic code + - index. Js | + -- -- - canvas. Js | | - index. The HTMLCopy the code

CSS styles and HTMl code

This part of the code is relatively simple and will not be repeated.

1. /css/index.css

* {margin: 0;
	padding: 0;
}
.bili-banner{
	margin: 0 auto;
    position: relative;
    z-index: 0;
	width: 100%;
	height: 9.375 vw;
    min-height: 155px;
    min-width: 999px;
    background-color: #f9f9f9;
    display: flex;
    justify-content: center;
}
.animated-banner{
	position: absolute;
	top: 0;
	bottom: 0;
	left: 0;
	right: 0;
	margin: auto;
	overflow: hidden;
}

.layer{
	position: absolute;
	left: 0;
	top: 0;
	height: 100%;
	width: 100%;
	display: flex;
	align-items: center;
	justify-content: center;
}

.layer img{
	transition: transform 0.2 s;
}
Copy the code

2. /index.html

<! DOCTYPEhtml>
<html>
	<head>
		<meta charset="utf-8">
		<title>Banner</title>
		<link href="css/index.css" rel="stylesheet" />
	</head>
	<body>
		<div class="bili-banner">
			<div class="animated-banner">
				<! Background - - - >
				<div class="layer">
					<img 
						src="image/bg1.png" 
						data-height="360" data-width="9666" height="180" width="4833" 
						style="transform: scale(1) translate(0px, -15px) rotate(0deg); opacity: 1;"
					>
				</div>
				<! - "zuoshangyi" -- >
				<div class="layer">
					<img 
						src="image/bg2.png" 
						data-height="360" data-width="9666" height="180" width="4833" 
						style="transform: scale(1) translate(1100px, 0px) rotate(0deg); opacity: 1;"
					>
				</div>
				<! Mountain - right - >
				<div class="layer">
					<img 
						src="image/bg3.png"
						data-height="360" data-width="3523" height="162" width="1585"
						style="transform: scale(1) translate(675px, 0px) rotate(0deg); opacity: 1;"
					>
				</div>
				<! - left the bridge -- -- >
				<div class="layer">
					<img 
						src="image/bg4.png"
						data-height="360" data-width="2938" height="176" width="1439"
						style="transform: scale(1) translate(-637px, 0px) rotate(0deg); opacity: 1;"
					>
				</div>
				<! - right - >
				<div class="layer">
					<img 
						src="image/bg5.png"
						data-height="139" data-width="556" height="62" width="250"
						style="Transform: scale(1) Translate (607.5px, 45px) Rotate (0deg); opacity: 1;"
					>
				</div>
				<! -->
				<div class="layer">
					<img 
						src="image/p4.png"
						data-height="302" data-width="734" height="84" width="205"
						style="Transform: scale(1) Translate (252px, 36.4px) Rotate (0deg); opacity: 0;"
					>
				</div>
				<! -- Middle lawn + tree -->
				<div class="layer">
					<img 
						src="image/bg6.png"
						data-height="180" data-width="1757" height="125" width="1229"
						style="transform: scale(1) translate(112px, 25px) rotate(0deg); opacity: 1;"
					>
				</div>
				<! -- Lawn + kite -->
				<div class="layer">
					<img 
						src="image/bg7.png"
						data-height="116" data-width="1757" height="81" width="1229"
						style="transform: scale(1) translate(-350px, 49px) rotate(0deg); opacity: 1;"
					>
				</div>
				<! - character - >
				<div class="layer">
					<img 
						src="image/p2.png"
						data-height="346" data-width="497" height="138" width="198"
						style="transform: scale(1) translate(-240px, 16px) rotate(0deg); opacity: 0;"
					>
				</div>
				<! - character - >
				<div class="layer">
					<img 
						src="image/p1.png"
						data-height="256" data-width="146" height="102" width="58"
						style="transform: scale(1) translate(-340px, 32px) rotate(0deg); opacity: 0;"
					>
				</div>
				<! - in the trees -- -- >
				<div class="layer">
					<img 
						src="image/t1.png"
						data-height="254" data-width="602" height="114" width="270"
						style="Transform: scale(1) Translate (-90px, 13.5px) Rotate (0deg); opacity: 1;"
					>
				</div>
				<! -- Middle lawn + tree -->
				<div class="layer">
					<img 
						src="image/bg8.png"
						data-height="360" data-width="4277" height="180" width="2138"
						style="transform: scale(1) translate(100px, 0px) rotate(0deg); opacity: 1;"
					>
				</div>
				<! -- Middle Character -->
				<div class="layer">
					<img 
						src="image/p3.png"
						data-height="327" data-width="933" height="147" width="419"
						style="Transform: scale(1) Translate (216px, 13.5px) Rotate (0deg); opacity: 1;"
					>
				</div>
				<! - the right tree -- -- >
				<div class="layer">
					<img 
						src="image/t3.png"
						data-height="353" data-width="740" height="211" width="444"
						style="transform: scale(1) translate(2100px, 0px) rotate(0deg); filter: blur(2px); opacity: 1;"
					>
				</div>
				<! - the left tree -- -- >
				<div class="layer">
					<img 
						src="image/t2.png"
						data-height="360" data-width="1916" height="180" width="958"
						style="transform: scale(1) translate(-1000px, 0px) rotate(0deg); filter: blur(1px); opacity: 1;"
					>
				</div>
				<canvas width="1519" height="155" style="position: absolute; top: 0px; left: 0px;" id="canvas"></canvas>
			</div>
		</div>
	</body>
	<script src="js/index.js"></script>
	<script src="js/canvas.js"></script>
	<script>.</script>
</html>

Copy the code

4. Monitor mouse movement to control picture translation

This part of the code is mainly in the /js/index.js file

1. Specific implementation ideas

  1. Get all. Layer nodes, which makes it easier to get img nodes
  2. The mouseEnter event that listens to the Banner records the value of the clientX mouse moved in
  3. Listen to the Mousemove event of the Banner to calculate the mouse movement distance in the X direction and call the image movement method move
  4. The mouseleave event that listens for the Banner clears the listener and calls the image reset method imgRest
  5. At this point, the banner is realized by mouse movement to control the picture pan
  6. The specific movA and imgRest methods actually change the transform and opacity implementation in the style of the corresponding image
  7. A utility function GetTranslate is involved to get the original movement distance of the image
  8. Note: There is no code simplification for everyone to understand

2. /js/index.js

let banner = document.querySelector('.bili-banner');
let layers = document.getElementsByClassName('layer');

let overX = 0;// The mouse cursor moves in the x coordinate
let leaveX = 0;// The x coordinate when the mouse moves out

// Mouse over
banner.addEventListener('mouseenter'.event= >{
	event.preventDefault();
	overX = event.clientX;
})

// Mouse over
banner.addEventListener('mouseleave'.event= >{
	event.preventDefault();
	leaveX = event.clientX;
	removeEventListener("mousemove",move);
	// The image is reset
	imgRest();
})

// Mouse movement
banner.addEventListener('mousemove',move);

// Mouse movement distance
function move(e){
	e.preventDefault();
	let startX = overX; 
	let endX = e.clientX;
	let moveX = startX-endX;
	// Move the image
	imgMove(moveX);
}

/ / 0
let img0 = layers[0].children[0];
let img0StartX = GetTranslate(img0,'x');
/ / 1
let img1 = layers[1].children[0];
let img1StartX = GetTranslate(img1,'x');
/ / 2
let img2 = layers[2].children[0];
let img2StartX = GetTranslate(img2,'x');
/ / 3
let img3 = layers[3].children[0];
let img3StartX = GetTranslate(img3,'x');
/ / 4
let img4 = layers[4].children[0];
let img4StartX = GetTranslate(img4,'x');
/ / 5 lead ship
let img5 = layers[5].children[0];
let img5StartX = GetTranslate(img5,'x');
/ / 6
let img6 = layers[6].children[0];
let img6StartX = GetTranslate(img6,'x');
/ / 7
let img7 = layers[7].children[0];
let img7StartX = GetTranslate(img7,'x');
//8
let img8 = layers[8].children[0];
let img8StartX = GetTranslate(img8,'x');
//9 hero kite 2
let img9 = layers[9].children[0];
let img9StartX = GetTranslate(img9,'x');
/ / 10
let img10 = layers[10].children[0];
let img10StartX = GetTranslate(img10,'x');
/ / 11
let img11 = layers[11].children[0];
let img11StartX = GetTranslate(img11,'x');
/ / 12
let img12 = layers[12].children[0];
let img12StartX = GetTranslate(img12,'x');
/ / 13
let img13 = layers[13].children[0];
let img13StartX = GetTranslate(img13,'x');
/ / 14
let img14 = layers[14].children[0];
let img14StartX = GetTranslate(img14,'x');

// Move the image
function imgMove(moveX){
	/ / the background
	img0.style.transform = "scale(1) translate("+(img0StartX+moveX*0.1) +"px, -15px) rotate(0deg)";
	/ / "zuoshangyi"
	img1.style.transform = "scale(1) translate("+(img1StartX+moveX*0.1) +"px, 0px) rotate(0deg)";
	/ / right mountain
	img2.style.transform = "scale(1) translate("+(img2StartX+moveX*0.03) +"px, 0px) rotate(0deg)";
	/ / left bridge
	img3.style.transform = "scale(1) translate("+(img3StartX+moveX*0.11) +"px, 0px) rotate(0deg)";
	/ / right the ship
	img4.style.transform = "scale(1) translate("+(img4StartX+moveX*0.1) +"px, 45px) rotate(0deg)";
	// Medium lawn + tree
	img6.style.transform = "scale(1) translate("+(img6StartX+moveX*0.5) +"px, 25px) rotate(0deg)";
	// Medium lawn + kite
	img7.style.transform = "scale(1) translate("+(img7StartX+moveX*0.5) +"px, 49px) rotate(0deg)";
	/ / in the tree
	img10.style.transform = "scale(1) translate("+(img10StartX+moveX*1) +"13.5 px, px) rotate (0 deg)";
	// Medium lawn + tree
	img11.style.transform = "scale(1) translate("+(img11StartX+moveX*1) +"px, 0px) rotate(0deg)";
	/ / in the figure
	img12.style.transform = "scale(1) translate("+(img12StartX+moveX*1) +"13.5 px, px) rotate (0 deg)";
	/ / right tree
	img13.style.transform = "scale(1) translate("+(img13StartX+moveX*1.5) +"px, 0px) rotate(0deg)";
	/ / the left tree
	img14.style.transform = "scale(1) translate("+(img14StartX+moveX*1.5) +"px, 0px) rotate(0deg)";
	// Character display
	if(moveX < 200){
		img5.style.transform = "scale(1) translate("+(img5StartX-moveX*0.25) +"36.4 px, px) rotate (0 deg)";
		img5.style.opacity = 1;
		img8.style.opacity = 0;
		img9.style.opacity = 0;
	}else{
		img8.style.transform = "scale(1) translate("+(img8StartX+moveX*0.2) +"px, 16px) rotate(0deg)";
		img9.style.transform = "scale(1) translate("+(img9StartX+moveX*0.4) +"px, 32px) rotate(0deg)";
		img5.style.opacity = 0;
		img8.style.opacity = 1;
		img9.style.opacity = 1; }}// The image is reset
function imgRest(){
	img0.style.transform = "scale(1) translate("+(img0StartX)+"px, -15px) rotate(0deg)";
	img1.style.transform = "scale(1) translate("+(img1StartX)+"px, 0px) rotate(0deg)";
	img2.style.transform = "scale(1) translate("+(img2StartX)+"px, 0px) rotate(0deg)";
	img3.style.transform = "scale(1) translate("+(img3StartX)+"px, 0px) rotate(0deg)";
	img4.style.transform = "scale(1) translate("+(img4StartX)+"px, 45px) rotate(0deg)";
	img5.style.transform = "scale(1) translate("+(img5StartX)+"36.4 px, px) rotate (0 deg)";
	img6.style.transform = "scale(1) translate("+(img6StartX)+"px, 25px) rotate(0deg)";
	img7.style.transform = "scale(1) translate("+(img7StartX)+"px, 49px) rotate(0deg)";
	img8.style.transform = "scale(1) translate("+(img8StartX)+"px, 16px) rotate(0deg)";
	img9.style.transform = "scale(1) translate("+(img9StartX)+"px, 32px) rotate(0deg)";
	img10.style.transform = "scale(1) translate("+(img10StartX)+"13.5 px, px) rotate (0 deg)";
	img11.style.transform = "scale(1) translate("+(img11StartX)+"px, 0px) rotate(0deg)";
	img12.style.transform = "scale(1) translate("+(img12StartX)+"13.5 px, px) rotate (0 deg)";
	img13.style.transform = "scale(1) translate("+(img13StartX)+"px, 0px) rotate(0deg)";
	img14.style.transform = "scale(1) translate("+(img14StartX)+"px, 0px) rotate(0deg)";
	// The characters are hidden
	img5.style.opacity = 0;
	img8.style.opacity = 0;
	img9.style.opacity = 0;
}

// get the x offset
function GetTranslate(node, sty) {
    var translates = document.defaultView.getComputedStyle(node, null).transform.substring(7);
	var result = translates.match(((/ \ [^)] *) \] /);// Re the () content
	var matrix = result ? result[1].split(', ') : translates.split(', ');
	if (sty == "x" || sty == undefined) {
	    return matrix.length > 6 ? parseFloat(matrix[12) :parseFloat(matrix[4]);
	} else if (sty == "y") {
	    return matrix.length > 6 ? parseFloat(matrix[13) :parseFloat(matrix[5]);
	} else if (sty == "z") {
	    return matrix.length > 6 ? parseFloat(matrix[14) :0;
	} else if (sty == "rotate") {
	    return matrix.length > 6 ? getRotate([parseFloat(matrix[0]), parseFloat(matrix[1]), parseFloat(matrix[4]), parseFloat(matrix[5])]) : getRotate(matrix); }}Copy the code

Five, petals fall to achieve

This part of the code is mainly in /js/canvas.js

1. Specific implementation ideas

  1. Get the Canva node and getContext
  2. The loading method loads image resources
  3. Define the petal class Flower
  4. Set the basic properties of Flower and the render method draw and the fall method updata
  5. CreateFlower Creates a specified number of petals
  6. The allDraw method renders all the inner petals of the screen
  7. The utility function RAND is used to generate random numbers
  8. Petals are cleared as they fall out of the frame
  9. Petal position, velocity and size are randomly generated
  10. Call the relevant method in index.html and start the timer

2./js/canvas.js

let canvas = document.querySelector('#canvas');
let ctx = canvas.getContext('2d');
let sw = canvas.width;
let sh = canvas.height;
let imgs = {
	"f1": 'image/f1.png'."f2": 'image/f2.png'};// Image loading
function loading() {
	// Total number of resources
	let AllAmount = Object.keys(imgs).length;
	// The number of loaded resources
	let count = 0;

	for (k in imgs) {
		// Image address
		let src = imgs[k]
		// Create the image
		imgs[k] = new Image()
		// Assign the image address
		imgs[k].src = src;
		imgs[k].onload = function() {
			count++;
			if(count == AllAmount) { start(); }}}}// Define the petal class
class Flower {
	constructor(img, x, y, w, h) {
		this.img = img;
		this.x = x;
		this.y = y;
		this.w = w;
		this.h = h;
		this.del = false;
	}
	/ / rendering
	draw() {
		ctx.drawImage(this.img, this.x, this.y, this.w, this.h);
	}
	/ / the falling
	updata() {
		if (this.x > sw || this.y > sh) {
			this.del = true;
		}else{
			this.del = false;
		}
		this.x += Math.random() * 3 + 1;
		this.y += Math.random() * 3 + 1; }}let fs = [];
// Create petals
function createFlower() {
	let wh = rand(0.15);
	let flower = null;
	if(fs.length<35) {if (rand(0.10) > 5) {
			flower = new Flower(imgs['f1'], rand(20, sw - 20), rand(0.10), wh, wh);
		} else {
			flower = new Flower(imgs['f2'], rand(20, sw - 20), rand(0.10), wh, wh); } fs.push(flower); }}/ / rendering
function allDraw(){
	for (i = 0; i < fs.length; i++) {
		let flower = fs[i];
		if(flower.del){		
			fs.splice(i,1);
			i--;
			continue; } flower.draw(); flower.updata(); }}/ / random number
function rand(min, max) {
	return Math.round(Math.random() * (max - min) + min);
}
Copy the code

3./index.html

<! DOCTYPEhtml>
<html>
	<head>
		<meta charset="utf-8">
		<title>Banner</title>
		<link href="css/index.css" rel="stylesheet" />
	</head>
	<body>
		<div class="bili-banner">
			<div class="animated-banner">
				<! Background - - - >
				<div class="layer">
					<img 
						src="image/bg1.png" 
						data-height="360" data-width="9666" height="180" width="4833" 
						style="transform: scale(1) translate(0px, -15px) rotate(0deg); opacity: 1;"
					>
				</div>
				<! - "zuoshangyi" -- >
				<div class="layer">
					<img 
						src="image/bg2.png" 
						data-height="360" data-width="9666" height="180" width="4833" 
						style="transform: scale(1) translate(1100px, 0px) rotate(0deg); opacity: 1;"
					>
				</div>
				<! Mountain - right - >
				<div class="layer">
					<img 
						src="image/bg3.png"
						data-height="360" data-width="3523" height="162" width="1585"
						style="transform: scale(1) translate(675px, 0px) rotate(0deg); opacity: 1;"
					>
				</div>
				<! - left the bridge -- -- >
				<div class="layer">
					<img 
						src="image/bg4.png"
						data-height="360" data-width="2938" height="176" width="1439"
						style="transform: scale(1) translate(-637px, 0px) rotate(0deg); opacity: 1;"
					>
				</div>
				<! - right - >
				<div class="layer">
					<img 
						src="image/bg5.png"
						data-height="139" data-width="556" height="62" width="250"
						style="Transform: scale(1) Translate (607.5px, 45px) Rotate (0deg); opacity: 1;"
					>
				</div>
				<! -->
				<div class="layer">
					<img 
						src="image/p4.png"
						data-height="302" data-width="734" height="84" width="205"
						style="Transform: scale(1) Translate (252px, 36.4px) Rotate (0deg); opacity: 0;"
					>
				</div>
				<! -- Middle lawn + tree -->
				<div class="layer">
					<img 
						src="image/bg6.png"
						data-height="180" data-width="1757" height="125" width="1229"
						style="transform: scale(1) translate(112px, 25px) rotate(0deg); opacity: 1;"
					>
				</div>
				<! -- Lawn + kite -->
				<div class="layer">
					<img 
						src="image/bg7.png"
						data-height="116" data-width="1757" height="81" width="1229"
						style="transform: scale(1) translate(-350px, 49px) rotate(0deg); opacity: 1;"
					>
				</div>
				<! - character - >
				<div class="layer">
					<img 
						src="image/p2.png"
						data-height="346" data-width="497" height="138" width="198"
						style="transform: scale(1) translate(-240px, 16px) rotate(0deg); opacity: 0;"
					>
				</div>
				<! - character - >
				<div class="layer">
					<img 
						src="image/p1.png"
						data-height="256" data-width="146" height="102" width="58"
						style="transform: scale(1) translate(-340px, 32px) rotate(0deg); opacity: 0;"
					>
				</div>
				<! - in the trees -- -- >
				<div class="layer">
					<img 
						src="image/t1.png"
						data-height="254" data-width="602" height="114" width="270"
						style="Transform: scale(1) Translate (-90px, 13.5px) Rotate (0deg); opacity: 1;"
					>
				</div>
				<! -- Middle lawn + tree -->
				<div class="layer">
					<img 
						src="image/bg8.png"
						data-height="360" data-width="4277" height="180" width="2138"
						style="transform: scale(1) translate(100px, 0px) rotate(0deg); opacity: 1;"
					>
				</div>
				<! -- Middle Character -->
				<div class="layer">
					<img 
						src="image/p3.png"
						data-height="327" data-width="933" height="147" width="419"
						style="Transform: scale(1) Translate (216px, 13.5px) Rotate (0deg); opacity: 1;"
					>
				</div>
				<! - the right tree -- -- >
				<div class="layer">
					<img 
						src="image/t3.png"
						data-height="353" data-width="740" height="211" width="444"
						style="transform: scale(1) translate(2100px, 0px) rotate(0deg); filter: blur(2px); opacity: 1;"
					>
				</div>
				<! - the left tree -- -- >
				<div class="layer">
					<img 
						src="image/t2.png"
						data-height="360" data-width="1916" height="180" width="958"
						style="transform: scale(1) translate(-1000px, 0px) rotate(0deg); filter: blur(1px); opacity: 1;"
					>
				</div>
				<canvas width="1519" height="155" style="position: absolute; top: 0px; left: 0px;" id="canvas"></canvas>
			</div>
		</div>
	</body>
	<script src="js/index.js"></script>
	<script src="js/canvas.js"></script>
	<script>
		let timer = null;
		window.onload = () = >{
			loading();
		}
		function start(){
			timer = setInterval(begin,1000/60)}function begin(){
			ctx.clearRect(0.0,sw,sh);
			createFlower();
			allDraw();
		}
	</script>
</html>
Copy the code

Five, the end

At this point, the development and implementation of the Bilibili website header dynamic Banner has been completed

Demo video of this article: Click browse

More front-end content welcome to pay attention to the public number: day small day personal network