原生css,js和vue实现图片瀑布流

两种实现图片瀑布流方式

1.css实现(column-count)

<html>
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>纯css实现图片瀑布流title>
    <style>
    .waterfall_container{
      column-count: 3;
      column-gap: 0px;
      width:60%;
      text-align: center;
    }
    .waterfall_item {
      -webkit-column-break-inside: avoid;
      break-inside: avoid;
      counter-increment: item-counter;
      padding-top:5px;
    }
    .waterfall_item img{
      width:90%;
    }
    .waterfall_item p{
      font-size:12px;
      text-align: center;
      margin:8px 0;
    }
    @media screen and (max-width:800px){
    .waterfall_container{
      width:100%;
      column-count: 2;
    }
    }
    style>
  head>
  <script src="https://cdn.bootcss.com/vue/2.6.10/vue.common.dev.js">script>
  <body>
    <div class="waterfall_container" id="app">
      <div class="waterfall_item" v-for="item in items">
        <img :src="'http://23.106.136.165/files/files/yushun/'+item[0]">
        <p>{{item[1]}}p>
      div>
    div>
  body>
  <script type="text/javascript">
    new Vue({
      el:"#app",
      data:{
        items:[]
      },
      methods:{
        get_result(){
          let that=this;
          setTimeout(function(){
            that.items=[["static/news_images/3536162/20171230113354-3e4ab1e1.jpg", "\u7cbe\u9009\u9762\u79ef72\u5e73\u73b0\u4ee3\u4e8c\u5c45\u5ba2\u5385\u5b9e\u666f\u56fe\u7247\u5927\u5168"], ["static/news_images/3536162/20171230113356-4b0a4dba.jpg", "2018\u7cbe\u900983\u5e73\u65b9\u4e8c\u5c45\u5ba2\u5385\u73b0\u4ee3\u88c5\u4fee\u8bbe\u8ba1\u6548\u679c\u56fe\u7247\u5927\u5168"], ["static/news_images/3536162/20171230113443-ef9a63d4.jpg", "\u7cbe\u900978\u5e73\u7c73\u4e8c\u5c45\u9910\u5385\u73b0\u4ee3\u88c5\u4fee\u6548\u679c\u56fe"], ["static/news_images/3536162/20171230113400-c075a845.jpg", "\u7cbe\u9009\u9762\u79ef86\u5e73\u73b0\u4ee3\u4e8c\u5c45\u5ba2\u5385\u88c5\u4fee\u8bbe\u8ba1\u6548\u679c\u56fe\u7247\u6b23\u8d4f"], ["static/news_images/3536162/20171230113434-a79ca815.jpg", "2018\u7cbe\u9009\u9762\u79ef70\u5e73\u73b0\u4ee3\u4e8c\u5c45\u9910\u5385\u88c5\u4fee\u8bbe\u8ba1\u6548\u679c\u56fe\u7247"], ["static/news_images/3536162/20171230113351-b9200e9f.jpg", "\u70ed\u95e8\u9762\u79ef78\u5e73\u73b0\u4ee3\u4e8c\u5c45\u5ba2\u5385\u88c5\u4fee\u6b23\u8d4f\u56fe\u7247\u5927\u5168"], ["static/news_images/3536162/20171230113419-66a901f7.jpg", "\u7cbe\u900988\u5e73\u7c73\u4e8c\u5c45\u5367\u5ba4\u73b0\u4ee3\u88c5\u4fee\u8bbe\u8ba1\u6548\u679c\u56fe\u7247\u5927\u5168"], ["static/news_images/3536162/20171230113405-090f969e.jpg", "201877\u5e73\u7c73\u4e8c\u5c45\u5ba2\u5385\u73b0\u4ee3\u88c5\u4fee\u5b9e\u666f\u56fe\u7247\u5927\u5168"], ["static/news_images/3536162/20171230113446-c61b8e2a.jpg", "\u70ed\u95e877\u5e73\u7c73\u4e8c\u5c45\u8863\u5e3d\u95f4\u73b0\u4ee3\u8bbe\u8ba1\u6548\u679c\u56fe"], ["static/news_images/3536162/20171230113409-67baab71.jpg", "2018\u73b0\u4ee3\u4e8c\u5c45\u53a8\u623f\u88c5\u4fee\u6548\u679c\u56fe\u7247\u5927\u5168"]];
          },1000)
      },
    },
    created(){
      this.get_result();//模拟请求数据
    },
    updated(){
    }
    })
  script>
  html>

效果图:

2.js计算实现(absolute)

<html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>js实现图片瀑布流(style:absolute)title>
  <style>
    .waterfall_container{
      width:50%;
    }
    .waterfall_item {
      padding-top:10px;
      opacity: 0;
      width:33.33%;
    }
    .waterfall_item img{
      width:90%;
    }
    .waterfall_item p{
      font-size:12px;
      text-align: center;
      margin:5px 0;
    }
    *{
      transition: opacity 0.1s;
    }
    @media screen and (max-width:800px){
    .waterfall_container{
      width:100%;
    }
    .waterfall_item{
      width:50%;
    }
    .waterfall_item p{
      font-size:10px;
    }
    }
  style>
head>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.common.dev.js">script>
<body>
  <div id="app">
    <div class="waterfall_container">
      <div class="waterfall_item" v-for="item in items">
        <img :src="'http://23.106.136.165/files/files/yushun/'+item[0]" waterfall>
        <p>{{item[1]}}p>
      div>
    div>
  div>
body>
<script type="text/javascript">
  new Vue({
    el:"#app",
    data:{
      items:[]
    },
    methods:{
      get_result(){
        var that=this;
        setTimeout(function(){
          that.items=[["static/news_images/3536162/20171230113354-3e4ab1e1.jpg", "\u7cbe\u9009\u9762\u79ef72\u5e73\u73b0\u4ee3\u4e8c\u5c45\u5ba2\u5385\u5b9e\u666f\u56fe\u7247\u5927\u5168"], ["static/news_images/3536162/20171230113356-4b0a4dba.jpg", "2018\u7cbe\u900983\u5e73\u65b9\u4e8c\u5c45\u5ba2\u5385\u73b0\u4ee3\u88c5\u4fee\u8bbe\u8ba1\u6548\u679c\u56fe\u7247\u5927\u5168"], ["static/news_images/3536162/20171230113443-ef9a63d4.jpg", "\u7cbe\u900978\u5e73\u7c73\u4e8c\u5c45\u9910\u5385\u73b0\u4ee3\u88c5\u4fee\u6548\u679c\u56fe"], ["static/news_images/3536162/20171230113400-c075a845.jpg", "\u7cbe\u9009\u9762\u79ef86\u5e73\u73b0\u4ee3\u4e8c\u5c45\u5ba2\u5385\u88c5\u4fee\u8bbe\u8ba1\u6548\u679c\u56fe\u7247\u6b23\u8d4f"], ["static/news_images/3536162/20171230113434-a79ca815.jpg", "2018\u7cbe\u9009\u9762\u79ef70\u5e73\u73b0\u4ee3\u4e8c\u5c45\u9910\u5385\u88c5\u4fee\u8bbe\u8ba1\u6548\u679c\u56fe\u7247"], ["static/news_images/3536162/20171230113351-b9200e9f.jpg", "\u70ed\u95e8\u9762\u79ef78\u5e73\u73b0\u4ee3\u4e8c\u5c45\u5ba2\u5385\u88c5\u4fee\u6b23\u8d4f\u56fe\u7247\u5927\u5168"], ["static/news_images/3536162/20171230113419-66a901f7.jpg", "\u7cbe\u900988\u5e73\u7c73\u4e8c\u5c45\u5367\u5ba4\u73b0\u4ee3\u88c5\u4fee\u8bbe\u8ba1\u6548\u679c\u56fe\u7247\u5927\u5168"], ["static/news_images/3536162/20171230113405-090f969e.jpg", "201877\u5e73\u7c73\u4e8c\u5c45\u5ba2\u5385\u73b0\u4ee3\u88c5\u4fee\u5b9e\u666f\u56fe\u7247\u5927\u5168"], ["static/news_images/3536162/20171230113446-c61b8e2a.jpg", "\u70ed\u95e877\u5e73\u7c73\u4e8c\u5c45\u8863\u5e3d\u95f4\u73b0\u4ee3\u8bbe\u8ba1\u6548\u679c\u56fe"], ["static/news_images/3536162/20171230113409-67baab71.jpg", "2018\u73b0\u4ee3\u4e8c\u5c45\u53a8\u623f\u88c5\u4fee\u6548\u679c\u56fe\u7247\u5927\u5168"]];
          console.log("get_info_finish");
        },1000)
    },
  getMaxHeight(arr){
    return Math.max.apply(null, arr)+"px";
  },
  getMinHeightIndex(arr){
    var minHeight=Math.min.apply(null, arr);
    if (!arr.indexOf){
        Array.prototype.indexOf=function(obj){
        var i=this.length;
            while(i-=1){
                if(this[i]==obj){
                    return i;
                }
            }return -1;
        }
    }
    return arr.indexOf(minHeight);
  },
  waterFall() {
      let imgs = document.querySelectorAll('img[waterfall]');
      let gradparentDIV=imgs[0].parentNode.parentNode;
      gradparentDIV.style.position="relative";
      let gap=0
      let pageWidth = gradparentDIV.offsetWidth;
      let itemWidth = imgs[0].parentNode.offsetWidth;
      let columns = Math.round(pageWidth / (itemWidth + gap));
      let top_Arr = [];
      let left_Arr = [];
      let loaded_count=0;
      var that=this;
      console.log("all_pictrues_count:"+imgs.length);
      for (let i = 0; i < imgs.length; i++) {
        var img=new Image();
        img.src=imgs[i].src;
        img.onload=function(){
          var parentDIV=imgs[i].parentNode;
          parentDIV.style.position="absolute";
          if (loaded_count < columns) {
              parentDIV.style.top = 0;
              parentDIV.style.left = (itemWidth + gap) * loaded_count + 'px';
              top_Arr.push(parentDIV.offsetHeight);
              left_Arr.push(parentDIV.style.left);
          } else {
              var index=that.getMinHeightIndex(top_Arr);
              parentDIV.style.top = top_Arr[index] + gap + 'px';
              parentDIV.style.left = left_Arr[index];
              top_Arr[index] = top_Arr[index] + parentDIV.offsetHeight + gap;
          }
          parentDIV.style.opacity="1";
          gradparentDIV.style.height=that.getMaxHeight(top_Arr);
          loaded_count++;
          // console.log("loaded_count:"+loaded_count);
          // console.log("loaded_index:"+i);
          if(imgs.length==loaded_count){
            console.log("loaded_all_pictrues");
          }
        }
      }
    },
    windowResizeLister(){
      var that=this;
      window.addEventListener("resize",function(){
        that.waterFall();
      })
    }
  },
  created(){
    this.get_result();//模拟请求数据
  },
  updated(){    
    this.$nextTick(function () {
      this.windowResizeLister();
      this.waterFall();
    })
  }
  })
script>
html>

效果图:

对比:

  1. css比较简单,但效果不咋地。
  2. js计较复杂,但是效果还不错。

注意:访问demo之前请先清空缓存。

demo1地址:

https://huxiaofan1223.coding.me/waterFall/css_waterfall.html

demo2地址:

https://huxiaofan1223.coding.me/waterFall/js_waterfall.html

技术上

demo1很简单没什么说的,因为js都没有用到。

demo2

1.图片异步下载。

图片是异步下载的,需要判断图片是否下载完,才能撑开div使其有offsetHeight

for (let i = 0; i < imgs.length; i++) {
  	var img=new Image();
  	img.src=imgs[i].src;
  	img.onload=function(){
      	do_calculate_and_DOM(); //进行复杂的计算并且操作dom
 	}
}

2.position计算。

加载完一张图片,top即为top_Arr中最小值。不仅要最小值,还要求出索引。需要由索引找出left,并且更新top_Arr

   let top_Arr = [];   //记录上一行元素的top值,length为每一行的列数。
   let left_Arr = [];   //记录上一行元素的top值,length为每一行的列数。
   /*找出最小值的index*/
   getMinHeightIndex(arr){
   	  var minHeight=Math.min.apply(null, arr);//找出最小值
   	  return arr.indexOf(minHeight);
   }
   /*以下代码放在循环中
   dom和更新top_Arr*/
  	var index=that.getMinHeightIndex(top_Arr);
  	parentDIV.style.top = top_Arr[index] +'px';
  	parentDIV.style.left = left_Arr[index];
  	top_Arr[index] = top_Arr[index] + parentDIV.offsetHeight;   //更新top_Arr

过程分析完,其实也不是想象中的那么难

感谢

1.Artful_Dodger-多列等宽高度不固定的几种css布局(文档流、浮动、瀑布流、flex、flexbox)


2.Levi丶-原生js实现瀑布流效果

你可能感兴趣的:(javascript)