JavaScript - PC side web page special effects

Posted by davidmuir on Mon, 07 Mar 2022 17:06:35 +0100

catalogue

1, Element offset offset series

1. offset overview

2. Common attributes

3. Difference between offset and style

Case - coordinates of mouse in box

Case - drag modal box

Case - Jingdong magnifying glass

2, Element viewable area client series

flexible source code analysis

Execute function now

pageshow event

3, Element scroll series

1. The page is rolled to the head

Case - imitation Taobao fixed right sidebar

 2. Page curled header compatibility scheme

4, Summary of three series

5, mouseenter and mouseover events

6, Animation function encapsulation

1. Animation implementation principle

2. Simple encapsulation of animation functions

3. The animation function records different timers for different elements

4. Jog effect animation

5. The animation function moves between multiple targets

6. Add callback parameters to animation functions

7. The animation function is encapsulated in a separate JS file

Case - right side box sliding

  

1, Element offset offset series

1. offset overview

Offset translates to offset. We can dynamically get the position (offset) and size of the element by using the relevant attributes of offset series.

  • Gets the location of the element from the parent element with the anchor
  • Get the size of the element itself
  • Note: all returned values do not have units

2. Common attributes

	<!-- offset position -->
	<style type="text/css">
		* {
			margin: 0;
			padding: 0;
		}

		.father {
			position: relative;
			width: 200px;
			height: 200px;
			background-color: pink;
			margin: 150px;
		}

		.son {
			width: 50px;
			height: 50px;
			background-color: blue;
			margin: 50px;
			padding: 10px;
			border: 2px solid red;
		}
	</style>
	<body>
		<div class="father">
			<div class="son">

			</div>
		</div>
		<script type="text/javascript">
			var father = document.querySelector('.father');
			var son = document.querySelector('.son');

			console.log(father.offsetTop);
			console.log(father.offsetLeft);
			//1. It is based on the father with positioning. If there is no father or father without positioning, it is based on the body
			console.log(son.offsetLeft);
			//2. You can get the size of the element. The width and height include padding+border+width
			console.log(son.offsetHeight);
			console.log(son.offsetWidth);
			//3. Return to the father with location. If not, return to the body
			console.log(son.offsetParent);
			console.log(son.parentNode);	//The return father is the father of the nearest level, whether there is positioning or not
		</script>
	</body>

3. Difference between offset and style

Case - coordinates of mouse in box

    <!-- Mouse coordinates in box -->
	<style type="text/css">
		.box {
			width: 200px;
			height: 200px;
			background-color: pink;
			margin: 100px 100px;
		}
	</style>
	<body>
		<div class="box"></div>
		<script type="text/javascript">
			var box = document.querySelector('.box');
			box.addEventListener('mousemove', function(e) {
				// console.log(e.pageX);
				// console.log(e.pageY);
				var x = e.pageX - this.offsetLeft;
				var y = e.pageY - this.offsetTop;
				this.innerHTML = 'x The coordinates are' + x + 'y The coordinates are' + y;
			})
		</script>
	</body>

Case - drag modal box

	<!-- Drag modal box -->
	<style type="text/css">
		.login-header {
			text-align: center;
		}

		a {
			margin: 0;
			padding: 0;
		}

		.login {
			display: none;
			width: 512px;
			height: 280px;
			position: fixed;
			border: 1px solid #EBEBEB;
			left: 50%;
			top: 50%;
			background-color: #FFFFFF;
			box-shadow: 0 0 20px #DDDDDD;
			z-index: 9999;
			transform: translate(-50%, -50%);
		}

		.login-title {
			width: 100%;
			margin: 10px 0 0 0;
			text-align: center;
			line-height: 40px;
			height: 40px;
			font-size: 18px;
			position: relative;
			cursor: move;
		}

		.login-input-content {
			margin-top: 20px;
		}

		.login-button {
			width: 50%;
			margin: 30px auto 0 auto;
			line-height: 40px;
			font-size: 14px;
			border: 1px solid #EBEBEB;
			text-align: center;
		}

		.login-bg {
			display: none;
			width: 100%;
			height: 100%;
			position: fixed;
			top: 0px;
			left: 0px;
			background-color: rgba(0, 0, 0, .3);
		}

		a {
			text-decoration: none;
			color: #000000;
		}

		.login-button a {
			display: block;
		}

		.login-input input.list-input {
			float: left;
			line-height: 35px;
			height: 35px;
			width: 350px;
			border: 1px solid #EBEBEB;
			text-indent: 5px;
		}

		.login-input {
			overflow: hidden;
			margin: 0 0 20px 0;
		}

		.login-input label {
			float: left;
			width: 90px;
			padding-right: 10px;
			text-align: center;
			line-height: 35px;
			height: 35px;
			font-size: 14px;
		}

		.login-title span {
			position: absolute;
			font-size: 12px;
			right: -20px;
			top: -30px;
			background-color: #FFFFFF;
			border: #EBEBEB solid 1px;
			width: 40px;
			height: 40px;
			border-radius: 20px;
		}
	</style>
	<body>
		<div class="login-header"><a id="link" href="javascript:;">Click to pop up the login box</a></div>
		<div id="login" class="login">
			<div id="title" class="login-title">Login member
				<span><a id="closeBtn" href="javascript:void(0);" class="close-login">close</a></span>
			</div>
			<div class="login-input-content">
				<div class="login-input">
					<label>user name:</label>
					<input type="text" name="info[username]" id="username" placeholder="enter one user name" class="list-input" />
				</div>
				<div class="login-input">
					<label>Login password:</label>
					<input type="password" placeholder="Please enter the login password" name="info[password]" id="password"
						class="list-input" />
				</div>
			</div>
			<div id="loginBtn" class="login-button"><a href="javascript:void(0);" id="login-button-submit">Sign in</a></div>
		</div>

		<!-- Covering layer -->
		<div id="bg" class="login-bg"></div>

		<script>
			//1. Get events
			var login = document.querySelector('.login');
			var mask = document.querySelector('.login-bg');
			var link = document.querySelector('#link');
			var closeBtn = document.querySelector('#closeBtn');
			var title = document.querySelector('#title');
			//2. Click pop-up to display login
			link.addEventListener('click', function() {
				mask.style.display = 'block';
				login.style.display = 'block';
			})
			//3. Click close
			closeBtn.addEventListener('click', function() {
				mask.style.display = 'none';
				login.style.display = 'none';
			})
			//4. Start dragging
			//(1) When the mouse is pressed, the coordinates of the mouse in the box are obtained
			title.addEventListener('mousedown', function(e) {
				var x = e.pageX - login.offsetLeft;
				var y = e.pageY - login.offsetTop;
				//(2) Mouse mobile, subtract the coordinates of the mouse in the box from the coordinates of the mouse in the page (unchanged)
				function move(e) {
					login.style.left = e.pageX - x + 'px';
					login.style.top = e.pageY - y + 'px';
				}
				document.addEventListener('mousemove', move);
				//(3) When the mouse pops up, the mouse movement event is removed
				document.addEventListener('mouseup', function() {
					document.removeEventListener('mousemove', move);
				})
			})
		</script>

Case - Jingdong magnifying glass

	<style type="text/css">
		* {
			margin: 0;
			padding: 0;
		}

		.preview_img {
			position: relative;
			border: 1px solid #CCCCCC;
			height: 400px;
			width: 400px;
		}

		.preview img {}

		.mask {
			display: none;
			position: absolute;
			top: 0;
			left: 0;
			height: 300px;
			width: 300px;
			background-color: #fede4f;
			border: 1px solid #CCCCCC;
			opacity: .5;
			cursor: move;
		}

		.big {
			display: none;
			position: absolute;
			top: 0;
			left: 410px;
			width: 500px;
			height: 500px;
			border: 1px solid #CCCCCC;
			overflow: hidden;
		}

		.big img {
			position: absolute;
			top: 0;
			left: 0;
		}
	</style>
	<body>
		<div class="preview_img">
			<img src="img/load.png" />
			<div class="mask">1</div>
			<div class="big">
				<img src="img/load-big.jpg" class="bigImg">
			</div>
		</div>
	</body>
	<script type="text/javascript">
		var preview_img = document.querySelector('.preview_img');
		var mask = document.querySelector('.mask');
		var big = document.querySelector('.big');
		//1. When the mouse passes the preview_img shows and hides mask occlusion layer and big box
		preview_img.addEventListener('mouseover', function() {
			mask.style.display = 'block';
			big.style.display = 'block';
		})
		preview_img.addEventListener('mouseout', function() {
			mask.style.display = 'none';
			big.style.display = 'none';
		})
		//2. Move the mouse and let the yellow box follow the mouse
		preview_img.addEventListener('mousemove', function(e) {
			//(1) First calculate the coordinates of the mouse in the box
			var x = e.pageX - this.offsetLeft;
			var y = e.pageY - this.offsetTop;
			//(2) Subtract the general height of the box to ensure that the mouse is in the middle
			var maskX = x - mask.offsetWidth / 2;
			var maskY = y - mask.offsetHeight / 2;
			//(3) The yellow box cannot be out of the small box range.
			//(3) . 1 if the x coordinate is less than 0, stop at the position of 0, which is greater than the width of the small box minus the width of the shielding layer
			//Maximum moving distance of shielding layer (square, same length and width)
			var maskMax = preview_img.offsetWidth - mask.offsetWidth;
			if (maskX < 0) {
				maskX = 0;
			} else if (maskX >= maskMax) {
				maskX = maskMax;
			}
			//(3) . 2 if the y coordinate is less than 0, stop at the position of 0, which is greater than the height of the small box minus the height of the shielding layer
			if (maskY < 0) {
				maskY = 0;
			} else if (maskY >= maskMax) {
				maskY = maskMax;
			}

			mask.style.left = maskX + 'px';
			mask.style.top = maskY + 'px';

			//Moving distance of large picture = moving distance of occlusion layer * maximum moving distance of large picture / maximum moving distance of occlusion layer
			var bigImg = document.querySelector('.bigImg');
			//Maximum moving distance of large picture
			var bigMax = bigImg.offsetWidth - big.offsetWidth;
			//Large picture moving distance bigX and bigY
			var bigX = maskX * bigMax / maskMax;
			var bigY = maskY * bigMax / maskMax;

			bigImg.style.left = -bigX + 'px';
			bigImg.style.top = -bigY + 'px';
		})
	</script>

2, Element viewable area client series

The border size and element size of the element can be dynamically obtained through the relevant attributes of the client series.

flexible source code analysis

(function flexible(window,document){
	// Get the root element of html
	var docEl=document.documentElement;
	// dpr pixel ratio
	var dpr=window.devicePixelRatio	|| 1;
	
	// Set the font size of the body
	function setBodyFontSize(){
		// If the page has a body element, set the text size of the body page
		if(document.body){
			document.body.style.fontSize=(12*dpr)+'px';
		}else{
			// If there is no body in the page, set the body font size after the main DOM elements of the page are loaded
			document.addEventListener('DOMContentLoaded',setBodyFontSize);
		}
	}
	setBodyFontSize();
	
	//Set the text size of html elements
	function setRumUnit(){
		var rem=docEl.clientWidth/10;
		docEl.style.fontSize=rem+'px';
	}
	setRumUnit();
	
	// When our page size changes, we need to reset the size of rem
	window.addEventListener('resize',setRumUnit());
	//pageshow enables us to reload the events triggered by the page
	window.addEventListener('pageshow',function(e){
		// e.persisted returns true, which means that if the page is taken from the buffer, the rem size also needs to be recalculated
		if(e.persisted){
			setRumUnit();
		}
	})
	
	// Some mobile terminals do not support 0.5 pixel writing
	if(dpr>=2){
		var fakeBody=document.createElement('body');
		var testElement=document.createElement('div');
		testElement.style.border='.5px solid transparent';
		fakeBody.appendChild(testElement);
		docEl.appendChild(fakeBody);
		if(testElement.offsetHeight===1){
			docEl.classList.add('hairlines')
		}
		docEl.removeChild('fakeBody')
	}
}(window,document))

Execute function now

  1. The immediate function does not need to be called and executes itself immediately
  2. You can also pass parameters
  3. When you create a local variable, there will be no local variable naming conflict. There will be no local variable naming conflict
//Create method
<script>
	(function(){})()
	(function(){}())
</script>
//You can also pass parameters
<script>
	(function sum(a,b){
		console.log(a+b);
	})(1,2)    //The second parenthesis can be regarded as a calling function and can pass parameters
</script>
//A scope is created independently, in which all variables are local variables, and there will be no naming conflict
<script>
	(function sum(a,b){
		var num=10;
	})();

	(function sum(a,b){
		var num=10;
	}())
</script>

pageshow event

3, Element scroll series

Using the relevant attributes of the scroll series, you can dynamically get the size and rolling distance of the element.

 

1. The page is rolled to the head

If the height (or width) of the browser is not enough to display the whole page, the scroll bar will appear automatically. When the scroll bar scrolls down, the height of the hidden top of the page is called the head of the page. The scroll bar triggers the onscroll event when scrolling

Case - imitation Taobao fixed right sidebar

  

 

    <style type="text/css">
		.slider-bar {
			position: absolute;
			left: 50%;
			top: 300px;
			margin-left: 600px;
			width: 45px;
			height: 130px;
			background-color: pink;
		}

		.w {
			width: 1200px;
			margin: 10px auto;
		}

		.header {
			height: 150px;
			background-color: lightgrey;
		}

		.banner {
			height: 400px;
			background-color: lightblue;
		}

		.main {
			height: 1000px;
			background-color: yellowgreen;
		}

		span {
			display: none;
			position: absolute;
			bottom: 0;
		}
	</style>
	<body>
		<div class="slider-bar">
			<span class="goBack">Back to top</span>
		</div>
		<div class="header w">Head area</div>
		<div class="banner w">banner region</div>
		<div class="main w">Main part</div>
	</body>
	<script type="text/javascript">
		var sliderbar = document.querySelector('.slider-bar');
		var banner = document.querySelector('.banner');
		
        //banner.offsetTop is the height of the roll, which should be written outside the scroll
		var bannerTop = banner.offsetTop;
		//The top value that should be maintained when our sidebar is fixed and positioned
		var sliderbarTop=sliderbar.offsetTop-bannerTop;
		
        //Get body element
		var main=document.querySelector('.main');
		var goBack=document.querySelector('.goBack');
		var mainTop=main.offsetTop;
		
		//2. Page scrolling events
		document.addEventListener('scroll', function() {
			//3. When the header of our page is larger than banner When offsettop, the sidebar becomes fixed positioning
			if (window.pageYOffset >= bannerTop) {
				sliderbar.style.position = "fixed";
				sliderbar.style.top=sliderbarTop+'px';
			} else {
				sliderbar.style.position = "absolute";
				sliderbar.style.top='300px';
			}
			
            //4. When the page scrolls to the main box, the goback module is displayed
			if (window.pageYOffset >= mainTop) {
				goBack.style.display="block";
			} else {
				goBack.style.display="none";
			}
		})
	</script>

 

 2. Page curled header compatibility scheme

  

4, Summary of three series

 

Main usage:

  1. The offset} series is often used to obtain the element position offsetLeft offsetTop
  2. The client} series is often used to obtain the element size clientWidth clientHeight
  3. Scroll is often used to obtain the scroll distance scrollTop scrollLeft
  4. Note that the scrolling distance of the page passes through the window Pagexoffset

 

5, mouseenter and mouseover events

  • mouseenter and mouseover events are triggered when the mouse moves over the element
  • When the mouseover mouse passes through its own box, it will be triggered, and when it passes through the sub box, it will also be triggered
  • mouseenter is triggered only through its own box
  • That's why mouseenter doesn't bubble
  • With mouseenter, the mouse leave event will not bubble

6, Animation function encapsulation

1. Animation implementation principle

Core principle: continuously move the box position through timer setInterval()

Implementation steps:

  1. Get the current box position
  2. Let the box add a pixel to its current position
  3. Use the timer to repeat this operation continuously
  4. Add end timer condition
  5. be careful! This element needs to add positioning

Common web effects cases

2. Simple encapsulation of animation functions

Note that you need to pass two parameters, the animated object and the distance to move

//Simple function encapsulation, obj target object, target target location
function animate(obj, target) {
	var timer = setInterval(function() {
		if (obj.offsetLeft >= target) {
			//Stop animation, stop timer
			clearInterval(timer);
		}
		obj.style.left = obj.offsetLeft + 1 + 'px';
	}, 30);
}

3. The animation function records different timers for different elements

    <body>
		<button type="button">go</button>
		<div></div>
		<span></span>
		<script type="text/javascript">
			//Simple function encapsulation, obj target object, target target location
			//When we keep clicking on the button, this element will be faster and faster. It should be that too many timers are turned on
			function animate(obj, target) {
				obj.timer = setInterval(function() {
					if (obj.offsetLeft >= target) {
						//Stop animation, stop timer
						clearInterval(obj.timer);
					}
					obj.style.left = obj.offsetLeft + 2 + 'px';
				}, 30);
			}

			var div = document.querySelector('div');
			var span = document.querySelector('span');
			var btn = document.querySelector('button');
			animate(div, 300);
			btn.addEventListener('click', function() {
				animate(span, 200);
			})
		</script>
	</body>

There is a bug in the above optimization: when we keep clicking the button, this element will be faster and faster. It should be that too many timers are turned on

function animate(obj, target) {
	//First clear the previous timer and only keep the current timer
	clearInterval(obj.timer);
	obj.timer = setInterval(function() {
		if (obj.offsetLeft >= target) {
			//Stop animation, stop timer
			clearInterval(obj.timer);
		}
		obj.style.left = obj.offsetLeft + 2 + 'px';
	}, 30);
}

Solution: clear the previous timer first and keep only the current timer

4. Jog effect animation

Jogging animation is to change the motion of elements.

Idea:

  1. Let the distance of each movement of the box slowly decrease, and the speed will slowly fall down
  2. Core algorithm: (target value - current position) / 10, as the step size of each movement
  3. Stop condition: stop the timer when the current box position is equal to the target position
  4. Note that the step value needs to be rounded
function animate(obj, target) {
	clearInterval(obj.timer);
	obj.timer = setInterval(function() {
		//The step value is written in the timer
		var step=(target-obj.offsetLeft)/10;
		if (obj.offsetLeft >= target) {
			clearInterval(obj.timer);
		}
		//Change each increment of 1 to slowly decrease, (target value - current position) / 10 as the step of each movement
		obj.style.left = obj.offsetLeft + step + 'px';
	}, 15);
}

5. The animation function moves between multiple targets

You can move animation functions from 800 to 500

When we click the button, we can judge whether the step is positive or negative

  1. If it is positive, the step size is rounded up.
  2. If it is negative, the step size is rounded down.
<body>
<button class="btn500">go500</button>
<button class="btn800">go800</button>
<div></div>
<span></span>
<script type="text/javascript">
	//Simple function encapsulation, obj target object, target target location
	//When we keep clicking on the button, this element will be faster and faster. It should be that too many timers are turned on
	function animate(obj, target) {
		clearInterval(obj.timer);
		obj.timer = setInterval(function() {
			//The step value is written in the timer
			// Change the step value to an integer to avoid reaching a fixed position
			// var step = Math.ceil((target - obj.offsetLeft) / 10);
			var step = (target - obj.offsetLeft) / 10;
			step = step > 0 ? Math.ceil(step) : Math.floor(step);
			if (obj.offsetLeft == target) {
				clearInterval(obj.timer);
			}
			//Change each increment of 1 to slowly decrease, (target value - current position) / 10 as the step of each movement
			obj.style.left = obj.offsetLeft + step + 'px';
		}, 15);
	}

	var div = document.querySelector('div');
	var span = document.querySelector('span');
	var btn500 = document.querySelector('.btn500');
	var btn800 = document.querySelector('.btn800');
	animate(div, 300);
	btn500.addEventListener('click', function() {
		animate(span, 500);
	})
	btn800.addEventListener('click', function() {
		animate(span, 800);
	})
</script>
</body>

6. Add callback parameters to animation functions

Callback function principle: function can be used as a parameter. Pass this function as a parameter to another function. After that function is executed, execute the passed function. This process is called callback.

Write position of callback function: the position where the timer ends.

<body>
<button class="btn500">go500</button>
<button class="btn800">go800</button>
<div></div>
<span></span>
<script type="text/javascript">
	//Simple function encapsulation, obj target object, target target location
	//When we keep clicking on the button, this element will be faster and faster. It should be that too many timers are turned on
	function animate(obj, target, callback) {
		// console.log(callback);// Equivalent to callback() when callback=function() {} is called
		clearInterval(obj.timer);
		obj.timer = setInterval(function() {
			//The step value is written in the timer
			// Change the step value to an integer to avoid reaching a fixed position
			// var step = Math.ceil((target - obj.offsetLeft) / 10);
			var step = (target - obj.offsetLeft) / 10;
			step = step > 0 ? Math.ceil(step) : Math.floor(step);
			if (obj.offsetLeft == target) {
				clearInterval(obj.timer);
				//The callback function is written in the timer
				if(callback){
					callback();
				}
			}
			//Change each increment of 1 to slowly decrease, (target value - current position) / 10 as the step of each movement
			obj.style.left = obj.offsetLeft + step + 'px';
		}, 15);
	}

	var div = document.querySelector('div');
	var span = document.querySelector('span');
	var btn500 = document.querySelector('.btn500');
	var btn800 = document.querySelector('.btn800');
	animate(div, 300);
	btn500.addEventListener('click', function() {
		animate(span, 500);
	})
	btn800.addEventListener('click', function() {
		animate(span, 800, function() {
			// alert('How are you ');
			span.style.backgroundColor='red';//Wait until the move is over
		});
	})
</script>
</body>

7. The animation function is encapsulated in a separate JS file

Because this animation function is often used in the future, it can be encapsulated in a JS file separately, and the JS file can be referenced when using it.

function animate(obj, target, callback) {
	// console.log(callback);// Equivalent to callback() when callback=function() {} is called
	clearInterval(obj.timer);
	obj.timer = setInterval(function() {
		//The step value is written in the timer
		// Change the step value to an integer to avoid reaching a fixed position
		// var step = Math.ceil((target - obj.offsetLeft) / 10);
		var step = (target - obj.offsetLeft) / 10;
		step = step > 0 ? Math.ceil(step) : Math.floor(step);
		if (obj.offsetLeft == target) {
			clearInterval(obj.timer);
			//The callback function is written in the timer
			if (callback) {
				callback();
			}
		}
		//Change each increment of 1 to slowly decrease, (target value - current position) / 10 as the step of each movement
		obj.style.left = obj.offsetLeft + step + 'px';
	}, 15);
}

Case - right side box sliding

<script src="js/animate.js" type="text/javascript" charset="utf-8"></script>

<style type="text/css">
	*{
		margin: 0;
		padding: 0;
	}
	.slider-bar{
		float: right;
		position: relative;
	}
	span{
		position: absolute;
		width: 40px;
		height: 40px;
		background-color: pink;
		right: 0;
		text-align: center;
	}
	.con{
		position: absolute;
		height: 40px;
		width: 200px;
		background-color: #0000FF;
		z-index: -1;
		text-align: left;
		right: -160px;
	}
</style>

<body>
	<div class="slider-bar">
		<span><-</span>
		<div class="con">Problem feedback</div>
	</div>
</body>

<script type="text/javascript">
	//1. Get element
	var sliderbar=document.querySelector('.slider-bar');
	var con=document.querySelector('.con');
	sliderbar.addEventListener('mouseenter',function(){
		animate(con,-160,function(){
			// When the animation is finished, point the left arrow to the right arrow
			sliderbar.children[0].innerHTML='->';
		});
	})
	sliderbar.addEventListener('mouseleave',function(){
		animate(con,0,function(){
			sliderbar.children[0].innerHTML='<-';
		});
	})
</script>

 

7, Common web effects cases

Case - Web carousel map

Rotation chart is also called focus chart

 

 

Topics: Javascript Front-end html css