原生js实现图片瀑布流布局,注释超详细

百般思念 提交于 2020-08-11 12:36:21

完整代码:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>瀑布流</title>
        <style type="text/css">
            img {
                width: 300px;

            }

            li {
                position: absolute;
                s left: 0;
                top: 0;
                list-style: none;
            }

            ul {
                margin: 0 auto;
                position: relative;
            }

            * {
                margin: 0;
                padding: 0;
            }
        </style>
    </head>
    <body>
        <ul></ul>
    </body>
    <script src="utils.js"></script>
    <script>
        let ul = document.querySelector('ul'), //获取ul标签
            list = ul.children, //动态更新ul里面的子元素
            teep = 10, //间距
            width = 300, //每张图片的宽度
            cols = Math.floor(document.documentElement.clientWidth / (width + teep)), //计算有多少列
            hh = [], //存取每一列的高度
            num = 0, //记录加载完成图片数量
            om = 0 //记录已经排版完成的li数量
        ul.style.width = cols * (width + teep) - teep + 'px' //计算ul的宽度
        get({ //提前封装好的方法
                url: 'http://rap2.taobao.org:38080/app/mock/256901/json'
            })
            .then(a => { //请求数据成功
                a = JSON.parse(a).img
                let dom = document.createDocumentFragment() //创建文档碎片
                a.forEach((item, index) => { //有多少条数据就创建多少个li
                    let li = document.createElement('li')
                    li.innerHTML = `<img src="${item.src}">`
                    dom.appendChild(li) //把li添加到文档碎片中
                })
                ul.appendChild(dom) //将文档碎片添加到ul中
                let imgs = Array.from(list).reduce((curr, item, index) => { //将每张img节点组成数组
                    if (om <= index) {
                        curr.push(item.querySelector('img'))
                    }
                    return curr
                }, [])

                Array.from(imgs).forEach(item => { //遍历每张图片
                    item.onload = () => { //该图片加载完成
                        num++
                        if (num === imgs.length) { //图片都加载完成了
                            for (let i = om; i < list.length; i++) { //遍历ul下的每个li
                                if (i < cols) { //给第一行每个li设置left/top值
                                    list[i].style.left = (width + teep) * i + 'px'
                                    list[i].style.top = teep + 'px'
                                    hh.push(list[i].offsetHeight + teep * 2)
                                } else { //除了第一行剩下的li
                                    let minHeight = Math.min(...hh) //求出最小高度
                                    let minIndex = hh.indexOf(minHeight) //求出最小高度的索引值
                                    list[i].style.left = (width + teep) * minIndex + 'px'
                                    list[i].style.top = minHeight + 'px'
                                    hh[minIndex] = list[i].offsetHeight + minHeight + teep //将最小高度更新
                                }
                            }
                            om = list.length //更新排版完成数量
                            ul.style.height = ul.scrollHeight + 'px' //给ul设置高度
                        }
                    }
                })
            })
    </script>
</html>

复制以上代码,并把下面这一段js代码复制到js文件中放到和上面代码同级的地方并引入,即可运行浏览效果

代码如下:

function ajax(obj, fn) {
    let ajx = new XMLHttpRequest() //创建ajax实例
    obj.type = obj.type ? obj.type : 'get' //判断type存不存在,不存在默认等于get
    let data = '' //向后端发送的数据
    if (obj.data) { //判断是否存在
        for (let i in obj.data) {
            data += i + '=' + obj.data[i] + '&' //键值拼接成name=zhagnsan&age=18形式
        }
        let k = data.split('')
        k.splice(data.length - 1, 1)
        data = k.join('')
    }
    if (obj.type == 'get') { //处理get请求发送数据
        ajx.open(obj.type, obj.url + '?' + data) //地址上拼接数据
        ajx.send()
    } else if (obj.type == 'post') { //处理post请求发送数据
        ajx.open(obj.type, obj.url)
        ajx.setRequestHeader('content-type', 'application/x-www-form-urlencoded') //设置请求头
        ajx.send(data) //发送数据
    }
    ajx.onreadystatechange = () => {
        if (ajx.readyState == 4) {
            if (ajx.status == 200) {
                /*
                将得到的数据传给回调函数
                短路写法,如果不传fn为空不会执行,有值就执行
                */
                fn && fn(ajx.responseText)
            }
        }
    }
}

// ajax({ //调用封装的方法
//     type: 'get', //可以不写,默认get
//     url: 'http://localhost/day02/api/gouwu.php', //请求地址
//     data: { //需要传输的数据,可选
//         name: 'zhangsan',
//         age: 18
//     }
// },a=>{//处理的到的数据
//     console.log(a)
// })

function jsonp(obj) {
    let sc = document.createElement('script')
    let data = ''
    if (obj.data) {
        for (let i in obj.data) {
            data += `${i}=${obj.data[i]}&`
        }
        data = data.slice(0, -1)
        sc.setAttribute('src', obj.url + `?cd=${obj.cd}&${data}`)
    } else {
        sc.setAttribute('src', obj.url + `?cd=${obj.cd}`)
    }

    document.body.appendChild(sc)
}

// jsonp({
//     url:'http://localhost/day02/api/gouwu.php',
//     cd:'fn'
// },a=>{
//     console.log(a)
// })

function get(obj) {
    return new Promise((resolve, reject) => {
        let a = new XMLHttpRequest()
        let data = ''
        if (obj.data) {
            for (let i in obj.data) {
                data += i + '=' + obj.data[i] + '&'
            }
            data = data.slice(0, -1)
            a.open('get', obj.url + '?' + data)
        }else{
            a.open('get', obj.url)
        }
        a.send()
        a.onreadystatechange = () => {
            if (a.readyState === 4) {
                if (a.status === 200) {
                    resolve(a.responseText)
                } else {
                    reject()
                }
            }
        }
    })

}
// get({//调用格式
//     url:'http://localhost/day02/api/gouwu.php',//获取的地址
//     data:{ //可不写
//         a:1,
//         b:2
//     }
// }).then(a=>{//获取数据成功
//     console.log(a)
// }).catch(err=>{ //获取数据失败
//     console.log(err)
// })

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!