The fifth day of learning JS BOM and DOM (Part 2)
1. Animation function
1.1 creep function
- The speed of movement is not uniform, but changes slowly
An example
- explain
- Achieve jog animation and can move between multiple values
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> div{ position: absolute; left: 0; top: 100px; width: 100px; height: 100px; background-color: pink; } </style> </head> <body> <button class="btn500">Mobile 500 px</button> <button class="btn800">Mobile 800 px</button> <div></div> <script> var div=document.querySelector('div'); // Encapsulate jog animation function function animateLow(obj,target){ clearInterval(obj.timer); obj.timer=setInterval(function(){ // The principle of slow movement is smaller and smaller // Moving distance = (target distance - current moving distance) / 10 var move=(target-obj.offsetLeft)/10; // Round the moving distance and take it in the larger direction // The moving distance is a negative number. Take it in the smaller direction move=move>=0 ? Math.ceil(move) : Math.floor(move); obj.style.left=obj.offsetLeft+move+'px'; // stop it if(obj.offsetLeft==target){ clearInterval(obj.timer); } },50); } var btn500=document.querySelector('.btn500'); var btn800=document.querySelector('.btn800'); btn500.addEventListener('click',function(){ animateLow(div,500); }); btn800.addEventListener('click',function(){ animateLow(div,800); }) </script> </body> </html>
- design sketch
Attention
- The jog movement distance is generally a floating point number and needs to be rounded (note that if the distance is positive - rounded up, the distance is negative - rounded down)
1.2 adding callback function to animation function
- Principle: a function can be used as a parameter to transfer the function to another function (as a formal parameter). After the execution of another function, the function as a formal parameter is executed. This process is called callback
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> div{ position: absolute; left: 0; top: 100px; width: 100px; height: 100px; background-color: pink; } </style> </head> <body> <button class="btn500">Mobile 500 px</button> <button class="btn800">Mobile 800 px</button> <div></div> <script> var div=document.querySelector('div'); // Encapsulate jog animation function // 2. Callback function // callback as the formal parameter of the function (representing the function) function animateLow(obj,target,callback){ clearInterval(obj.timer); obj.timer=setInterval(function(){ // Slow motion principle, the moving distance is getting smaller and smaller // Moving distance = (target distance - current moving distance) / 10 var move=(target-obj.offsetLeft)/10; // Round the moving distance and take it in the larger direction // The moving distance is a negative number. Take it in the smaller direction move=move>=0 ? Math.ceil(move) : Math.floor(move); obj.style.left=obj.offsetLeft+move+'px'; // stop it if(obj.offsetLeft==target){ clearInterval(obj.timer); // After the task of timer is completed // Execute callback function callback(); } },50); } var btn500=document.querySelector('.btn500'); var btn800=document.querySelector('.btn800'); btn500.addEventListener('click',function(){ animateLow(div,500); }); // The callback function is passed as a parameter btn800.addEventListener('click',function(){ animateLow(div,800,function(){ alert('Hello'); }); }) </script> </body> </html>
- design sketch
1.3 call after animation function encapsulation
- Encapsulated animation js
function animateLow(obj,target,callback){ clearInterval(obj.timer); obj.timer=setInterval(function(){ // Slow motion principle, the moving distance is getting smaller and smaller // Moving distance = (target distance - current moving distance) / 10 var move=(target-obj.offsetLeft)/10; // Round the moving distance and take it in the larger direction // The moving distance is a negative number. Take it in the smaller direction move=move>=0 ? Math.ceil(move) : Math.floor(move); obj.style.left=obj.offsetLeft+move+'px'; // stop it if(obj.offsetLeft==target){ clearInterval(obj.timer); // After the task of timer is completed // Execute callback function if(callback){ callback(); } } },15); }
- Call animation
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> .sliderbar{ width: 50px; height: 50px; position: absolute; right: 0; top: 300px; overflow: hidden; } .sliderbar span{ width: 50px; height: 50px; background-color: skyblue; position: absolute; left: 0; top: 0; z-index: 10; text-align: center; line-height: 50px; } .sliderbar div{ box-sizing: border-box; position: absolute; left: 0; top: 0; width: 200px; height: 50px; background-color: pink; padding-left: 30px; line-height: 50px; } </style> <script src="./01.Animation function.js"></script> </head> <body> <div class="sliderbar"> <span> ← </span> <div class="box">I am the content</div> </div> <script> var span=document.querySelector('span'); var div=document.querySelector('.box'); var sliderbar=document.querySelector('.sliderbar'); span.addEventListener('mouseenter',function(){ sliderbar.style.overflow='visible'; animateLow(div,-150,function(){ span.innerHTML='→'; }) }) span.addEventListener('mouseout',function(){ animateLow(div,0,function(){ span.innerHTML='←'; sliderbar.style.overflow='hidden'; }) }) </script> </body> </html>
- design sketch
2. Rotation chart
- thinking
Principle of seamless rotation
- Add an additional banner diagram (the first one) and put it at the end. When moving to the penultimate one, click the right slide button to execute:
- Animation transition from the penultimate to the last
- 1. After the execution, set the left of the large picture (all rotation pictures), so that the first picture of the large picture is replaced (the first picture is moved to the center of the rotation box) and the last one (the process does not need transition), which is invisible to the naked eye and seamless
- Principle of left slip
- Click the move left button for the first one
- Replace the first one with the last one (the same as the first one) (the last one moves to the center of the rotation box) (the process does not need transition)
- Realize the transition from the last one to the penultimate one
A case of rotating pictures
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> *{ margin: 0; padding: 0; } /* Rotation chart box */ .box{ width: 800px; height: 505px; background-color: pink; margin: 100px auto; position: relative; overflow: hidden; } /* Left arrow button */ .left{ width: 22px; height: 32px; position: absolute; left: 0; top: 50%; z-index: 1000 } /* Right arrow button */ .right{ width: 22px; height: 32px; position: absolute; right: 0; top: 50%; z-index: 1000; } /* The width and height of the left and right arrows are determined by the a box */ .right img, .left img{ width: 100%; height: 100%; } /* ul To set the width wide enough, you can put 4 small li in one line */ ul{ position: absolute; left: 0; top: 0; overflow: hidden; list-style: none; width: 600%; } /* The width of each li is 1 / 6 of ul */ ul li{ width: 800px; /* display: block; */ float: left; height: 100%; } /* Clickable range expansion */ ul li a{ display: block; width: 100%; height: 100%; } /* The picture is consistent with li width */ ul li a img{ display: block; width: 100%; height: 100%; } /* ol The rotation indicator is horizontally centered */ ol{ position: absolute; list-style: none; bottom: 15px; left: 50%; transform: translateX(-50%); background-color: rgba(255,255,255,.5); border-radius: 12px; z-index: 100; } ol li{ float: left; } ol li a{ display: block; margin: 6px; width: 12px; height: 12px; border-radius: 50%; /* ps */ border: 1px solid #fff; } /* Selected status */ ol li a.current{ display: block; margin: 6px; width: 12px; height: 12px; border-radius: 50%; /* ps */ background-color: #fff; } .clearfix::after, .clearfix::before{ content: ""; display: table; } .clearfix:after{ clear: both; } .clearfix{ *zoom: 1; } </style> </head> <body> <div class="box clearfix"> <a class="left" href="javascript:;"> <img src="./images/arrow-prev.png" alt=""> </a> <a class="right" href="javascript:;"> <img src="./images/arrow-next.png" alt=""> </a> <ul class="banner"> <li> <a href="javascript:;"> <img src="./images/focus.jpg" alt=""> </a> </li> <li> <a href="javascript:;"> <img src="./images/focus1.jpg" alt=""> </a> </li> <li> <a href="javascript:;"> <img src="./images/focus2.jpg" alt=""> </a> </li> <li> <a href="javascript:;"> <img src="./images/focus3.jpg" alt=""> </a> </li> </ul> <!-- Bottom rotation button section --> <ol class="circle"> </ol> </div> <script src="./16.Animation encapsulated into js file/01.Animation function.js"></script> <script> var left=document.querySelector('.left'); var right=document.querySelector('.right'); var box=document.querySelector('.box'); var timer=null; // Move the mouse into the banner diagram to display the left and right arrows box.addEventListener('mouseenter',function(){ left.style.display='block'; right.style.display='block'; clearInterval(timer); timer=null; }) // Move the mouse out of the banner diagram to hide the left and right arrows box.addEventListener('mouseleave',function(){ left.style.display='none'; right.style.display='none'; timer=setInterval(function(){ right.click(); },2000); }) var ul=document.querySelector('.banner'); var ol=document.querySelector('.circle'); // console.log(ul.children.length); // Number of round robin indicators generated for(var i=0;i<ul.children.length;i++){ var li=document.createElement('li'); var a=document.createElement('a'); a.href='#'; // Number of generated banner graphs // Subscript a in li of ol a.setAttribute('index',i); li.appendChild(a); ol.appendChild(li); } // Set the first small circle as selected ol.children[0].children[0].className='current'; // Clone the first li tag and put it at the end to realize seamless rotation var li1=ul.children[0].cloneNode(true); ul.appendChild(li1); // This is also an idea. There are two additional pictures // Clone the last tag to the front // var li2=ul.children[ul.children.length-2].cloneNode(true); // console.log(li2); // ul.insertBefore(li2,ul.children[0]); // Show second picture // ul.style.left=-ul.clientWidth/6+'px'; // Record the serial number of the current picture, starting from 0 var numr=0; // Click the rotation indicator, and the small circle of the indicator turns solid white ol.addEventListener('click',function(e){ var target=e.target; // Exclusive thought for(var i=0;i<ol.children.length;i++){ ol.children[i].children[0].className=''; } target.className='current'; // Realize the movement of pictures, that is, the movement of ul var index=target.getAttribute('index'); var step=index*ul.clientWidth/6; step=Math.ceil(step); // console.log(-step); animateLow(ul,-step); // Synchronous numr value numr=parseInt(index); }) // Left and right arrows move // The right button realizes right sliding right.addEventListener('click',function(){ // Detect when moving to the last one and quickly change to the first one if(numr===ul.children.length-1){ ul.style.left='0px'; numr=0; } // If it is the last one, realize the transition between the first one and the second one numr++; var step=numr*(ul.clientWidth/6); animateLow(ul,-step); console.log(numr); check(numr); }) // The left button realizes left sliding left.addEventListener('click',function(){ // If it's already the first one, slide left again // Move to the last one first if(numr===0){ numr=ul.children.length-1; ul.style.left=-(ul.clientWidth/6)*(numr)+'px'; } // Then switch between the last one and the penultimate one numr--; var step=numr*ul.clientWidth/6; animateLow(ul,-step); check(numr); }) // Cycle detection rotation chart button display function check(numr){ // Exclusive thought for(var i=0;i<ol.children.length;i++){ ol.children[i].children[0].className=''; } var circle; // Special case, 5 pictures, 1 repetition circle=numr; if(numr===-1){ circle=ul.children.length-2; }else if(numr===4){ circle=0; } // console.log(index); ol.children[circle].children[0].className='current'; // console.log(ol.children); } // Refresh the interface to enter once timer=setInterval(function(){ right.click(); },2000); </script> </body> </html>
- design sketch
3. Throttle valve
-
Objective: to prevent the rotation chart button from playing too fast due to continuous clicking
-
Purpose of throttle valve: when the animation content of a function is executed, the next animation function will be executed, so that the event cannot be triggered continuously
-
Core development idea: using callback function, add a variable control, lock function and unlock function
-
Specific steps
- Set a variable: var flag=true;
- If (flag) {flag = false; something} turn off the tap
- Using the callback function: after the animation is executed, turn on the faucet
Examples
- Prevent the right slide button from clicking too fast
var flag=true; right.addEventListener('click',function(){ if(flag){ // Turn off the tap flag=false; // Detect when moving to the last one and quickly change to the first one if(numr===ul.children.length-1){ ul.style.left='0px'; numr=0; } // If it is the last one, realize the transition between the first one and the second one numr++; var step=numr*(ul.clientWidth/6); // The callback function turns on the faucet animateLow(ul,-step,function(){ flag=true; }); console.log(numr); check(numr); } })
- design sketch
##4. Return to top case
- Scroll the window to a specific location in the document
window.scroll(x,y)
-
x. Y does not follow the unit, write the number directly (x,y represents the distance from the top)
-
x. When y is 0, return to the top
thinking
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> .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: purple; } .banner { height: 250px; background-color: skyblue; } .main { height: 1000px; background-color: yellowgreen; } span { display: none; position: absolute; bottom: 0; } </style> </head> <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> <script> // Get banner var banner=document.querySelector('.banner'); var sliderbar=document.querySelector('.slider-bar'); var bannerTop=banner.offsetTop; // Distance after fixed positioning var sliderTop=sliderbar.offsetTop-bannerTop; // Get main var main=document.querySelector('.main'); var mainTop=main.offsetTop; // Get back to top var goBack=document.querySelector('.goBack'); // When the page is rolled away by the offset top of the banner area, the scrolling navigation bar becomes a fixed unit document.addEventListener('scroll',function(){ if(window.pageYOffset>=bannerTop){ sliderbar.style.position='fixed'; sliderbar.style.top=sliderTop+'px'; }else{ sliderbar.style.position='absolute'; sliderbar.style.top='300px'; } if(window.pageYOffset>=mainTop){ goBack.style.display='block'; }else{ goBack.style.display='none'; } goBack.addEventListener('click',function(){ // window.scroll scrolls the window to the top // window.scroll(0,0); // 2. Use the jog function to return to the top with animation animateLow(window,0); }) function animateLow(obj,target,callback){ clearInterval(obj.timer); obj.timer=setInterval(function(){ // Slow motion principle, the moving distance is getting smaller and smaller // Moving distance = (target distance - current moving distance) / 10 var move=(target-obj.pageYOffset)/10; // Round the moving distance and take it in the larger direction // The moving distance is a negative number. Take it in the smaller direction move=move>=0 ? Math.ceil(move) : Math.floor(move); // obj.style.left=obj.offsetLeft+move+'px'; obj.scroll(0,move+obj.pageYOffset); // stop it if(obj.pageYOffset==target){ clearInterval(obj.timer); // After the task of timer is completed // Execute callback function if(callback){ callback(); } } },15); } }) </script> </body> </html>
- design sketch
5. Somersault cloud homepage case
- Train of thought analysis
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <style> * { margin: 0; padding: 0 } ul { list-style: none; } body { background-color: black; } .c-nav { width: 900px; height: 42px; background: #fff url(images/rss.png) no-repeat right center; margin: 100px auto; border-radius: 5px; position: relative; } .c-nav ul { position: absolute; } .c-nav li { float: left; width: 83px; text-align: center; line-height: 42px; } .c-nav li a { color: #333; text-decoration: none; display: inline-block; height: 42px; } .c-nav li a:hover { color: white; } .cloud { position: absolute; left: 0; top: 0; width: 83px; height: 42px; background: url(images/cloud.gif) no-repeat; } </style> <script src="./01.Animation function.js"></script> <script> window.addEventListener('load',function(){ var cloud=document.querySelector('.cloud'); var nav=document.querySelector('.c-nav'); // console.log(nav); // Get all small li // Use bubbling // nav.addEventListener('mouseover',function(e){ // var target=e.target; // console.log(target); // console.log(target.offsetLeft); // cloud.style.left=target.offsetLeft+'px'; // }) // Bubbling a and li are difficult to distinguish var list=nav.querySelectorAll('li'); var space=0; for(var i=0;i<list.length;i++){ // Move when passing list[i].addEventListener('mouseover',function(){ animateLow(cloud,this.offsetLeft); }); // Return to original value when leaving list[i].addEventListener('mouseout',function(){ animateLow(cloud,space); }) // Modify the default value of space when clicking list[i].addEventListener('click',function(){ space=this.offsetLeft; }) } }) </script> </head> <body> <div id="c_nav" class="c-nav"> <span class="cloud"></span> <ul> <li><a href="#"> home page news</a></li> <li><a href="#"> faculty</a></li> <li><a href="#"> Event Planning</a></li> <li><a href="#"> corporate culture</a></li> <li><a href="#"> Recruitment Information</a></li> <li><a href="#"> Company Profile</a></li> <li><a href="#"> I'm page</a></li> <li><a href="#"> what is page</a></li> </ul> </div> </body> </html>
- design sketch