移動web必會技能-圖片居中處理

咱們在平常使用移動APP的時候,特別是一些資訊類的APP,都會有圖片展現的相關UI,例現在日頭條APP的單大圖和三圖模式,以下圖: 單圖: javascript

圖片描述

三圖: css

santu

或者是相似微博或者朋友圈這種9宮格的圖片展現效果,以下圖: html

圖片描述

對於這些圖片,若是你單純的覺得直接用幾個<img>,配置一下src地址,而後渲染在頁面上,那就大錯特錯了😂,對於這種類型的UI展現,咱們須要明確下面幾點:java

  1. 圖片在上傳後,會有不一樣的大小,有的是長圖(長大於寬),有的是寬圖(寬大於長),或者是一些接近正方形的圖片。
  2. 在保證圖片本來長寬比的狀況下,要想將圖片顯示在一個正方形的區域內,或者是固定長寬的區域內,是必需要截取一部分圖片展現的。
  3. 採用CSS或者JavaScript均可以實現這種效果。

你們能夠看下面這幾張圖,紅色的是圖片自己,虛線框就是展現出來的區域,便於理解: 寬圖: web

圖片描述

長圖: 網絡

圖片描述

CSS的background-size

單獨使用CSS的話,咱們能夠輕鬆的實現上面這個效果,主要利用到的屬性就是background-size這個屬性,能夠先從概念上了解一下這個屬性:app

background-size: length|percentage|cover|contain
複製代碼
  • length:設置背景圖像的高度和寬度。第一個值設置寬度,第二個值設置高度。若是隻設置一個值,則第二個值會被設置爲 "auto"。學習

  • percentage:以父元素的百分比來設置背景圖像的寬度和高度。第一個值設置寬度,第二個值設置高度。若是隻設置一個值,則第二個值會被設置爲 "auto"。ui

  • cover:在保持圖像的縱橫比的前提下,以適合鋪滿整個容器並將圖像縮放成將徹底覆蓋背景定位區域的最小大小。優勢是背景圖片所有覆蓋所屬元素區域;缺點是超出的部分會被隱藏。url

  • contain:與cover相反,在保持圖像的縱橫比的狀況下,以適合鋪滿整個容器,並將圖像縮放成將適合背景定位區域的最大大小。優勢是圖片不會出現變形,同時背景圖片被徹底展現出來;缺點是當所屬元素的寬高比與背景圖片的寬高比不一樣時,會出現背景留白。

咱們能夠採用background-size:cover;比較合適,在保證縱橫比的狀況下,若是圖片超過背景區域,將多餘部分隱藏便可,同時設置background-position: center center;將主要內容居中顯示。

CSS的object-fit

HTML5新增的<img />標籤的屬性object-fit也可知足需求,可是要注意兼容性

object-fit: fill|contain|cover|scale-down|none|initial|inherit;
複製代碼

主要用到如下屬性:

  • fill:默認,不保證保持原有的比例,內容拉伸整個內容容器。

  • contain:保持原有尺寸比例,內容被縮放,參考background-size:contain。

  • cover:保持原有尺寸比例,但部份內容可能被剪切,參考background-size:cover。

  • scale-down:保持原有尺寸比例。內容的尺寸與 none 或 contain 中的一個相同,取決於它們兩個之間誰獲得的對象尺寸會更小一些,更加智能。

代碼效果demo:

首先你們能夠打開 app.nihaoshijie.com.cn/mypro/image… 來看一下效果。

若是是一個單大圖,咱們能夠直接給一個div設置background-image,而後設置background-image便可,代碼以下:

<div class="one-img"></div>
複製代碼
.one-img {
      width: 100%;
      padding-top: 50%;
      background-image: url('https://gpic.qpic.cn/gbar_pic/osL7w6JTehzgKuaKrPEJ8V3lia1zoLaPShY05MdBofOpBye0yNpRXYA/');
      background-size: cover;
      background-position: center center;
    }
複製代碼

效果以下圖:

圖片描述
代碼中使用的圖片來源於網絡

這裏有一個知識點,咱們若是想要實現屏幕的適配,div的長寬是毫不能夠寫成固定值px的,因此寬度能夠設置成100%,這樣若是在大屏幕下,圖片自身會變大,可是高度咱們是沒法設置一個合適的百分比的,這裏咱們藉助了padding-top屬性,將padding-top設置成百分比,可讓一個div的高度被撐開,具體的值依據寬度的值,即50%表示是寬度(width:100%)的50%。

三張連續圖,代碼以下:

<div class="three-img-other-wrap">
     <div class="three-img-other-1 img-1"></div>
     <div class="three-img-other-2 img-2"></div>
     <div class="three-img-other-3 img-3"></div>
   </div>
複製代碼
.three-img-wrap {
     margin-top: 5px;
     width: 100%;
     overflow: hidden;
   }
.three-img {
     float: left;
     width: 33.3333%;
     padding-top: 33.3333%;
     border-right: 1px solid #fff;
     background-size: cover;
     background-position: center center;
     box-sizing: border-box;
   }
複製代碼

效果以下:

圖片描述

每一個div,設置float:left來實現橫向平鋪,注意一下這裏不建議使用display:inline-block,會出現都得空隙,若是想要實現9宮格,將這3個複製2份便可。

或者是另一種3+2+1顯示方式圖,代碼以下:

.three-img-other-wrap {
      margin-top: 5px;
      width: 100%;
      overflow: hidden;
}

.three-img-other-1 {
      width: 66.6666%;
      padding-top: 66.6666%;
      float: left;
      border-right: 1px solid #fff;
      background-size: cover;
      background-position: center center;
      box-sizing: border-box;
    }
.three-img-other-2 {
      width: 33.3333%;
      padding-top: 33.3333%;
      float: left;
      border-bottom: 1px solid #fff;
      background-size: cover;
      background-position: center center;
      box-sizing: border-box;

}
.three-img-other-3 {
      width: 33.3333%;
      padding-top: 33.3333%;
      float: left;
      background-size: cover;
      background-position: center center;
      box-sizing: border-box;
}
複製代碼
<div class="three-img-other-wrap">
   <div class="three-img-other-1 img-1"></div>
   <div class="three-img-other-2 img-2"></div>
   <div class="three-img-other-3 img-3"></div>
</div>
複製代碼

效果以下:

圖片描述

圖片之間的縫問題:

從上面的效果圖來看,每張圖片之間都有必定的間距(通常是1px-3px之間),在這裏咱們若是使用margin來實現的話,咱們是沒法設置一個具體的數值的,由於咱們的長寬都是採用百分比,margin也必須採用百分比,不然會出現錯亂,可是在此場景下margin不適合採用百分比,因此咱們採用border邊框來模擬這個間距:

border-right: 1px solid #fff;
box-sizing: border-box;
複製代碼

須要注意box-sizing: border-box;,這樣border將的長度將會計算在整個寬度裏面,即border+width等於具體的設置的百分比。

採用JavaScript來實現:

其實從代碼的優雅程度上來講,採用咱們上面講解的純Css的方法是比較好的一種方法,可是也有弊端: 1. 沒法監聽圖片的加載成功和失敗事件,例如onerror或者onload。這會致使咱們沒法給加載失敗的圖片一個默認的顯示圖。 2. 咱們在實現圖片懶加載的邏輯時,div+background-image這種方式相交於<img>方式須要寫更多的邏輯。

在這裏給你們介紹一下div+background-image<img>之間的區別:

在網頁加載的過程當中,以css背景圖存在的圖片background-image會等到結構加載完成(網頁的內容所有顯示之後)纔開始加載,而html中的標籤img是網頁結構(內容)的一部分會在加載結構的過程當中加載,換句話講,網頁會先加載標籤<img>的內容,再加載背景圖片background-image,若是你用引入了一個很大的圖片,那麼在這個圖片下載完成以前,<img>後的內容都不會顯示。而若是用css來引入一樣的圖片,網頁結構和內容加載完成以後,纔開始加載背景圖片,不會影響你瀏覽網頁內容。

若是咱們想要用JavaScript加<img>,來實現這種效果,基本邏輯是:

  1. 首先須要知道圖片的寬高。
  2. 給每一個<img>設置src以後,須要同時設置一個父div用來包裹這個<img>
  3. 同時父div須要設置overflow:hidden,而後根據外框的大小,和圖片的寬高,動態設置<img>的margin或者left,top來產生位移。

這裏的核心是如何根據外框的寬高來動態計算出圖片的位移,咱們能夠封裝一個方法來計算,具體的邏輯能夠看註釋:

getImagePosition(img, cW, cH) {
    // cW爲外框寬度,// cW爲外框高度,
    img.marginTop = img.marginLeft = 0;

    // img.h表示圖片自己高度,img.height表示計算設置以後的高度
    // img.w表示圖片自己高度,img.width表示計算設置以後的高度

    img.width = cW;
    img.height = cH;

    // 長圖 優先設置寬度,而後長圖居中
    if (img.h * cW / img.w > cH) {
        img.height = img.h * cW / img.w;
        img.marginTop = (cH - img.height) * 0.5 // 0.5表示居中
    } else {// 寬圖 優先設置高度度,而後寬圖居中
        img.width = img.w * cH / img.h;
        img.marginLeft = (cW - img.width) * 0.5 // 0.5表示居中
    }

    return img;
}
複製代碼

在計算出圖片位移後,外框的寬高也可使用JavaScript來動態設置,例如屏幕寬度的三分之一或者是圖片寬度的三分之二,代碼以下:

document.body.clientWidth * 0.5
document.body.clientWidth * 2 / 3
複製代碼

在衆多的移動web技能中,圖片居中處理是一個很是重要的技能,也是用的比較多的一種技能,固然還有一些極端狀況例如遇到麪條圖,或者是長寬小於10px的這種很是小的圖片,可能須要單獨特殊邏輯處理了。固然若是你想要了解更多的移動web技能,歡迎訂閱這篇專欄,感謝支持。

本文向您推薦了慕課網的專欄課程《從0到1 實戰朋友圈移動Web App開發》,但願小夥伴們能經過這門課程收穫滿滿,祝你們學習進步。

相關文章
相關標籤/搜索