整合營銷服務(wù)商

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

          免費咨詢熱線:

          IT學(xué)堂:純CSS的瀑布流布局方法總結(jié)

          IT學(xué)堂:純CSS的瀑布流布局方法總結(jié)

          布流布局出來好多年了,剛出來時,一般都采用js來實現(xiàn),涌現(xiàn)了很多比較好的js插件,例如:masonry.js、gridify.js等等。這里就不再詳說如何使用了,網(wǎng)上都能找到。今天討論的是純CSS實現(xiàn)瀑布流布局。

          一、多個列表并列的瀑布流布局法:

          這種布局方法非常簡單,就是將多個列表橫向排列,每個列表擁有的項都差不多。圖片寬度固定,高度自動撐起來。

          html:

          <div class="wrap">
          	<ul class="waterfall">
          		<li class="item"><img src="image/1.jpg"></li>
          		<li class="item"><img src="image/3.jpg"></li>
          		<li class="item"><img src="image/5.jpg"></li>
          		<li class="item"><img src="image/7.jpg"></li>
          		<li class="item"><img src="image/9.jpg"></li>
          	</ul>
          	<ul class="waterfall">
          		<li class="item"><img src="image/2.jpg"></li>
          		<li class="item"><img src="image/4.jpg"></li>
          		<li class="item"><img src="image/6.jpg"></li>
          		<li class="item"><img src="image/8.jpg"></li>
          		<li class="item"><img src="image/10.jpg"></li>
          	</ul>
          </div>
          

          css:

          .wrap{
          	display:flex;
          	justify-content: space-between;
          }
          .waterfall{
          	width:50%;
          }
          .waterfall .item img{
          	width:100%;
          }
          

          注:

          1、waterfall也可以浮動,wrap清除浮動,只要兩個列表在一行就行。

          2、每一塊 item 都是從上往下排列的,并不能實現(xiàn)從左往右,解決辦法是:在獲取數(shù)據(jù)時,需要將數(shù)據(jù)按奇偶進(jìn)行分類顯示(假設(shè)顯示兩列,多列同理)。您可以定義兩個數(shù)組:listEven和listOdd,分別來接受獲取的數(shù)據(jù)的偶數(shù)項和奇數(shù)項,然后分別進(jìn)行渲染。這里用VUE來演示:

          //假設(shè)res.data為ajax請求到的數(shù)據(jù)
          res.data.map(function(item,index){
          	index%2===0 ? that.listEven.push(item) : that.listOdd.push(item);
          })
          
          <div class="wrap">
          	<ul class="waterfall">
          		<li class="item" v-for="(item,index) in listEven" :key="'even'+index"><img :src="item"></li>
          	</ul>
          	<ul class="waterfall">
          		<li class="item" v-for="(item,index) in listOdd" :key="'odd'+index"><img :src="item"></li>
          	</ul>
          </div>
          

          3、這種布局方法,會有一個問題,如果item高度左右列相差很大,就會顯示有問題,如下圖,解決辦法給item一個max-height,超過圖片這個max-height就隱藏,此外,后臺在傳圖片時做裁切更好:

          css 瀑布流

          二、CSS3 column瀑布流布局法:

          CSS3 column多列可以非常輕松的實現(xiàn)瀑布流效果,它會自動將列表項分配到根據(jù)設(shè)置的列數(shù)當(dāng)中去,先看下它的常用屬性:

          • column-count:列數(shù) 給waterfall加
          • column-width:列的寬度
          • column-gap:列之間的間隙
          • break-inside:avoid 禁止列表項斷裂,即左邊列表項的內(nèi)容有可能跑到右邊的最上面 給item加

          html

          <ul class="waterfall">
          	<li class="item"><img src="1.jpg"></li>
          	<li class="item"><img src="2.jpg"></li>
          	<li class="item"><img src="3.jpg"></li>
          	<li class="item"><img src="4.jpg"></li>
          	<li class="item"><img src="5.jpg"></li>
          	<li class="item"><img src="6.jpg"></li>
          	<li class="item"><img src="7.jpg"></li>
          	<li class="item"><img src="8.jpg"></li>
          	<li class="item"><img src="9.jpg"></li>
          	<li class="item"><img src="10.jpg"></li>
          </ul>
          

          css

          .waterfall{
          	column-count:2;
          }
          .waterfall .item{
          	break-inside: avoid;
          }
          

          效果如下:

          css3瀑布流布局

          注:

          1、每一塊 item 都是從上往下排列的,并不能實現(xiàn)從左往右,第一種方法采用了奇偶兩個數(shù)組解決了,這個不好解決,如果帶有上拉加載,不確定總個數(shù),就更不好解決了。

          2、item的上下間距盡量不要用margin,否則可能會出現(xiàn)下面這種情況,這是因為左列最后一個margin跑到右邊上面去了,改成padding即可,因為padding屬于item的內(nèi)容,而break-inside: avoid則禁止item折斷:

          css3瀑布流布局

          三、CSS3 flex豎排瀑布流布局法

          CSS3的flex用法很多。大多數(shù)情況都是用來橫排,將塊狀容器顯示在一行,還有就是用來對其一行。但是,改變flex-direction就可以做到縱向排列。

          html

          <ul class="waterfall">
          	<li class="item"><img src="1.jpg"></li>
          	<li class="item"><img src="2.jpg"></li>
          	<li class="item"><img src="3.jpg"></li>
          	<li class="item"><img src="4.jpg"></li>
          	<li class="item"><img src="5.jpg"></li>
          	<li class="item"><img src="6.jpg"></li>
          	<li class="item"><img src="7.jpg"></li>
          	<li class="item"><img src="8.jpg"></li>
          	<li class="item"><img src="9.jpg"></li>
          	<li class="item"><img src="10.jpg"></li>
          </ul>
          

          css

          .waterfall{
          	/*flex-box*/
          	display: flex;
          	/*縱向排列*/
          	flex-direction: column;
          	/*換列*/
          	flex-wrap: wrap;
          	height: 100vh;
          }
          .waterfall .item{
          	width:50%;
          }
          

          注:

          1、flex-wrap: wrap 是為了讓item撐滿waterfall的時候換列(可以理解為換行)

          2、這里waterfall的height一定要寫,否則,waterfall隨著內(nèi)容變多,不斷撐高也不會換列。

          3、waterfall的height要隨著item的數(shù)量變化而變化,否則,一列顯示不了就顯示兩列,兩列顯示不了就顯示三列,為了維持固定的列數(shù),只能不斷升高waterfall的高度。

          4、flex-direction: column和flex-wrap: wrap可以合并為flex-flow: column wrap;

          5、與前面兩種方法一樣,這種方法仍然是不好解決從上往下排列而非從左往右排列的問題。

          總結(jié):純CSS實現(xiàn)瀑布流,總有這樣或那樣的問題,最終還是要通過js來控制。如果對排序沒有要求的話,第二種方法還是比較好用的。純css實現(xiàn)瀑布流,大家還有什么好的方法,歡迎留言評論。關(guān)注IT學(xué)堂,會有更多驚喜哦!

          本文簡介

          • 面試大廠,HTML/CSS,JS,網(wǎng)絡(luò)基礎(chǔ)這三塊硬知識是必不可少的
          • 我整理了一些備考筆記,分享給大家
          • 初中級前端到高級前端的蛻變,從基礎(chǔ)知識開始~

          2 塊元素和行元素

          2.1 請說出3個H5新增的塊元素,并介紹他們的應(yīng)用場景

          • aside:表示article元素內(nèi)容之外,與article元素內(nèi)容相關(guān)的輔助信息
          • figure:代表一個塊級圖像,包含說明。figure添加標(biāo)題時,與figcaption元素結(jié)合使用。
          • dialog:表示幾個人直接的對話。與dt和dd元素結(jié)合使用,dt表示講話者,dd表示講話內(nèi)容。

          2.2 行內(nèi)元素和塊元素的區(qū)別

          • HTML元素分為行內(nèi)、塊狀、行內(nèi)塊元素三種。
          • 塊元素和行內(nèi)塊元素可以設(shè)置寬高
          • 行內(nèi)元素不可以,高度由內(nèi)容撐開
          • 三者是可以通過display屬性任意轉(zhuǎn)換的 block 塊狀元素 inline-block行內(nèi)塊元素 inline 行內(nèi)元素

          2.3 塊級元素特征

          • 可以設(shè)置寬高
          • 設(shè)置margin、padding的上下左右都有效
          • 元素獨占一行
          • 多個塊狀元素一起寫,默認(rèn)排列從上至下

          我自己是一名從事了多年開發(fā)的web前端老程序員,目前辭職在做自己的web前端私人定制課程,今年我花了一個月整理了一份最適合2020年學(xué)習(xí)的web前端學(xué)習(xí)干貨,各種框架都有整理,送給每一位前端小伙伴,想要獲取的可以關(guān)注我的頭條號并在后臺私信我:前端,即可免費獲取。

          2.4 行內(nèi)塊元素特征

          • 能設(shè)置寬高
          • 不會自動換行
          • 多個行內(nèi)塊一起寫,默認(rèn)從左至右排列

          2.5 行內(nèi)元素特征

          • 設(shè)置寬高無效
          • 設(shè)置margin的上下無效,左右有效,設(shè)置padding上下左右都有效(并且會撐大空間)
          • 不會自動換行

          3 CSS

          3.1 請說出3個CSS瀏覽器前綴

          1. -ms- 兼容IE瀏覽器
          2. -moz- 兼容firefox
          3. -o- 兼容opera
          4. -webkit- 兼容chrome和safari

          使用demo

          div {  -ms-transform: rotate(0);  -webkit-transform: rotate(0);  -moz-transform: rotate(0);  -o-transform: rotate(0);  transform: rotate(0);}

          CSS前綴自動補全:autoprefixer

          3.2 盒模型

          1. 盒模型分為標(biāo)準(zhǔn)盒模型和怪異盒模型(IE5.X和6)兩種
          2. 標(biāo)準(zhǔn)盒模型 width=content
          3. 怪異盒模型 width=content + padding + border

          已知: margin:20px; border:10px; padding:10px; width:200px; height:50px;

          ![](https://imgkr2.cn-bj.ufileos.com/5b02ca29-357c-41bd-b193-925fbf089562.png?UCloudPublicKey=TOKEN_8d8b72be-579a-4e83-bfd0-5f6ce1546f13&Signature=N8j%252FT85l87RtNBPpgYnJ1lYCWIo%253D&Expires=1599734594)

          標(biāo)準(zhǔn)盒模型:1\. 占用寬:margin*2+padding*2+border*2+width=20*2+10*2+10*2+200=2802\. 占用高:margin*2+padding*2+border*2+height=20*2+10*2+10*2+50=1303\. 盒子實際寬度:padding*2+border*2+width=10*2+10*2+200=2404\. 盒子實際高度padding*2+border*2+height=10*2+10*2+50=90

          ![](https://imgkr2.cn-bj.ufileos.com/7779f321-279b-4c46-b6e5-b319a28b8549.png?UCloudPublicKey=TOKEN_8d8b72be-579a-4e83-bfd0-5f6ce1546f13&Signature=iY2y7oaq2dl4L39xDbN0PO%252Bd4QI%253D&Expires=1599734605)

          怪異盒模型:1\. 占用寬:margin*2+width=20*2+200=2402\. 占用高:margin*2+height=20*2+50=903\. 盒子實際寬度:width=2004\. 盒子實際高度height=50
          

          IE8及更早版本不兼容問題解決方案:在HTML頁面聲明

          3.3 box-sizing都有哪些值?他們的寬高分別如何計算?

          1. content-box(標(biāo)準(zhǔn)盒模型)|border-box(怪異盒模型)|inherit(繼承父元素)
          2. content-box的寬高由content決定
          3. border-box的寬高由content+padding+border決定


          4. BFC

          4.1 什么是邊界塌陷(或邊界重疊)?

          1. 兄弟div(上下margin塌陷)
          2. 父子div(如果父級div沒有padding\border\inlinecontent, 子級div的margin會向上查找邊界塌陷的div,直到找到某個標(biāo)簽包括border\padding\inline content的其中一個,然后按此div進(jìn)行margin)

          4.2 什么是BFC(格式化上下文)?如何實現(xiàn)?

          BFC(塊狀格式化上下文,獨立的盒子,布局不受外部影響,但是如果同一個BFC中,同級塊狀元素的margin-top和margin-bottom會重疊)

          只要元素滿足下面的任一條件,都會觸發(fā)BFC特征。

          1. body根元素
          2. position: fixed|absolute(絕對定位元素)
          3. float(浮動元素) 除了none
          4. overflow: hidden|auto|scroll (除了visible之外的值)
          5. display: inline-block\ table-cells\flex (具有table-的屬性)

          解決問題:

          1. 解決邊界塌陷問題
          2. 解決浮動元素導(dǎo)致父元素高度塌陷問題
          3. 解決阻止元素被浮動元素覆蓋問題


          4.3 多個inline元素之間會有空隙,為什么?如何解決?

          元素被當(dāng)成行內(nèi)元素排版時,元素直接的空白符會被瀏覽器處理,根據(jù)white-spack的處理方式(默認(rèn)是normal,合并多余空白),Html代碼在回車換行時被轉(zhuǎn)成一個空白符,在字體不為0的情況下,空白符占據(jù)一定寬度,所以inline-block元素之間就出現(xiàn)了空隙。

          復(fù)現(xiàn)<ul>  <li>首頁</li>  <li>登陸</li>  <li>資源</li>  <li>社區(qū)</li>  <li>幫助</li></ul>

          ![](https://imgkr2.cn-bj.ufileos.com/50a6afa3-421d-4af9-9fad-48d72e69feb3.jpeg?UCloudPublicKey=TOKEN_8d8b72be-579a-4e83-bfd0-5f6ce1546f13&Signature=fkwoshYKbb6i%252FNOezztndQzAZPk%253D&Expires=1599740520)

          解決辦法:

          1. 多個inline元素寫在同一行
          2. 將父級元素的font-size:0
          3. 給inline元素添加float的樣式
          4. 設(shè)置子元素的margin為負(fù)值
          5. 設(shè)置父元素display:table和word-spacing:-1em

          5 浮動

          5.1 浮動會出現(xiàn)什么問題?

          • 浮動會導(dǎo)致父元素高度塌陷
          • 會覆蓋其他元素

          5.2 如何清除浮動?

          • 父元素加上overflow:hidden
          • 在浮動元素的后面(同級),添加一個div,屬性是clear:both
          • 在父元素添加一個偽元素 .clearfix:after { display: block; height: 0; visibility: hidden; clear: both; content: '';} .clearfix{ //IE6模式下 zoom:1;}
          • 在父元素添加雙偽元素 .clearfix:before,.clearfix:after { display: table; content: '';}.clearfix:after { clear: both;}.clearfix { zoom: 1; //兼容IE6下}

          6 position都有哪些值?

          • relative 相對定位 (相對元素在文檔中的初始位置定位)
          • absolute絕對定位(相對于定位元素定位,最頂級是body)
          • fixed 固定定位 (相對窗口定位)
          • static 文檔流

          ![](https://imgkr2.cn-bj.ufileos.com/6ddb8a2b-1261-4b84-ae49-ec32c3c4b59a.webp?UCloudPublicKey=TOKEN_8d8b72be-579a-4e83-bfd0-5f6ce1546f13&Signature=B7HTGqcB2LRMUjsAlcvjkLzn03s%253D&Expires=1599739510)

          7 CSS的選擇器

          7.1 CSS的選擇器有哪些?

          • id 選擇器
          • class 選擇器
          • tag 選擇器
          • 屬性 選擇器(a[href=""] )
          • 派生 選擇器

          7.2 優(yōu)先級高低如何判斷?

          • 不同級優(yōu)先級: !important>內(nèi)聯(lián)>id>class=屬性=偽類 >標(biāo)簽=偽元素 > 通配符(*)
          • 同一級別: 后來居上 (后寫覆蓋先寫) 內(nèi)聯(lián)樣式 > 內(nèi)部樣式表 > 外部樣式表 > 導(dǎo)入樣式 @import ![](https://imgkr2.cn-bj.ufileos.com/67305866-9d2f-4f5c-9761-d42ee5ec7848.jpeg?UCloudPublicKey=TOKEN_8d8b72be-579a-4e83-bfd0-5f6ce1546f13&Signature=%252FKfOJPBRWgQIyPnGTYRpw8J4f%252BQ%253D&Expires=1599739287)

          優(yōu)先級相同時會發(fā)生什么? 樣式被覆蓋

          7.3 列舉幾條常用的CSS reset

          • *{ margin:0; padding:0;}
          • ol, ul { list-style:none;}
          • body {line-height:1;}

          7.4 是否了解normalize?

          normalize.css是一個css reset的替代方案。

          • 保護(hù)有用的瀏覽器默認(rèn)樣式而不是完全去掉
          • 一般化樣式:為大部分html元素提供
          • 修復(fù)瀏覽器自身的bug
          • 優(yōu)化css可用性
          • 解釋代碼

          7.5 如何做到一個list中奇數(shù)和偶數(shù)行的背景色不一樣?

           ul>li:nth-child(2n+1) {    background-color: red; }ul>li:nth-child(2n) {    background-color: yellow;}
          

          7.6 如何做到一個list的第一行沒有上邊框?

           ul>li:first-child {      border-top: none;  }
          


          有夢想的人,眼睛會發(fā)光。

          希望屏幕前的你,能夠關(guān)注我一波。接下來,我會分享前端各種干貨,以及編程中的趣事。

          天這篇文章我們開始詳細(xì)講解JS的事件。之前我們已經(jīng)講過許多事件,而我們今天要講的主要是事件對象。之前我們學(xué)習(xí)的onclick事件用于得知一個元素是否被點擊,但如果我們想知道一些更詳細(xì)的信息,例如點擊位置,點擊鍵是左鍵還是右鍵,就需要用到event對象。又例如我們希望檢測用戶鍵盤按的到底是左鍵還是右鍵來完成相應(yīng)的功能,也需要用到event對象。

          event對象和事件冒泡

          event對象的作用是幫助我們獲取一些事件的信息,例如鼠標(biāo)位置,鍵盤按鍵。這里我們用一個小例子來說明event對象是怎么運作的。現(xiàn)在我們試圖實現(xiàn)一個效果:無論點擊頁面的什么地方,都可以彈窗。聰明的同學(xué)可能已經(jīng)猜到,我們可以直接給body添加onclick事件來實現(xiàn)這一點:

          <!DOCTYPE HTML>
          <html>
           <head>
           <meta charset="utf-8" />
           <title>無標(biāo)題文檔</title>
           <script>window.onload=function (){
           document.body.onclick=function ()
           {
           alert('a');
           };};
           </script>
           </head>
           <body> 
           </body>
          </html>

          但實際上你會發(fā)現(xiàn),無論怎么點擊頁面都無法進(jìn)行彈窗,這是為什么呢?現(xiàn)在我們對這個頁面改造一下:

          <html>
           <head>
           <meta charset="utf-8" />
           <title>無標(biāo)題文檔</title>
           <script>window.onload=function (){
           document.body.onclick=function ()
           {
           alert('a');
           };};</script>
           </head>
           <body style="border:1px solid black;"> 
           <input type="button"value="aaa">
           </body>
          </html>

          可以看到的是,在body內(nèi)沒有內(nèi)容的時候,body頁面是撐不起來的(至少在ie下是這樣的),我們在頁面中加入了一個button后,body的大小也隨著button略微增大。當(dāng)然我們可以從樣式角度去解決這個問題,但是我們現(xiàn)在從程序的角度考慮的話,應(yīng)該怎么去解決他呢?其實很簡單,我們不選擇給body添加onclick事件而是直接給document添加就可以了:

          window.onload=function (){
           document.onclick=function ()
           {
           alert('a');
           };
          };

          效果如下:

          這里body也沒有被撐起來,但是document代表的是整個網(wǎng)頁,因此可以通過點擊頁面任何地方彈窗。這里我們通過一個例子來講講document到底是什么東西。

          window.onload=function (){
           alert(document.childNodes[0].tagName);
          };

          效果如下:

          這里本應(yīng)該打印出document第一個子節(jié)點的標(biāo)簽名,但返回結(jié)果為undefined。順便大家可以用IE7測試一下,其返回結(jié)果會為一個感嘆號。聰明的同學(xué)應(yīng)該可以猜到,感嘆號其實就是DOCTYPE聲明中的第一個字符,DOCTYPE聲明本身也是作為一個節(jié)點存在的。

          實際上我們可以這么理解:在一個頁面里,DOCTYPE和html存在同一個父級,也就是document(一個看不見的虛擬節(jié)點),他包括了整個網(wǎng)頁的內(nèi)容和網(wǎng)頁聲明。我們提了這么多關(guān)于document的知識,為的就是告訴大家一點:如果想給整個頁面添加事件,那么使用document一定比使用html好,因為html頁面是有可能撐不開的。回到我們的事件對象來。我們通過event對象可以獲取事件的信息,例如可以退獲取點擊的坐標(biāo):

          window.onload=function (){
           document.onclick=function (ev)
           {
           //IE
           //alert(event.clientX+','+event.clientY);
          
           //FF
           //alert(ev.clientX+','+ev.clientY);
           var oEvent=ev||event;
           alert(oEvent.clientX+','+oEvent.clientY);
           };
          };

          在ie瀏覽器下,直接通過event.clientX和event.clientY就可以獲取點擊的坐標(biāo),而在火狐下,event對象是不兼容的,需要給事件讀入一個參數(shù)(參數(shù)本身就是事件對象,由系統(tǒng)讀入),用這個參數(shù)來調(diào)用clientX和clientY屬性獲取坐標(biāo)。而“var oEvent=ev||event;”這種寫法,系統(tǒng)會自動獲取為真的一邊,這樣就可以通過一句話完美解決兼容性的問題了。

          說完事件對象后我們來看看事件流?事件流說的簡單一點,其實就是事件跟水一樣從頭到尾流動的過程。我們來看一個關(guān)于事件流的最簡單的小例子:

          <!DOCTYPE HTML>
          <html onclick="alert('html');">
           <head>
           <meta charset="utf-8">
           <title>無標(biāo)題文檔</title>
           <style>
           div {padding:100px;}
           </style>
           </head>
           <body onclick="alert('body');">
           <div style="background:#CCC;" onclick="alert(this.style.background);">
           <div style="background:green;" onclick="alert(this.style.background);">
           <div style="background:red;" onclick="alert(this.style.background);">
           </div>
           </div>
           </div>
          </body>
          </html>

          效果如下:

          當(dāng)我們點擊最里面的一個div時,它會連續(xù)彈出多個框,原因大家應(yīng)該都明白。這里,就涉及到了事件冒泡的知識——在這個程序里,當(dāng)我們點擊了最里面的div并執(zhí)行事件后,還會將這個事件傳遞給父級繼續(xù)執(zhí)行,依次類推,直到html和document。這就是所謂的事件冒泡——事件會隨著層級依次傳遞到底。

          事件冒泡學(xué)完以后大家更多的疑問肯定是,我們能用它來做點什么,畢竟學(xué)了任何知識都是拿來用的,而不是看的。一個小小的結(jié)論是:在我們平時做東西的時候,真正主動去利用時間冒泡去做的事情非常少,甚至可以說,很多時候事件冒泡都會給我們帶來煩惱腦。為什么這么說呢,下面我們來看一個小例子,立刻就能明白了。

          <!DOCTYPE HTML>
          <html>
           <head>
           <meta charset="utf-8">
           <title>無標(biāo)題文檔</title>
           <style>
           #div1 {width:400px; height:300px; background:#CCC; display:none;}
           </style>
           <script>
           window.onload=function ()
           {
           var oBtn=document.getElementById('btn1');
           var oDiv=document.getElementById('div1');
           oBtn.onclick=function (ev)
           {
           var oEvent=ev||event;
           oDiv.style.display='block';
           //alert('按鈕被點擊了');
           oEvent.cancelBubble=true;
           };
          
           document.onclick=function ()
           {
           oDiv.style.display='none';
           //alert('document被點擊了');
           };
           };
           </script>
           </head>
           <body>
           <input id="btn1" type="button" value="顯示" />
           <div id="div1">
           </div>
           </body>
          </html>

          我們試想一下,我們想要實現(xiàn)一個功能:點擊頁面任意地方,都可以讓已經(jīng)顯示的div塊隱藏,根據(jù)我們前面所學(xué)的知識,最好的方法應(yīng)該是給document添加事件。但如果我們直接這么做的話,就會存在下面這個問題:我們在點擊按鈕的時候,這個事件也會被傳遞到其根元素document上,也就是說,點擊了按鈕后,會觸發(fā)兩個事件,div依然會被隱藏。取消冒泡的方式也是通過事件對象,在event對象里有一個屬性叫cancelBubble,當(dāng)我們將它設(shè)置為true的時候,就可以取消該元素的事件冒泡了。

          鼠標(biāo)事件

          下面我們來說一下鼠標(biāo)事件,之前說過了,clientX,clinentY可以獲取鼠標(biāo)的坐標(biāo)。不過,我們僅僅說它是鼠標(biāo)的坐標(biāo),而并沒有說它是鼠標(biāo)的什么坐標(biāo)。現(xiàn)在我們來看一下clientX,clinentY有一些小問題。

          <!DOCTYPE html>
          <html>
           <head>
           <meta charset="utf-8" />
           <title>無標(biāo)題文檔</title>
           <style>
           #div1 {width:200px; height:200px; background:red; position:absolute;}
           </style>
           <script>
           document.onmousemove=function (ev)
           {
           var oEvent=ev||event;
           var oDiv=document.getElementById('div1');
           
           oDiv.style.left=oEvent.clientX+'px';
           oDiv.style.top=oEvent.clientY+'px';
           };</script>
           </head>
           <body>
           <div id="div1">
           </div> 
           </body>
          </html>

          效果如下:

          我們讓div1坐標(biāo)就等于鼠標(biāo)的當(dāng)前坐標(biāo),可以看到我們實現(xiàn)了一個div隨著鼠標(biāo)移動的效果。但這個程序存在一個小小的隱患——例如,現(xiàn)在如果我們把body的高度設(shè)置為2000px,會發(fā)生什么呢?實際上,無論是clientX還是clientY,它們代表的實際含義都是可視區(qū)坐標(biāo),而div則是根據(jù)body來定位的,所以當(dāng)可視區(qū)并不在頁面頂端時,必然會出現(xiàn)鼠標(biāo)和div之間的錯位。這里,我們可以使用scrollTop來解決這個問題。

          <html>
          <head>
           <meta charset="utf-8">
           <title>無標(biāo)題文檔</title>
           <style>
           #div1 {width:200px; height:200px; background:red; position:absolute;}
           </style>
           <script>
           document.onmousemove=function (ev){
           var oEvent=ev||event;
           var oDiv=document.getElementById('div1');
           var scrollTop=document.documentElement.scrollTop||document.body.scrollTop;
           oDiv.style.left=oEvent.clientX+'px';
           oDiv.style.top=oEvent.clientY+scrollTop+'px';
           };
           </script>
          </head>
          <body style="height:2000px;">
           <div id="div1"></div>
          </body>
          </html>

          這樣,無論是否滾動頁面,都不會出現(xiàn)錯位的問題了(不過會出現(xiàn)div抖動的情況,我們以后會有方法解決)。一個小小的經(jīng)驗是:但凡是你用到clientX,clientY的時候一定要加上scrollLeft或者scrollTop,否則很容易出問題。

          現(xiàn)在我們來看一下其另一個例子(這里我們將scroll封裝成一個函數(shù)getPos。

          <!DOCTYPE HTML>
          <html>
          <head>
           <meta charset="utf-8">
           <title>無標(biāo)題文檔</title>
           <style>
           div {width:10px; height:10px; background:red; position:absolute;}
           </style>
           <script>
           function getPos(ev){
           var scrollTop=document.documentElement.scrollTop||document.body.scrollTop;
           var scrollLeft=document.documentElement.scrollLeft||document.body.scrollLeft;
          
           return {x: ev.clientX+scrollLeft, y: ev.clientY+scrollTop};}document.onmousemove=function (ev){
           var aDiv=document.getElementsByTagName('div');
           var oEvent=ev||event;
           var pos=getPos(oEvent);
           for(var i=aDiv.length-1;i>0;i--)
           {
           aDiv[i].style.left=aDiv[i-1].offsetLeft+'px';
           aDiv[i].style.top=aDiv[i-1].offsetTop+'px';
           }
           aDiv[0].style.left=pos.x+'px';
           aDiv[0].style.top=pos.y+'px';
           };
           </script>
          </head>
          <body><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div><div></div>
          </body>
          </html>

          效果如下:

          這里制作出了一串div跟隨著鼠標(biāo)走的特效。我們讓后一個div都跟著前一個div走,第一個div跟著鼠標(biāo)走,就可以實現(xiàn)這種效果了。

          鍵盤事件

          說完鼠標(biāo)事件之后,我們來看看鍵盤事件。通過keyCode,我們可以獲取用戶操作的是哪個按鍵。這里我們需要介紹兩個新事件:onkeydown和onkeyup,分別代表按下鍵盤按鍵和放開鍵盤按鍵的事件。

          這里通過一個小例子來說明他們是怎么用的:

          <!DOCTYPE HTML>
           <html>
           <head>
           <meta charset="utf-8">
           <title>無標(biāo)題文檔</title>
           <script>
           document.onkeydown=function (ev)
           {
           var oEvent=ev||event;
           alert(oEvent.keyCode);
           };
           </script>
           </head>
           <body>
           </body>
          </html>

          可以看到的是,我們輸入一個鍵盤按鍵后,頁面會彈出一個數(shù)字,實際上鍵盤幾乎每個按鍵都有對應(yīng)的keyCode,因此keyCode可以很好地為我們檢測用戶按的是哪個鍵。現(xiàn)在我們來看一個通過keyCode用鍵盤控制div的移動的小例子:

          <html>
           <head>
           <meta charset="utf-8">
           <title>無標(biāo)題文檔</title>
           <style>
           #div1 {width:100px; height:100px; background:#CCC; position:absolute;}
           </style>
           <script>
           document.onkeydown=function (ev)
           {
           var oEvent=ev||event;
           var oDiv=document.getElementById('div1');
           if(oEvent.keyCode==37)
           {
           oDiv.style.left=oDiv.offsetLeft-10+'px';
           }
           else if(oEvent.keyCode==39)
           {
           oDiv.style.left=oDiv.offsetLeft+10+'px';
           }
           };
           </script>
           </head>
           <body>
           <div id="div1"></div>
           </body>
          </html>

          值得注意的一點是,如果我們按住一個方向鍵不動,可以看到div塊會先定住一會兒,然后才開始移動(實際上我們平時打字的時候也是這樣),這里給大家留一個懸念,大家可以自己思考一下如何解決這個問題。除了keyCode外,JS鍵盤事件還有幾個屬性:ctrlKey,altKey,shiftKey等。我們在論壇或微博經(jīng)常可以看到ctrl+回車提交留言的功能,就是通過這些屬性完成的:

          <!DOCTYPE HTML><html>
           <head>
           <meta charset="utf-8">
           <title>無標(biāo)題文檔</title>
           <script>
           window.onload=function ()
           {
           var oTxt1=document.getElementById('txt1');
           var oTxt2=document.getElementById('txt2');
           
           oTxt1.onkeydown=function (ev)
           {
           var oEvent=ev||event;
           
           if(oEvent.keyCode==13 && oEvent.ctrlKey)
           {
           oTxt2.value+=oTxt1.value+'\n';
           oTxt1.value='';
           }
           };
           };
           </script>
           </head>
           <body>
           <input id="txt1" type="text" /><br>
           <textarea id="txt2" rows="10" cols="40"></textarea>
           </body>
          </html>

          oEvent.keyCode==13 && oEvent.ctrlKey代表的就是在按回車的同時按住ctrl鍵——這樣,我們就完成了一個ctrl+回車提交的功能。從下節(jié)課我們會講一些事件更加復(fù)雜,更加高級一些的應(yīng)用。

          我是石川(Blue),如果你覺得我的公眾號還不錯,請多幫我推薦給你的朋友,多謝了。

          作者簡介:前阿里巴巴高級技術(shù)經(jīng)理,現(xiàn)開課吧技術(shù)學(xué)院院長。精通C/C++、Java、Python、前端開發(fā)等多種開發(fā)技術(shù),曾參與淘寶網(wǎng)的早期建設(shè)和優(yōu)化,擁有豐富的企業(yè)級系統(tǒng)開發(fā)經(jīng)驗,對HTML5移動端互聯(lián)網(wǎng)技術(shù)及生態(tài)體系有深厚的造詣。


          主站蜘蛛池模板: 亚洲夜夜欢A∨一区二区三区 | 波多野结衣一区在线| 日韩经典精品无码一区| 国产免费一区二区视频| 精品亚洲福利一区二区| 国产一区二区电影在线观看| 无码人妻一区二区三区兔费| 精品一区二区三区免费| 国产乱码精品一区二区三区四川| 黑人大战亚洲人精品一区| 国产精品一区二区无线| 秋霞午夜一区二区| 亚洲成a人一区二区三区| 国产精品视频第一区二区三区| 亚洲av无码一区二区三区四区| 精品国产一区二区三区香蕉事 | 成人国内精品久久久久一区| 日韩精品人妻一区二区三区四区| 免费无码毛片一区二区APP| 精品一区二区三区3d动漫| 秋霞鲁丝片一区二区三区| 亚洲一区无码精品色| 国产裸体歌舞一区二区| 亚洲色偷精品一区二区三区| 亚洲成a人一区二区三区| 免费无码一区二区| 国产肥熟女视频一区二区三区| 亚洲中文字幕乱码一区| 亚洲福利一区二区精品秒拍| 国产一区二区三区高清视频| 能在线观看的一区二区三区| 亚洲Av无码国产一区二区| 精品欧洲av无码一区二区14| 无码人妻精品一区二区三区东京热| 精品一区二区三区四区在线| 亚洲性日韩精品一区二区三区 | 一本色道久久综合一区| 日本高清一区二区三区| 亚洲一区二区三区国产精华液| 99久久综合狠狠综合久久一区| 国产一区二区三区免费|