懒加载 & 瀑布流布局

前几天星星零零的学习,终于搞定了懒加载和瀑布流布局,下面我们通过这篇文章一起学习和探讨一下~

懒加载

首先,什么是懒加载呢?原理?
其原理是:将图片的 src 设置为统一的一张默认图片 / loading图 / logo / 空白图片(这样做会使网络请求只有一条哦),可以将真实图片的 src 存储到 img 标签的自定义属性 data-src 中,当图片出现在用户视野 / 可视窗口中(需要展示出来)时,即将自定义属性 data-src 中 的地址替换 src 中的默认图片地址,达到懒加载的效果。

那这么做是为了什么呢?本质?
这个通过原理也很容易看出来,如果页面存在大量的图片,那并不是所有的图片在一开始的时候都要加载完毕,这样浏览器的压力太大了。所以懒加载的本质就是为了,缓解浏览器的压力,提升用户体验,防止页面一次性向服务器响应大量请求导致服务器响应慢,页面卡顿或崩溃等问题。

这里我们需要解决两个问题

1. 如何判断图片是否出现在用户的视野 / 可视窗口中?
上图!

判断元素是否出现.png

是否一目了然
判断一个元素是否出现在用户视野 / 可视窗口只需要判断是否
$view.height() + $view.scrollTop() >= $node.offset().top
即窗口的高度加上窗口滚动的距离是否大于等于元素距离容器顶部的距离,如果是,则该元素出现(需要加载),否则没有出现(不需要加载)

2. 如何加载图片?
这个问题在原理处就进行了阐述,可以将真实图片的 src 放到自定义属性 data-src 中,当判断图片出现在了可视窗口中,将自定义属性中的值拿出替换 img 标签的 src
或者我们可以将真实图片的 src 存储到数组中,通过下标访问

其实这之中还存在一些问题,比如
加载过的图片在 scroll 上去再次出现在可视窗口,不需要重复修改 src
这个问题我们同样可以在 img 标签中添加自定义属性标志该图片已经加载完毕 $node.attr('data-isLoaded', 1) ,然后在滚动触发加载图片时判断该图片是否已经加载完毕
同时给滚动事件设置函数节流,避免极短时间内很多重复执行

下面给出懒加载完整代码:

start()

var clock = null 

$(window).on('scroll', function() {
    if (clock) clearTimeout(clock) 
    clock = setTimeout(function() {
        start()
    }, 300);
})

function start() {  
    $('.container img').not('[data-isLoaded]').each(function() {
        var $node = $(this)
        if ( isShow($node) ) {
            loading($node)
        }
    })
}

function loading($node) {
    $node.attr('src', $node.attr('data-src'))
    $node.attr('data-isLoaded', 1)
}

function isShow($node) {
    return $node.offset().top <= $(window).height() + $(window).scrollTop()
}

瀑布流布局

蘑菇街网

瀑布流布局

看了上面两张截图,对瀑布流有没有一些认识呢?
其中的共同点是不是:固定宽度,高度不定,间隙均匀的各元素,一行中从左到右排列,一行排满之后,其余会按顺序排在最短的一列后

这样做有什么好处呢?
1、吸引用户
当用户在浏览瀑布流式布局的时候(这里抛开懒加载),用户会产生一种错觉,就是信息是不停的在更新的,这会激发用户的好奇心,使用户不停的往下滑动。
2.良好视觉体验
采用瀑布流布局的方式可以打破常规网站布局排版,给用户眼前一亮的新鲜感,用户在浏览内容时会感到很有新鲜感,带来良好的视觉体验。
3.更好的适应移动端
由于移动设备屏幕比电脑小,一个屏幕显示的内容不会非常多,因此可能要经常翻页。而在建网站时使用瀑布流布局,用户则只需要进行滚动就能够不断浏览内容。(这一点和懒加载有一点像)

那么瀑布流如何实现?原理?
简单的来说:

  1. 对需要瀑布流布局的元素绝对定位,其父元素position: relative。
  2. 通过计算父元素(窗口或者显示容器)宽度除以需要瀑布流布局的元素宽度得到瀑布流布局的列数,并对存储每列高度值的数组进行初始化
  3. 摆放元素时,比较每列高度,每次选取高度最低的一列摆放一个元素,通过设置元素css top 和 left
  4. 重复3直到元素全部摆放完毕

这里可以利用元素宽度及其包裹元素的外边距 $node.outerWidth(true) 来计算元素占据的全部宽度
下面是JS代码:

var colCount
var colHeightArray = []
var imgWidth = $('.waterfall img').outerWidth(true)

colCount = Math.floor($(window).width() / imgWidth)
for (var i = 0; i < colCount; i++) {
    colHeightArray[i] = 0
}

$('.waterfall img').on('load', function() {
    var minValue = colHeightArray[0]
    var minIndex = 0

    for (var i = 0; i < colCount; i++) {
      if (colHeightArray[i] < minValue) {
        minValue = colHeightArray[i] 
        minIndex = i
      }
    }
    $(this).css({
      left: minIndex * imgWidth,
      top: minValue
    })
    colHeightArray[minIndex] += $(this).outerHeight(true)
})

改进:

var waterfall = {
  init: function() {
    this.clock = null
    this.colHeightArray = []
    this.imgWidth = $('.waterfall img').outerWidth(true)
    this.colCount = Math.floor($(window).width() / this.imgWidth)
    for (var i = 0; i < this.colCount; i++) {
      this.colHeightArray[i] = 0
    }
    this.bind()
  },
  bind: function() {
    var _this = this
    $('.waterfall img').on('load', function() {
      _this.layout($(this))
    })
    $(window).on('resize', function() {
      if (_this.clock) clearTimeout(_this.clock)

      _this.colCount = Math.floor($(window).width() / _this.imgWidth)
      for (var i = 0; i < _this.colCount; i++) {
        _this.colHeightArray[i] = 0
      }
          
      _this.clock = setTimeout(function() {
        $('.waterfall img').each(function() {
          _this.layout($(this))
        })
      }, 300);
    })
  },
  layout: function($node) {
    var minValue = this.colHeightArray[0]
    var minIndex = 0

    for (var i = 0; i < this.colCount; i++) {
      if (this.colHeightArray[i] < minValue) {
        minValue = this.colHeightArray[i] 
        minIndex = i
      }
    }
    $node.css({
      left: minIndex * this.imgWidth,
      top: minValue
    })
    this.colHeightArray[minIndex] += $node.outerHeight(true)
  }
}

waterfall.init()

详细可以参考:
原生JS实现瀑布流

应用:瀑布流新浪新闻

waterfall-sinaNews

要如何实现这个效果呢?
我们在这里理一下思路

  • 首先
    页面第一次加载:
    1.ajax发送 page = 1 perPageCount = 10 请求获取数据
    2.将请求到的数据拼接成 dom 放到页面中
    3.使用瀑布流布局去摆放元素
    4.page++
  • 滚动到底部
    再次加载数据
    1.ajax发送page perPageCount 请求获取数据
    2.将请求到的数据拼接成 dom 放到页面中
    3.使用瀑布流布局去摆放元素
    4.page++

这里我们需要知道,怎么判断是否到达底部了?

判断是否到达底部.png

从图中我们得知,当到达底部时
$view.height() + $view.scrollTop() = $content.height()
所以我们可以利用
$view.height() + $view.scrollTop() +20px >= $content.height()
判断是否到达了底部,需要再次请求数据加载数据了

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,084评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,623评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,450评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,322评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,370评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,274评论 1 300
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,126评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,980评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,414评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,599评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,773评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,470评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,080评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,713评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,852评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,865评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,689评论 2 354

推荐阅读更多精彩内容

  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 13,751评论 1 92
  • 简述图片懒加载的实现原理 原理:先将img标签中的src链接设为同一张图片(空白图片),将其真正的图片地址存储再i...
    饥人谷_阿银阅读 385评论 0 0
  • 懒加载 一、懒加载的实现原理 由于过多的图片会严重影响网页的加载速度,并且移动网络下的流量消耗巨大,所以说延迟加载...
    我不信这样也重名阅读 712评论 0 0
  • 简述图片懒加载的实现原理 原理:先将img标签中的src链接设为同一张图片(空白图片),将其真正的图片地址存储再i...
    jrg陈咪咪sunny阅读 1,547评论 0 1
  • 1.如何判断一个元素是否出现在窗口可视范围(浏览器的上边缘和下边缘之间,肉眼可视)。写一个函数 isVisible...
    飘飘流浪者阅读 1,382评论 0 2