jQuery 스크롤 이미지 구현 원리_jquery

WBOY
풀어 주다: 2016-05-16 15:25:58
원래의
1120명이 탐색했습니다.

本文主要通过以下几方面来说明懒加载技术的原理,个人前端小菜,有错误请多多指出

一、什么是图片滚动加载?

  通俗的讲就是:当访问一个页面的时候,先把img元素或是其他元素的背景图片路径替换成一张大小为1*1px图片的路径(这样就只需请求一次),只有当图片出现在浏览器的可视区域内时,才设置图片正真的路径,让图片显示出来。这就是图片懒加载。

二、为什要使用这个技术?

  比如一个页面中有很多图片,如淘宝、京东首页等等,如果一上来就发送这么多请求,页面加载就会很漫长,如果js文件都放在了文档的底部,恰巧页面的头部又依赖这个js文件,那就不好办了。更为要命的是:一上来就发送百八十个请求,服务器可能就吃不消了(又不是只有一两个人在访问这个页面)。

  因此优点就很明显了:不仅可以减轻服务器的压力,而且可以让加载好的页面更快地呈现在用户面前(用户体验好)。

三、怎么实现?

关键点如下:

      1、页面中的img元素,如果没有src属性,浏览器就不会发出请求去下载图片(也就没有请求咯,也就提高性能咯),一旦通过javascript设置了图片路径,浏览器才会送请求。有点按需分配的意思,你不想看,就不给你看,你想看了就给你看~

  2、如何获取正真的路径,这个简单,现在正真的路径存在元素的“data-url”(这个名字起个自己认识好记的就行)属性里,要用的时候就取出来,再设置;

  3、开始比较之前,先了解一些基本的知识,比如说如何获取某个元素的尺寸大小、滚动条滚动距离及偏移位置距离; 

1)屏幕可视窗口大小:对应于图中1、2位置处

    原生方法:window.innerHeight 标准浏览器及IE9+ || document.documentElement.clientHeight 标准浏览器及低版本IE标准模式 || document.body.clientHeight 低版本混杂模式

       jQuery方法: $(window).height()

2)浏览器窗口顶部与文档顶部之间的距离,也就是滚动条滚动的距离:也就是图中3、4处对应的位置;

    原生方法:window.pagYoffset——IE9+及标准浏览器 || document.documentElement.scrollTop 兼容ie低版本的标准模式 || document.body.scrollTop 兼容混杂模式;

        jQuery方法:$(document).scrollTop();

3)获取元素的尺寸:对应于图中5、6位置处;左边jquery方法,右边原生方法

    $(o).width() = o.style.width;

    $(o).innerWidth() = o.style.width+o.style.padding;

    $(o).outerWidth() = o.offsetWidth = o.style.width+o.style.padding+o.style.border;

    $(o).outerWidth(true) = o.style.width+o.style.padding+o.style.border+o.style.margin;

注意:要使用原生的style.xxx方法获取属性,这个元素必须已经有内嵌的样式,如

;

CSS 스타일이 원래 외부 또는 내부 스타일 시트를 통해 정의된 경우 o.currentStyle[xxx] ||document.defaultView.getCompulatedStyle(0)[xxx]를 사용하여 스타일 값을 가져와야 합니다

4) 요소의 위치 정보 가져오기: 는 그림의 위치 7과 8에 해당합니다

1) 문서의 상단과 왼쪽을 기준으로 요소의 거리를 반환합니다.

jQuery: $(o).offset().top 요소와 문서 상단 사이의 거리, $(o).offset().left 요소와 문서 왼쪽 가장자리 사이의 거리

네이티브: getoffsetTop(), 고도에 대한 구체적인 지침이 있으므로 여기서는 무시하겠습니다.

그런데 첫 번째 위치에 있는 상위 요소를 기준으로 반환된 요소의 오프셋 거리가 위의 오프셋 거리와의 차이에 주의하세요.

jQuery: position()은 $(o).position().left = style.left, $(o).position().top = style.top을 반환합니다.

4. 요소 크기와 오프셋 거리를 얻는 방법을 알고 나면 다음 질문은 요소가 시각적 창 영역에 들어갔는지 또는 곧 들어갈지 여부를 확인하는 방법입니다. 다음은 문제를 설명하기 위한 그림이기도 합니다.

1) 바깥쪽의 가장 큰 상자는 실제 페이지 크기이고, 가운데의 연한 파란색 상자는 상위 요소의 크기를 나타내며, 개체 1~8은 페이지에서 요소의 실제 위치를 나타냅니다. 가로방향으로!

 2) 페이지의 왼쪽 테두리를 기준으로 한 객체 8의 왼쪽 테두리의 오프셋 거리(offsetLeft)는 페이지의 왼쪽 테두리를 기준으로 한 상위 요소의 오른쪽 테두리의 거리보다 큽니다. 시간이 지나면 해당 요소는 상위 요소 외부에서 읽을 수 있습니다.

 3) 객체 7의 왼쪽 테두리가 상위 요소의 오른쪽 테두리를 교차합니다. 이때 페이지의 왼쪽 테두리를 기준으로 객체 7의 왼쪽 테두리의 오프셋 거리(offsetLeft)가 거리보다 작습니다. 페이지의 왼쪽 테두리를 기준으로 상위 요소의 오른쪽 테두리를 지정하므로 개체 7은 상위 요소의 표시 영역에 들어갑니다.

 4) 객체 6의 위치에서 객체 5의 오른쪽 가장자리와 페이지의 왼쪽 가장자리 사이의 거리는 상위 요소의 왼쪽 가장자리와 페이지의 왼쪽 가장자리 사이의 거리보다 큽니다. 🎜>

 5) 객체 5의 위치에서 객체 5의 오른쪽 가장자리와 페이지의 왼쪽 가장자리 사이의 거리가 상위 요소의 왼쪽 가장자리와 페이지의 왼쪽 가장자리 사이의 거리보다 작을 때; 이때 해당 요소는 상위 요소의 가시 영역 밖에 있다고 판단할 수 있습니다.

 6) 따라서 요소가 상위 요소의 시각적 영역 내에 있음을 나타내려면 가로 방향에서 두 가지 조건을 충족해야 합니다. 마찬가지로 세로 방향에서도 두 가지 조건을 충족해야 합니다. 자세한 내용은 아래

4. jquery 플러그인으로 확장

사용법: $("selector").scrollLoad({ 매개변수는 코드에 설명되어 있습니다 })

(function($) {
 $.fn.scrollLoading = function(options) {
  var defaults = {
   // 在html标签中存放的属性名称;
   attr: "data-url",
   // 父元素默认为window
   container: window,
   callback: $.noop
  };
  // 不管有没有传入参数,先合并再说;
  var params = $.extend({}, defaults, options || {});
  // 把父元素转为jquery对象;
  var container = $(params.container);
  // 新建一个数组,然后调用each方法,用于存储每个dom对象相关的数据;
  params.cache = [];
  $(this).each(function() {
   // 取出jquery对象中每个dom对象的节点类型,取出每个dom对象上设置的图片路径
   var node = this.nodeName.toLowerCase(), url = $(this).attr(params["attr"]);
   //重组,把每个dom对象上的属性存为一个对象;
   var data = {
    obj: $(this),
    tag: node,
    url: url
   };
   // 把这个对象加到一个数组中;
   params.cache.push(data);
  });

  var callback = function(call) {
   if ($.isFunction(params.callback)) {
    params.callback.call(call);
   }
  };
  
  //每次触发滚动事件时,对每个dom元素与container元素进行位置判断,如果满足条件,就把路径赋予这个dom元素!
  var loading = function() {
   // 获取父元素的高度
   var contHeight = container.outerHeight();
   var contWidth = container.outerWidth();

   // 获取父元素相对于文档页顶部的距离,这边要注意了,分为以下两种情况;
   if (container.get(0) === window) {
    // 第一种情况父元素为window,获取浏览器滚动条已滚动的距离;$(window)没有offset()方法;
    var contop = $(window).scrollTop();
    var conleft = $(window).scrollLeft();
   } else {
    // 第二种情况父元素为非window元素,获取它的滚动条滚动的距离;
    var contop = container.offset().top;
    var conleft = container.offset().left;
   }

   $.each(params.cache, function(i, data) {
    var o = data.obj, tag = data.tag, url = data.url, post, posb, posl, posr;
    if (o) {
     //对象顶部与文档顶部之间的距离,如果它小于父元素底部与文档顶部的距离,则说明垂直方向上已经进入可视区域了;
     post = o.offset().top - (contop + contHeight);
     //对象底部与文档顶部之间的距离,如果它大于父元素顶部与文档顶部的距离,则说明垂直方向上已经进入可视区域了;
     posb = o.offset().top + o.height() - contop;

     // 水平方向上同理;
     posl = o.offset().left - (conleft + contWidth);
     posr = o.offset().left + o.width() - conleft;

     // 只有当这个对象是可视的,并且这四个条件都满足时,才能给这个对象赋予图片路径;
     if ( o.is(':visible') && (post < 0 && posb > 0) && (posl < 0 && posr > 0) ) {
      if (url) {
       //在浏览器窗口内
       if (tag === "img") {
        //设置图片src
        callback(o.attr("src", url));
       } else {
        // 设置除img之外元素的背景url
        callback(o.css("background-image", "url("+ url +")"));
       }
      } else {
       // 无地址,直接触发回调
       callback(o);
      }
      // 给对象设置完图片路径之后,把params.cache中的对象给清除掉;对象再进入可视区,就不再进行重复设置了;
      data.obj = null;
     }
    }
   });
  };
  //加载完毕即执行
  loading();
  //滚动执行
  container.bind("scroll", loading);
 };
})(jQuery);
로그인 후 복사

위 내용은 스크롤 로딩 이미지의 구현 원리를 자세히 소개한 내용이므로 모든 분들의 학습에 도움이 되기를 바랍니다.

원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿