How to realize waterfall layout with native js [detailed version!!!]

How to implement waterfall layout with native js?

Concept:

Waterfall flow, also known as waterfall flow layout. It is a relatively popular website page layout, which is visually represented as an uneven multi column layout. As the page scrolls downward, this layout will also constantly load data blocks and attach them to the current tail. The earliest website adopting this layout is Pinteres, which has gradually become popular in China. Most domestic fresh stations are basically of this style.

Layout features:

  1. Dazzling: the whole page is dominated by pictures, and pictures of different sizes are arranged according to certain rules.

  2. Aestheticism: the style of pictures is mainly aestheticism.

  3. Simple operation: when browsing the website, you just need to slide the mouse wheel slightly, and all the wonderful pictures can be presented in front of you.

Application scenario:

  • For example, the following figure is Suning's official website

  • For example, the following figure: website layout

Principle:

The waterfall layout is characterized by equal width and unequal height. In order to minimize the gap in the last line, you need to place the picture below the shortest picture in the first line from the second line, and so on. The parent element is set to relative positioning, and the element where the picture is located is set to absolute positioning. Then locate each element by setting the top and left values.

To put it simply:

  1. Fix the width of the picture, divide the size of the browser window by the width of each picture, and find the number of columns to be divided

  2. Position each picture

  3. Each time the column with the minimum height is found, the picture is added to the column

Process oriented - specific code:

<!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>Process oriented: simulating waterfall flow</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        
        .box {
            width: 600px;
            margin: 0 auto;
            border: 1px solid #000;
            position: relative;
        }
        
        .box>div {
            width: 100px;
            border: 1px solid pink;
            box-sizing: border-box;
            position: absolute;
        }
    </style>
</head>

<body>
    <div class="box">
    </div>

    <script>
        // Waterfall core:
        // 1. Fix the width of the picture, divide the size of the browser window by the width of each picture, and find the number of columns to be divided
        // 2. Position each picture
        // 3. Each time the column with the minimum height is found, add the picture to the column
        var box = document.querySelector('.box');

        // Function to generate random numbers: get a random integer between two numbers (excluding the maximum and minimum values)
        function rdNum(min, max) {
            return Math.ceil(Math.random() * (max - min)) + min
        }

        // Encapsulation function: to obtain the minimum value in the array
        function getMin(abc) {
            return Math.min.apply(null, abc);
        }

        // Record the height of each element in each column
        var arr = [0, 0, 0, 0];
        // Dynamically generate random height, go to the smallest column in the array, and add up the numbers
        for (var i = 0; i < 20; i++) {
            // Get the minimum value in each column array
            var minVal = getMin(arr);
            // Gets the index of the minimum value of the array for each column
            var index = arr.findIndex(function(item, index) {
                return item === minVal;
            });
            // Generate a random number --- that is, the height of each div
            var randomNum = rdNum(40, 150);
            // Dynamically create div Tags
            var div = document.createElement('div');
            // The content of div is index
            div.innerText = i;
            // box width
            var boxWidth = box.offsetWidth;
            console.log(boxWidth);
            // Set the height of div
            div.style.height = randomNum + 'px';
            console.log(div.style.height);
            // Set the distance from each div to the left
            div.style.left = index * (((boxWidth - 4 * 100) / (4 - 1)) + 100) + 'px';
            // The distance to the top is the minimum value of each column
            div.style.top = minVal + 'px';
            box.appendChild(div);

            // The random number is added to the array element of the smallest column in the array
            arr[index] += randomNum;
            //randomNum: the height of each div / / index: the index to get the minimum value of the array in each column / / arr[index] is the value of the minimum array element in each column
            console.log(arr)
        }
        box.style.height = Math.max.apply(null, arr) + 'px'
    </script>
</body>

</html>

Object oriented - specific code:

<!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>Object oriented: simulating waterfall flow</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        
        .box {
            width: 600px;
            margin: 0 auto;
            border: 1px solid red;
            position: relative;
        }
        
        .box>div {
            border: 1px solid orange;
            box-sizing: border-box;
            position: absolute;
        }
        
        .container {
            width: 800px;
            margin: 100px auto;
            border: 1px solid #000;
        }
        
        .container>div {
            border: 1px solid orange;
            box-sizing: border-box;
        }
    </style>
</head>

<body>
    <div class="box"></div>
    <div class="container"></div>
    <script>
        function Pubu(obj) {
            this.box = document.querySelector(obj.el);
            this.column = obj.column;
            this.width = obj.width;
            this.show();
        }

        Pubu.prototype.rdNum = function(max, min) {
            return Math.ceil(Math.random() * (max - min)) + min;
        }

        Pubu.prototype.getMin = function(abc) {
            return Math.min.apply(null, abc);
        }

        Pubu.prototype.getIndex = function(abc, def) {
            return abc.findIndex(function(item) {
                return item === def;
            })
        }

        Pubu.prototype.createDv = function(i, randomNum, index, minVal) {
            var dv = document.createElement('div');
            dv.innerText = i;
            dv.style.width = this.width + 'px';
            dv.style.position = 'absolute';
            dv.style.height = randomNum + 'px';
            dv.style.left = index * ((this.box.offsetWidth - this.width * this.column) / (this.column - 1) + this.width) + 'px';
            dv.style.top = minVal + 'px';
            this.box.appendChild(dv);
        }

        Pubu.prototype.show = function() {
            this.box.style.position = 'relative';
            var arr = new Array(this.column);
            arr.fill(0);
            for (var i = 0; i < 20; i++) {
                var minVal = this.getMin(arr);
                var index = this.getIndex(arr, minVal);
                var randomNum = this.rdNum(40, 150);
                this.createDv(i, randomNum, index, minVal);
                arr[index] += randomNum;
                this.box.style.height = Math.max.apply(null, arr) + 'px';
            }
        }

        new Pubu({
            el: '.box',
            column: 4,
            width: 110
        })

        new Pubu({
            el: '.container',
            column: 7,
            width: 100
        })
    </script>
</body>
  • design sketch:

Tags: Front-end Javascript css

Posted by Obsession on Sun, 11 Sep 2022 02:45:34 +0930