整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          深入css布局—定位與浮動

          css知識體系中,除了css選擇器,樣式屬性等基礎(chǔ)知識外,css布局相關(guān)的知識才是css比較核心和重要的點(diǎn)。今天我們來深入學(xué)習(xí)一下css布局相關(guān)的知識。

          一、定位與浮動

          不同類型元素的特點(diǎn)你們了解嘛?我們可以隨意的排列組合他們來達(dá)到我們想要的效果。但是他們都是基于一個二維平面的,如果我們想在布局中有遮擋,重疊之類的更豐富效果,我們就需要使用到定位和浮動的相關(guān)知識。喜歡小編的伙伴可以從評論區(qū)一起討論學(xué)習(xí)!

          1 文檔流

          文檔流就是按照頁面元素書寫的順序,將頁面元素按從左到右,從上至下的一般順序進(jìn)行排列。那么也就可以理解成我們剛才所說的一個二維平面的概念。

          那么如果我想要實(shí)現(xiàn)更豐富的效果,就需要脫離文檔流,在一個新的平面上去顯示,這樣我們就可以在屏幕上有多個平面疊加顯示的效果了,那么這就是浮動和定位的工作了。

          1.2 包含塊

          包含塊就是個專有名詞,其實(shí)概念很簡單,這里了解一下就好。

          包含塊是一個矩形區(qū)域,當(dāng)元素設(shè)置屬性的百分比的時候,比如width:50% 或者 top: 10%,其參考系就是他的包含塊。

          大部分時候?qū)τ谖臋n流里的元素,其包含塊指的都是其父元素的區(qū)域。

          對于定位元素來說,相對定位元素包含塊也是其父元素區(qū)域;

          絕對定位元素的包含塊是其帶有position為非static的祖先元素區(qū)域。如果其沒有這樣的祖先元素的話其包含塊為首屏顯示區(qū)域,這個區(qū)域也有個專有名詞叫做初級包含塊。

          固定定位元素的包含塊就是當(dāng)前可視區(qū)的區(qū)域。

          1.3 定位

          定位允許你使用 position 屬性,將一個元素相對于他自己或者他的祖先元素甚至是瀏覽器窗口通過 top , left , right , bottom 屬性進(jìn)行偏移。

          根據(jù) position 屬性的取值,元素可以分為靜態(tài)定位元素static(默認(rèn)值)、相對定位元素relative、絕對定位元素absoute和固定定位元素fixed。

          首先我們拋開static這個默認(rèn)值,因?yàn)樗静粚儆诙ㄎ坏姆懂?,因?yàn)樵啬J(rèn)就是static,他就相當(dāng)于是依據(jù)文檔流顯示。

          當(dāng)我們使用定位時,需要position屬性和top,left,right,bottom這兩類屬性共同參與來決定一個元素的 定位類型 和 偏移量 。

          使用方法很簡單,這里說下他們之間的區(qū)別:

          relative相對定位

          元素根據(jù)其在當(dāng)前文檔流所在位置作為參考系,進(jìn)行偏移。

          定位之后原來元素在文檔流中的位置會被空出來,不會被其他元素所占據(jù)。

          absolute絕對定位

          元素會將其帶有position為非static的祖先元素作為參考系進(jìn)行偏移。

          如果祖先元素里沒有帶有position為非static的,則會以首屏作為參考系。

          定位后,原來在文檔流中占據(jù)的位置,會被其他元素所占據(jù)。

          fixed固定定位

          根據(jù)當(dāng)前可視區(qū)進(jìn)行定位,所以當(dāng)文檔流為多屏可滾動時,fixed定位的元素會跟隨滾動而滾動。

          跟absolute定位一樣,定位后,原來在文檔流中占據(jù)的位置,會被其他元素所占據(jù)。

          1.4 浮動

          浮動允許你將元素浮動起來,脫離文檔流向左或者向右移動。直到它的外邊緣碰到包含框或另一個浮動框的邊框?yàn)橹埂?/p>

          雖然浮動也脫離文檔流顯示,但是與定位不同的是 inline 和 inline-block 的元素可以識別這種因浮動而脫離的文檔流,從而不發(fā)生重疊。

          <!DOCTYPE html>

          <html>

          <head>

          <meta charset="UTF-8">

          <title>Document</title>

          <style>

          * {

          margin: 0;

          padding: 0;

          }

          .float {

          width: 40px;

          height: 40px;

          background: blue;

          float: left;

          }

          p{

          display: inline-block;

          width: 100px;

          height: 100px;

          background: red;

          }

          </style>

          </head>

          <body>

          <div></div>

          <p>LearnInPro LearnInPro LearnInPro</p>

          </body>

          </html>

          我們會發(fā)現(xiàn)p元素并沒有占據(jù)掉浮動元素的位置,然后我們將上面的代碼稍作修改,將p元素的display改為block我們就會發(fā)現(xiàn)

          雖然這樣p標(biāo)簽占據(jù)了float元素的位置,但是標(biāo)簽里面的文本則不會去占據(jù)float元素的位置。

          這個設(shè)定其實(shí)是有些詭異的。另外說一句,在css歷史上浮動這個東西一開始被造出來是為了實(shí)現(xiàn)文字圍繞圖片這種效果的而不是用來做布局的,當(dāng)時只有圖片可以設(shè)置浮動效果,但是后來慢慢所有元素都可以浮動并且基于浮動有了自己的布局體系,所有由于歷史原因相對來說浮動的規(guī)則是比較亂的小部分還有些詭異的。有些地方我們記住就好。

          我們來具體看下浮動的規(guī)則:浮動元素會從最后一行最左側(cè)的空白位置開始浮動,如當(dāng)前行無法容納下自己寬度,則垂直下沉到下一行,向左或者向右碰到包含框或另一個浮動框的邊框?yàn)橹?。我們這里舉兩個例子:

          <!DOCTYPE html>

          <html>

          <head>

          <meta charset="UTF-8">

          <title>Document</title>

          <style>

          .float{

          width: 30%;

          height: 40px;

          border: 1px solid black;

          float: left;

          }

          </style>

          </head>

          <body>

          <div>flaot1</div>

          <div style="height: 60px;">flaot2</div>

          <div>flaot3</div>

          <div>flaot4</div>

          <!--<div style="width: 10px;">flaot5</div>-->

          </body>

          </html>

          這里float4在float3右側(cè)空白位置起始,發(fā)現(xiàn)當(dāng)前行無法容納下自己則垂直向下到下一行,向左移動,在碰到包含塊之前,碰到了float2的邊框,于是就會在float2的右邊框處停止浮動。

          之后我們將代碼稍作修改,把float5這行注釋刪掉,我們會發(fā)現(xiàn),一開始float5的起始位置就是在float4這行的右側(cè)空白區(qū)域,當(dāng)前行可容納下自己,于是就停在了float4的右側(cè)。雖然第一行也就是float3這行右側(cè)空白區(qū)域也空著,可以放得下float5,但是float5的起始位置并不會在第一行,所以最終即使第一行有位置可以顯示下float5,它也不會在那里顯示。

          1.4 清除浮動

          首先為啥要清除浮動?

          由于浮動元素會脫離文檔流顯示,所以在浮動元素后面的塊級元素會默認(rèn)占據(jù)這些元素的位置,就會造成這些塊級元素會在浮動元素的下層顯示,出現(xiàn)浮動元素蓋住后面正常文檔流元素的效果,但這往往不是我們想要的結(jié)果。

          其作用是改變 使用清除浮動的這個元素 與 前一個聲明的浮動元素 之間的默認(rèn)布局規(guī)則,讓 使用清除浮動的這個元素 在新的一行中顯示。

          如何清除浮動

          clear屬性,其值為left | right | both。

          浮動元素或者非浮動元素的塊級元素都可以使用這個屬性來清除浮動(我們之前說inline和inline-block元素可以自動識別浮動,所以他們不需要清除浮動), 他們的作用對象是前一個聲明的浮動元素。如果使用 clear:left | right 則是清除前一個float為left或者right的元素的浮動,clear:both則是清除前一個浮動元素,無論它是向哪邊移動。那么使用clear屬性的元素會在浮動元素的下方新開一行顯示。

          清除浮動的特殊應(yīng)用

          清除浮動可以解決父元素高度塌陷問題。當(dāng)一個元素包裹了一些float元素的時候,由于float元素脫離文檔流顯示,所以父元素?zé)o法被這些元素?fù)伍_高度,導(dǎo)致父元素高度為0。

          那么最常用的一種解決方案是:設(shè)置父元素的after偽元素的clear屬性 來讓其撐開父元素的高度。

          <!DOCTYPE html>

          <html>

          <head>

          <meta charset="UTF-8">

          <title>Document</title>

          <style>

          .clearfix {

          background: gray;

          border: 1px solid black;

          }

          .float {

          width: 200px;

          height: 100px;

          background: red;

          float: left;

          }

          .clearfix:after,

          .clearfix::after{

          content: " ";

          display: block;

          clear: both;

          visibility: hidden;

          height: 0;

          }

          </style>

          </head>

          <body>

          <div>

          <div>float</div>

          </div>

          </body>

          </html>

          當(dāng)我們沒有設(shè)置clearfix的after偽元素時,會發(fā)現(xiàn)clearfix的高度為0,只有邊框會顯示出來。我們通過設(shè)置clearfix的after偽元素來讓我們在不需要新增標(biāo)簽的情況下就可以清除掉浮動,并且clearfix類還可以復(fù)用。

          注意點(diǎn):

          content和display屬性會將after偽元素渲染出來,加上clear: both實(shí)現(xiàn)一個真實(shí)標(biāo)簽清除浮動的效果。

          在一般瀏覽器中不設(shè)置visibility和height是沒有問題的,但為了增加代碼健壯性和規(guī)范性,建議加上。

          :after 和 ::after的區(qū)別::after的寫法是css2的,可以兼容到IE8,::after的寫法是css3中規(guī)定的,用以區(qū)分偽類(:hover)和偽元素(::before)。

          定位與浮動的相關(guān)知識點(diǎn)就講的差不多了,下篇文章會去講下merge的一些問題 和 格式化上下文(formatting context) , 繼續(xù)把css布局篇完成。

          最后你覺得我們的文章對你有幫助,歡迎關(guān)注我,有問題可以加我們的學(xué)習(xí)交流群,在文章下方評論處,并且你可以隨時在上面向我們提問,把你在學(xué)習(xí)前端過程中所遇到的問題發(fā)給我們。我們每天都會按時回復(fù)大家的每一個問題,希望我們可以伴隨你從入門到專家。

          前面兩篇文章,學(xué)習(xí)了JavaScript中DOM、BOM相關(guān)基礎(chǔ)知識后,今天我們將結(jié)合前面所學(xué)內(nèi)容,利用DOM操作實(shí)現(xiàn)常見的網(wǎng)頁動畫效果;結(jié)合知識點(diǎn)有相關(guān)案例效果演示,另外本文所設(shè)計(jì)的源碼和配套素材可在文末獲?。?/p>

          JavaScript網(wǎng)頁特效

          學(xué)習(xí)目標(biāo)

          • offset的屬性與作用
          • client的屬性與作用
          • scroll的屬性與作用
          • 封裝簡單動畫函數(shù)
          • 網(wǎng)頁輪播圖

          I、元素偏移量

          獲得元素距離帶有定位父元素的位置

          獲得元素自身的width和height

          1.offset常用的屬性

          2.offset與style的區(qū)別

          案例:獲取鼠標(biāo)在盒子內(nèi)的坐標(biāo)

          思路:盒子內(nèi)的坐標(biāo)可以通過鼠標(biāo)事件的e.pageX獲取到頁面坐標(biāo)再減去element.offsetLeft來得到;

          var box = document.querySelector('.box');
          box.addEventListener('click',function(e){
              var x = e.pageX - this.offsetLeft;
              var y = e.pageY - this.offsetTop;
              console.log('x:'+x+',y:'+y);
          })

          案例:模態(tài)框拖拽

          需求:

          (1)點(diǎn)擊彈出層,會淡出模塊框,并且顯示灰色半透明的遮擋層;

          (2)點(diǎn)擊關(guān)閉按鈕,可以關(guān)閉模態(tài)框,并且同時關(guān)閉灰色半透明遮擋層;

          (3)鼠標(biāo)放到模態(tài)框最上面一行,可以按住鼠標(biāo)拖拽模態(tài)框在頁面中移動;

          (4)鼠標(biāo)松開,可以停止拖動模態(tài)框移動;

          分析:

          (1)拖拽事件,鼠標(biāo)是按著的狀態(tài),故mousemovemouseup須卸載mousedown事件里面;

          (2)在拖拽的過程中,鼠標(biāo)的位置相對于組件的坐標(biāo)是不變的,因此為了改變組件的位置,需要將頁面坐標(biāo)減去相對組件坐標(biāo)來獲?。?/span>

          var link = document.querySelector('#link');
          var login_window = document.querySelector('#login');
          var close_button = document.querySelector('#closeBtn');
          var bg = document.querySelector('#bg');
          link.addEventListener('click',function(){
              login_window.style.display = 'block';
              bg.style.display = 'block';
          })
          close_button.addEventListener('click',function(){
              login_window.style.display = 'none';
              bg.style.display = 'none';
          })
          // 拖動事件三個過程:mousedown、mousemove、mouseup
          var title = document.querySelector('#title');
          title.addEventListener('mousedown',function(e){
              var x = e.pageX - login_window.offsetLeft;
              var y = e.pageY - login_window.offsetTop;
              document.addEventListener('mousemove',move);
              function move(e){
                  login_window.style.left = e.pageX - x + 'px';
                  login_window.style.top = e.pageY -y + 'px';
              }
              document.addEventListener('mouseup',function (e) {
                  document.removeEventListener('mousemove',move);
              });
          });

          案例:仿京東放大鏡效果

          分析:

          (1)mask界面與big界面可以通過鼠標(biāo)事件設(shè)置dispaly屬性即可;mouseover顯示mask,mouseleave隱藏mask、mousemove移動mask

          (2)mask的left與top的值可以通過鼠標(biāo)在prew_img中的位置來獲取;

          (3)為了讓mask界面中央跟著鼠標(biāo)指針走,則需要減去mask尺寸一半的偏移量;

          (4)防止mask頁面跑出prew_img,需要對偏移量進(jìn)行判斷;

          (5)大圖片移動距離怎么計(jì)算?mask移動距離/mask最大移動距離 = 大圖片移動距離/大圖片最大移動距離;所以大圖片移動距離 = mask移動距離 * 大圖片移動最大距離 / 遮擋層最大移動距離;

          window.addEventListener('load',function(){
              var prew_img = document.querySelector('.preview_img');
              var mask = document.querySelector('.mask');
              var big = document.querySelector('.big');
              prew_img.addEventListener('mouseover',function(){
                  mask.style.display = 'block';
                  big.style.display = 'block';
              })
              prew_img.addEventListener('mousemove',function(e){
                  // 獲取鼠標(biāo)在prew_img元素內(nèi)的坐標(biāo)
                  var x = e.pageX - this.offsetLeft;
                  var y = e.pageY - this.offsetTop;
                  // 防止mask頁面跑出prew_img盒子
                  var maskX = x - mask.offsetWidth / 2;
                  // 遮擋層的最大移動距離maskMax
                  var maskMax = this.offsetWidth - mask.offsetWidth;
                  if(maskX <= 0){
                      maskX = 0;
                  }else if(maskX >= maskMax){
                      maskX = maskMax;
                  }
                  var maskY = y - mask.offsetHeight / 2;
                  if(maskY <= 0){
                      maskY = 0;
                  }else if(maskY >= maskMax){
                      maskY = maskMax;
                  }
                  // 讓mask界面中央跟著鼠標(biāo)指針走
                  mask.style.left = maskX + 'px';
                  mask.style.top = maskY + 'px';
                  // 讓big界面內(nèi)容跟著mask位置移動,
                  // 大圖片移動距離 = mask移動距離 * 大圖片移動最大距離 / mask最大移動距離
                  var big_img = document.querySelector('.bigImg');
                  var bigMax = big_img.offsetWidth - big.offsetWidth;
                  // 大圖片移動距離
                  var bigMoveX = maskX * bigMax / maskMax;
                  var bigMoveY = maskY * bigMax / maskMax;
                  big_img.style.left = -bigMoveX + 'px';
                  big_img.style.top = -bigMoveY + 'px';
              });
          
              prew_img.addEventListener('mouseleave',function(){
                  mask.style.display = 'none';
                  big.style.display = 'none';
              });
          });

          II、元素的可視區(qū)


          立即執(zhí)行函數(shù)

          不需要調(diào)用,立馬能自己執(zhí)行的函數(shù);

          // 寫法一:
          (function(){})()
          // 寫法二:
          (function(){}())

          立即執(zhí)行函數(shù)也可以傳遞參數(shù):

          (function(a,b){
          console.log(a+b);
          })(1,2)

          立即執(zhí)行函數(shù)的作用是獨(dú)立創(chuàng)建了一個作用域,里面所有的變量都是局部變量,不會有命名沖突的情況;

          III、元素滾動scroll

          使用scroll系列相關(guān)屬性可以動態(tài)得到元素的大小、滾動距離;

          scroll系列屬性 作用 備注 element.scrollTop 返回被卷去的上側(cè)距離 返回的數(shù)值不帶單位 element.scrollLeft 返回被卷去的左側(cè)距離 返回的數(shù)值不帶單位 element.scrollWidth 返回自身的實(shí)際寬度,不含邊框 返回的數(shù)值不帶單位 element.scrollHeight 返回自身的實(shí)際高度,不含邊框 返回的數(shù)值不帶單位

          案例:仿淘寶固定側(cè)邊欄

          • 1.原先側(cè)邊欄是絕對定位
          • 2.當(dāng)頁面滾動到一定的位置,側(cè)邊欄改為固定定位
          • 3.頁面繼續(xù)滾動,會讓頂部顯示出來

          頁面被卷去的頭部可以通過:window.pageYOffset來獲得

          // 1.獲取元素
          var sliderBar = document.querySelector('.slider-bar');
          var topBar = document.querySelector('.header');
          var banner = document.querySelector('.banner');
          var main = document.querySelector('.main');
          var goBack = document.querySelector('.goBack');
          
          var barHeight = banner.offsetTop;
          var sliderBarTop = sliderBar.offsetTop;
          var fixTop = sliderBarTop - barHeight;
          var mainTop = main.offsetTop;
          // 2.頁面滾動事件
          document.addEventListener('scroll',function(){
          
              if(window.pageYOffset >= barHeight){
                  sliderBar.style.position = 'fixed';
                  sliderBar.style.top = fixTop + 'px';
              }else{
                  sliderBar.style.position = 'absolute';
                  sliderBar.style.top = sliderBarTop + 'px';
              }
              if(window.pageYOffset >= mainTop){
                  goBack.style.display = 'block';
              }else{
                  goBack.style.display = 'none';
              }
          })

          IV、鼠標(biāo)事件

          當(dāng)鼠標(biāo)移動到元素上時就會觸發(fā)mouseenter事件,類似mouseenter

          兩者的區(qū)別是:mouseover鼠標(biāo)經(jīng)過自身盒子會觸發(fā)、經(jīng)過子盒子也會觸發(fā);而mouseenter只有經(jīng)過自身盒子才會觸發(fā);

          原因是mouseenter不會冒泡;跟mouseenter搭配的通常是mouseleave

          V、動畫函數(shù)

          1.動畫實(shí)現(xiàn)的原理:

          通過定時器setInterval()不斷移動盒子位置;

          實(shí)現(xiàn)步驟:

          • 獲得盒子當(dāng)前位置
          • 讓盒子在當(dāng)前位置加上一個移動距離
          • 加上一個結(jié)束定時器的條件
          • 盒子需要添加定位,才能使用element.style.left
          //利用setInterval設(shè)置一個box元素從左向右移動400像素的動畫
          var box = document.querySelector('.box');
          var timer = setInterval(function(){
              if(box.offsetLeft > 200){
                  // 停止動畫,本質(zhì)上是清除定時器
                  clearInterval(timer);
              }
              box.style.left = box.offsetLeft + 5 + 'px';
          },50);

          2.動畫函數(shù)的封裝

          將動畫函數(shù)封裝起來,利用JS是動態(tài)語言的特性,通過設(shè)置對象的方式,給每個不同的元素指定不同的定時器;

          // 簡單動畫函數(shù)的封裝,目標(biāo)對象obj,目標(biāo)位置target
          function animate(obj,target){
              // 如果設(shè)置一個按鈕啟動動畫,會存在一個bug,只要不斷點(diǎn)擊按鈕,動畫會越走越快;
              // 原因是啟動了太多定時器,解決方案是,讓元素只有一個定時器執(zhí)行
              clearInterval(obj.timer);
              obj.timer = setInterval(function(){
              if(obj.offsetLeft > target){
                  // 停止動畫,本質(zhì)上是清除定時器
                  clearInterval(obj.timer);
              }
              obj.style.left = obj.offsetLeft + 5 + 'px';
          },50);
          }
          //利用setInterval設(shè)置動畫
          var btn = document.querySelector('button');
          var box1 = document.querySelector('.box1');
          btn.addEventListener('click',function(){
              animate(box1,400);
          });

          3.緩動動畫原理

          緩動動畫就是讓元素運(yùn)動速度有所變換,最常見的就是讓速度慢慢停下來;

          思路:讓盒子每次移動的距離慢慢變??;

          核心算法每次移動的步長 = (目標(biāo)值-現(xiàn)在的位置)/10這里的10是份數(shù)可以是9也可以是8;

          停止的條件是:當(dāng)前盒子的位置等于目標(biāo)位置就停止定時器;

          // 緩動動畫
          function animate(obj,target){
              // 清除定時器
              clearInterval(obj.timer);
              obj.timer = setInterval(function() {
                  // 每次運(yùn)行定時器都要重新計(jì)算步長值,所以步長值寫在定時器里面
                  var step = (target - obj.offsetLeft)/10;
                  // 如果step是正值則往大取整,如果step是負(fù)值則往小取整
                  step = step >= 0 ? Math.ceil(step) : Math.floor(step);
                  if(obj.offsetLeft == target){
                      clearInterval(obj.timer);
                  }
                  // 緩動動畫核心算法:前進(jìn)步長=(目標(biāo)-當(dāng)前)/ 10
                  obj.style.left = obj.offsetLeft + step + 'px';
              },50);
          }

          動畫函數(shù)添加回調(diào)函數(shù)

          回調(diào)函數(shù)原理:函數(shù)可以作為一個參數(shù),將這個函數(shù)作為參數(shù)傳入到另一個函數(shù)里面,當(dāng)這個函數(shù)執(zhí)行完成后,再執(zhí)行傳進(jìn)去的這個函數(shù),這個過程叫做回調(diào)。

          回調(diào)函數(shù)位置:寫到定時器結(jié)束的位置

          // 緩動動畫
          function animate(obj,target,callback){
              // 清除定時器
              clearInterval(obj.timer);
              obj.timer = setInterval(function() {
                  // 每次運(yùn)行定時器都要重新計(jì)算步長值,所以步長值寫在定時器里面
                  var step = (target - obj.offsetLeft)/10;
                  // 如果step是正值則往大取整,如果step是負(fù)值則往小取整
                  step = step >= 0 ? Math.ceil(step) : Math.floor(step);
                  if(obj.offsetLeft == target){
                      clearInterval(obj.timer);
                      if(callback){
                          // 調(diào)用函數(shù)
                          callback();
                      }
                  }
                  // 緩動動畫核心算法:前進(jìn)步長=(目標(biāo)-當(dāng)前)/ 10
                  obj.style.left = obj.offsetLeft + step + 'px';
              },50);
          }

          將動畫函數(shù)封裝到單獨(dú)的JS文件

          在head里引入JS文件

          <script src="animate.js"></script>

          實(shí)際調(diào)用過程中可以直接調(diào)用JS中定義的函數(shù)

          var sliderbar = document.querySelector('.sliderbar');
          var con = document.querySelector('.con');
          sliderbar.addEventListener('mouseenter',function(){
              animate(con,-160,function () {
                  // 動畫執(zhí)行完畢,將左箭頭轉(zhuǎn)為右箭頭
                  sliderbar.children[1].innerHTML = '→';
              });
          })
          sliderbar.addEventListener('mouseleave',function(){
              animate(con,0,function () {
                  sliderbar.children[1].innerHTML = '←';
              });
          })

          案例:網(wǎng)頁輪播圖

          功能需求:

          • 鼠標(biāo)經(jīng)過輪播圖模塊,左右按鈕顯示,離開隱藏左右按鈕;
          • 鼠標(biāo)點(diǎn)擊右側(cè)按鈕一次,圖片往左播放一張,以此內(nèi)推,左側(cè)按鈕同理;
          • 圖標(biāo)播放的同時,下面小圓圈模塊跟隨一起變化;
          • 點(diǎn)擊小圓圈,可以播放相應(yīng)圖片;
          • 鼠標(biāo)不經(jīng)過輪播圖,輪播圖也會自動播放圖片;
          • 鼠標(biāo)經(jīng)過,輪播圖模塊,自動播放停止
          window.addEventListener('load', function () {
              // === 0.定義變量,獲取元素
              var focus = document.querySelector('.focus');
              var arrowL = document.querySelector('.arrow-l');
              var arrowR = document.querySelector('.arrow-r');
          
              // === 1.鼠標(biāo)經(jīng)過輪播圖模塊,左右按鈕顯示,離開隱藏左右按鈕;=====
              focus.addEventListener('mouseenter', function () {
                  arrowL.style.display = 'block';
                  arrowR.style.display = 'block';
                  clearInterval(timer);
                  timer = null;
              });
              focus.addEventListener('mouseleave', function () {
                  arrowL.style.display = 'none';
                  arrowR.style.display = 'none';
                  timer = window.setInterval(function () {
                      arrowR.click();
                  }, 3000);
              });
              // === 2.根據(jù)輪播圖的數(shù)量自動生成小圓圈
              var ul = focus.querySelector('ul');
              var ol = focus.querySelector('.circle');
              var pictureWidth = focus.offsetWidth;
              // 獲取到輪播圖圖片的數(shù)量length
              var length = ul.children.length;
              // 顯示當(dāng)前圖片的索引
              var circle = 0;
              // 顯示當(dāng)前圖片的索引
              var num = 0;
              // 創(chuàng)建元素插入到ol中
              for (var i = 0; i < length; i++) {
                  var li = document.createElement('li');
                  // 給沒一個小圓圈添加一個index屬性,方便點(diǎn)擊事件的ul移動長度的確定
                  li.setAttribute('index', i);
                  // 給每一個小圓圈添加點(diǎn)擊事件
                  li.addEventListener('click', function () {
                      // 移除其他小圓圈的選中屬性
                      for (var i = 0; i < length; i++) {
                          ol.children[i].className = '';
                      }
                      // 設(shè)置當(dāng)前選中小圓圈的選中屬性
                      this.className = 'current';
                      // 定義選中的小圓圈的索引
                      var index = this.getAttribute('index');
                      num = index;
                      circle = index;
                      animate(ul, -pictureWidth * index);
                  });
                  ol.appendChild(li);
              }
              ol.children[0].className = 'current';
          
              // === 3.鼠標(biāo)點(diǎn)擊右側(cè)按鈕一次,圖片往左播放一張,以此內(nèi)推,左側(cè)按鈕同理;==
              // 為了實(shí)現(xiàn)無縫滾動,需要將第一張圖添加到最后一張圖中
              var lastLi = ul.children[0].cloneNode(true);
              ul.appendChild(lastLi);
              // 設(shè)置一個節(jié)流閥,防止按鈕在短時間內(nèi)點(diǎn)擊過多
              var flag = true;
              arrowR.addEventListener('click', function () {
                  if (flag) {
                      flag = false;
                      if (num == ul.children.length - 1) {
                          ul.style.left = 0;
                          num = 0;
                      }
                      num++;
                      animate(ul, -pictureWidth * num, function () {
                          flag = true;
                      });
                      circle++;
                      if (circle == ol.children.length) {
                          circle = 0;
                      }
                      activateCircle(circle);
                  }
              });
          
              arrowL.addEventListener('click', function () {
                  if (flag) {
                      flag = false;
                      if (num == 0) {
                          num = ul.children.length - 1;
                          ul.style.left = -num * pictureWidth + 'px';
                      }
                      num--;
                      animate(ul, -num * pictureWidth, function () {
                          flag = true;
                      });
                      if (circle == 0) {
                          circle = ol.children.length;
                      }
                      circle--;
                      activateCircle(circle);
                  }
              });
          
              // 排他法思想點(diǎn)亮小圓圈
              function activateCircle(index) {
                  for (var i = 0; i < ol.children.length; i++) {
                      ol.children[i].className = '';
                  }
                  ol.children[index].className = 'current';
              }
          
              // 實(shí)現(xiàn)輪播圖自動播放
              var timer = window.setInterval(function () {
                  arrowR.click();
              }, 3000);
          });

          顯示效果:

          輪播圖自動播放的原理是:設(shè)置一個定時器使用click()函數(shù)模擬按鈕點(diǎn)擊事件;

          輪播圖實(shí)現(xiàn)無縫滾動的原理是:將第一個圖動態(tài)加在最后一張圖上,當(dāng)切到最后一張圖時,重新設(shè)置元素布局距離,再執(zhí)行滑動動畫。

          防止同一個按鈕在短時間內(nèi)點(diǎn)擊次數(shù)過多,可以設(shè)置一個節(jié)流閥,將啟動節(jié)流閥的操作寫在動畫回調(diào)函數(shù)里,這樣只有當(dāng)動畫執(zhí)行完畢后才才可以重新恢復(fù)按鈕的點(diǎn)擊功能;

          頁面滾動動畫可以使用函數(shù):window.scroll(x,y)可以滾動至頁面的指定坐標(biāo)位置;


          最后:

          本文配套源碼與素材獲取:https://gitee.com/yushengtan/jscode

          關(guān)于JavaScript在網(wǎng)頁動畫中的使用就介紹到這里,下一節(jié)我們將繼續(xù)深入介紹JavaScript的異步調(diào)用相關(guān)知識的學(xué)習(xí)~

          、什么是 CSS 盒模型,它是如何工作的?

          CSS 盒模型定義了元素在網(wǎng)頁上的呈現(xiàn)方式。它由內(nèi)容、內(nèi)邊距、邊框和邊距組成。內(nèi)容代表實(shí)際的元素內(nèi)容,而填充則在內(nèi)容和邊框之間添加空間。邊框提供可見的邊界,邊距在元素周圍創(chuàng)建空間。

          這是一個例子:

          .box {  width: 200px;  padding: 20px;  border: 1px solid black;  margin: 10px;}

          2、解釋 CSS 特異性的概念以及它如何影響樣式應(yīng)用。

          CSS 特異性決定了當(dāng)多個規(guī)則針對某個元素時,將哪些樣式應(yīng)用于該元素。特異性是根據(jù)選擇器的組合計(jì)算的,例如,元素類型、類、ID 和內(nèi)聯(lián)樣式。特異性越高,規(guī)則的優(yōu)先級越高。

          這是一個例子:

          /* ID selector - high specificity */#myElement {  color: red;}
          /* Class selector - medium specificity */.myClass {  color: blue;}/* Element selector - low specificity */div {  color: green;}

          3、使元素水平和垂直居中的不同方法有哪些?

          有多種方法可以使元素水平和垂直居中。以下是三種流行的技術(shù):

          1).彈性盒方法:

          .container {  display: flex;  justify-content: center;  align-items: center;}

          2).CSS網(wǎng)格方法:

          .container {  display: grid;  place-items: center;}

          3).變換方法:

          .container {  position: relative;}
          .centered-element {  position: absolute;  top: 50%;  left: 50%;  transform: translate(-50%, -50%);}

          4、如何創(chuàng)建在滾動時保持固定的粘性標(biāo)題?

          您可以通過使用position:sticky;來實(shí)現(xiàn)粘性標(biāo)題。此屬性允許元素在滾動時在其容器或視口中保持固定。

          這是一個例子:

          .header {  position: sticky;  top: 0;  background-color: #ffffff;}

          5、什么是CSS浮動屬性,它是如何工作的?

          CSS float 屬性用于在其容器內(nèi)定位元素。浮動元素向左或向右移動,允許其他元素環(huán)繞它們。此屬性通常用于創(chuàng)建多列布局或定位圖像。


          主站蜘蛛池模板: 亚洲一区二区三区久久久久| 精品国产一区二区二三区在线观看 | 视频一区二区三区在线观看| 国产成人无码一区二区三区在线| 午夜性色一区二区三区不卡视频| 日韩人妻一区二区三区免费| 国产亚洲自拍一区| 国产一区二区三区在线看片 | 国产成人AV区一区二区三| 亚洲av乱码一区二区三区香蕉| 国产AV午夜精品一区二区三| 国产91精品一区二区麻豆亚洲| 国产视频一区二区| 国产无人区一区二区三区 | 国产一区二区视频在线观看 | 一区视频在线播放| 精品视频在线观看一区二区 | 亚洲AV一区二区三区四区| 亚洲一区二区三区亚瑟| 国产一区二区三区韩国女主播| 亚洲日本乱码一区二区在线二产线 | 国产一区二区三区电影| 免费无码一区二区三区蜜桃大| 亚洲av无码一区二区三区人妖| 一区二区和激情视频| 国产一区二区三区播放心情潘金莲| 亚洲AV无码一区二区三区电影| 亚洲美女视频一区二区三区| AA区一区二区三无码精片 | 一区二区三区精品视频| 国产激情一区二区三区| 人妻少妇精品一区二区三区| 亚洲国产精品一区二区成人片国内 | 国产成人一区二区三区免费视频| 怡红院美国分院一区二区| 国产MD视频一区二区三区| 中文国产成人精品久久一区| 无码午夜人妻一区二区三区不卡视频| 日韩精品在线一区二区| 国产精品视频一区麻豆| 精品一区二区三区无码视频|