在直播軟體搭建中有哪些可以實現瀑布流的的方法?

雲豹科技程式設計師 發表於 2021-10-09

介紹

相信大家對瀑布流並不陌生,瀑布流又稱瀑布流式佈局。是直播軟體搭建時比較流行的一種網站頁面佈局,視覺表現為參差不齊的多欄佈局,隨著頁面滾動條向下滾動,這種佈局還會不斷載入資料塊並附加至當前尾部。

他具有以下特點:

1、直播軟體搭建展示頁面以圖片為主
2、圖片尺寸不一交錯排布
3、空間使用更加充分,節省了空間

既然瀑布流適用直播軟體搭建場景那麼多,我們本期就是以瀑布流在前端的三種實現方案,以及他們使用的優缺來探索。

正文

A. column方案

column可以指定容器下元素列的寬度和數量

columns: column-width column-count;

但我們瀑布流用到的css屬性是:

  • column-count:指定列數
  • column-gap:列之間的差距

實現

<ul class="img-wrapper">
    <li><img src="./image/1.jpg" alt=""></li>
    <!-- 
        ... 
        ... 
        ... 
    -->
    <li><img src="./image/20.jpg" alt=""></li></ul>

我們在html中先放入二十張圖片作為本次演示。

.img-wrapper{
    column-count: 4;
    column-gap: 10px;
    
    counter-reset: count;
    width: 960px;
    margin: 0 auto;}.img-wrapper>li{
    position: relative;
    margin-bottom: 10px;}

這裡我們用column-count設定為了4列,column-gap間距為10畫素。就這麼簡單的兩句我們就實現了直播軟體搭建中的一個瀑布流。
對了,為了我們更直觀的觀察排列規律,我們用偽類再做個計數器(後面的方案都會出現該偽類和html結構)。

.img-wrapper>li>img{
    width: 100%;
    height: auto;
    vertical-align: middle;}.img-wrapper>li::after{
    counter-increment: count;
    content: counter(count);
    width: 2em;
    height: 2em;
    background-color: rgba(0,0,0,0.9);
    color: #ffffff;
    line-height: 2em;
    text-align: center;
    position: absolute;
    font-size: 1em;
    z-index: 2;
    left: 0;
    top: 0;}

優點

1、在直播軟體搭建中實現簡單,僅需兩行核心程式碼。
2、圖片自動填充不用考慮圖片載入狀態。

缺點

1、相容性仍有些不盡人意。
2、直播軟體搭建排列規律永遠都是先上下再左右,無法控制,動態載入會出現嚴重問題。

B. flex方案

用到的html結構與偽類計數與A方案相同,這裡不再過多佔用篇幅。
這個方案用到了彈性盒子,你沒聽錯,用彈性佈局也可以實現一個瀑布流,雖然很多侷限性,但是也可以,在一定需求場景內使用。

實現

.img-wrapper{
    display: flex;
    flex-wrap: wrap;
    flex-direction: column;
    height: 1300px;}.img-wrapper>li{
    position: relative;
    width: calc(100% / 4);
    padding: 5px;
    box-sizing: border-box;}

我們對父容器設定彈性盒後,因為直播軟體搭建瀑布流是多行的所以還要flex-wrap設定wrap,並且flex-direction還要設定為column。最關鍵的是一定要設定一個高度。當然在其子元素用百分比設定要顯示幾列。
就這樣,flex也可以實現一個瀑布流了。
當然,我們如果想在直播軟體搭建時改變一定程度的序列優先順序,可以改變css的order屬性。

.img-wrapper>li:nth-child(4n+1){
    order: 1;}.img-wrapper>li:nth-child(4n+2){
    order: 2;}.img-wrapper>li:nth-child(4n+3){
    order: 3;}.img-wrapper>li:nth-child(4n){
    order: 4;}

優點

1、在直播軟體搭建中實現相對簡單。
2、圖片自動填充不用考慮圖片載入狀態。
3、順序在一定程度上可以改變。

缺點

1、高度是固定的,很難做活。
2、順序雖然可以改變,但是仍然不靈活,不盡人意。

C. js+absolute方案

js實現瀑布流的話,我們可以考慮把子元素全部設定成絕對定位。然後監聽圖片載入,如果載入完就把子元素設定其對應的位置,逐個塞到父容器中。

實現

import Waterfall from "./js/Waterfall"
 window.onload = new Waterfall({
    $el: document.querySelector(".img-wrapper"),
    count: 4,
    gap: 10})

我們先在配置階段把父容器和列數,間距設定好。
然後再去寫Waterfall類:

export default class Waterfall {
    constructor(options) {
        this.$el = null;             // 父容器
        this.count = 4;              // 列數
        this.gap = 10;               // 間距
        Object.assign(this, options);
        this.width = 0;              // 列的寬度
        this.items = [];             // 子元素集合
        this.H = [];                 // 儲存每列的高度方便計算
        this.flag = null;            // 虛擬節點集合
        this.init();
    }
    init() {
        this.items = Array.from(this.$el.children);
        this.reset();
        this.render();
    }
    reset() {
        this.flag = document.createDocumentFragment();
        this.width = this.$el.clientWidth / this.count;
        this.H = new Array(this.count).fill(0);
        this.$el.innerHTML = "";
    }
    render() {
        const { width, items,flag,H,gap } = this;
        items.forEach(item => {
            item.style.width = width + "px";
            item.style.position = "absolute";
            let img = item.querySelector("img");
            if(img.complete){
                let tag = H.indexOf(Math.min(...H)); 
                item.style.left = tag * (width + gap) + "px";
                item.style.top = H[tag] + "px";                  
                H[tag] += img.height*width/ img.width + gap;
                flag.appendChild(item);
            }
            else{
                img.addEventListener("load", () => {
                    let tag = H.indexOf(Math.min(...H)); 
                    item.style.left = tag * (width + gap) + "px";
                    item.style.top = H[tag] + "px";                  
                    H[tag] += img.height*width/ img.width + gap;
                    flag.appendChild(item);
                    this.$el.append(flag);
                })
            }
        })
        this.$el.append(flag);
    }}

我們這裡就簡單實現了一下:

  • 初始化,計算出列寬來,將H作為列高儲存器,4列那麼就是[0,0,0,0]。然後收集子元素後,清除父容器內容。
  • 遍歷其子元素,設定其都為絕對定位,設定其列寬。後監聽其下的圖片載入是否完畢。
  • 如果載入成功,那麼計算應該在的位置,瀑布流的常規原則是哪一列數值最小就在那一列上設定新圖片。當然他的相對高度和間距也要計算出來,同時在H當前列上要把高度存起來。
  • 每次圖片載入完就更新虛擬節點到父容器中。

優點

1、在直播軟體搭建中控制靈活,隨意擴充套件。
2、也可以無限載入,不用過多考慮相容問題。
3、同時可以新增諸多動畫來增強使用者體驗。

缺點

1、在直播軟體搭建中實現相對複雜。
2、圖片填充需要考慮圖片載入狀態。
3、效能遜色於純css實現。

思考

以上便是在直播軟體搭建中瀑布流實現的三種方式,其實絕大部分的商業級都是js實現的瀑布流,本質實現起來並不麻煩,我們有時間可以自己封裝一套。

本文轉載自網路,轉載僅為分享乾貨知識,如有侵權歡迎聯絡雲豹科技進行刪除處理
原文連結:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69996194/viewspace-2795131/,如需轉載,請註明出處,否則將追究法律責任。