一键转贴Chrome扩展开发经验总结9:自动滚屏处理-出家如初,成佛有余

一键转贴Chrome扩展开发经验总结9:自动滚屏处理

技术 admin 447浏览 0评论

在《一键转贴Chrome扩展开发经验总结8:动态装载图片的处理》提到了动态图片的处理思路。继续阐述一下easyPublish中自动滚屏的技术实现方案。

执行自动滚屏的目的:模拟人工滚屏操作,让当前页面在滚屏过程中,JavaScript动态更新采用惰性装载图片的属性<img src=”” data-src=”” />,或者动态更新页面DOM内容。

自动滚屏需要解决的几个技术难题

1、怎样判断页面是否需要自动滚屏?

2、怎样通过chrome扩展实现自动滚屏?

3、怎样判断屏幕已经滚动到底部?

这里先说最复杂的:怎样判断屏幕已经滚动到底部?

要判断屏幕是否滚动到底部,基本上都会想到如下方案:

var scrollTop = (document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop;

var scrollHeight = (document.documentElement && document.documentElement.scrollHeight) || document.body.scrollHeight;

var scrolledToBottom = (scrollTop + window.innerHeight) >= scrollHeight;

但此种方案只适合于页面scrollHeight 相对固定的情况,并不适用于pixiv.net这样图片瀑布流的网站页面。

像pixiv.net这些采用图片瀑布流的网站,由于会在滚屏过程中,动态装载图片内容并append到页面尾部。因此采用以上方案判读是否滚屏到底部,会遇到如下问题:执行滚屏操作后,内容尚在装载过程中,如果此时判断,会发现已经滚动到底部了。

对此,改进的方案可以是:滚屏后,通过setTimeout sleep几十毫秒,再做判断。

但尝试后,会发现此种方案也不行。由于并不知道是否滚屏到尾部,因此必须每一次滚屏都sleep,滚屏效率太差,基本上不可用。

图片瀑布流自动滚屏解决方案

由于伴随滚屏,DOM树的内容也会变化,也就是说:对瀑布流的网站,是否滚屏到底部,可以通过判断DOM内容是否变化。

也即: 对于图片流的网站,要判断是否滚动到底部,可以通过判断最近几次执行滚屏后,网页DOM内容是否变化。

要监控页面DOM是否变化,可以用 MutationObserver模式。

而对于只采用惰性装载的网站,要判断是否滚动到底部,可以通过判断最近几次执行滚屏后,相应的scrollTop、scrollHeight是否相等。

自动滚屏是否到底部判断算法

因此,结合纯惰性装载和瀑布流模式的网站,可以得到判断自动滚屏是否到底部总的算法:(以下按照每10毫秒执行一次滚屏操作为例)

1、在content-scripts页面装载时候,注入JavaScript代码,代码主要完成如下功能

a、获取当前页面支持的Event Listeners,重点为scroll事件

b、自动滚屏处理

2、content-scripts页面判断是否有scoll事件以及页面是否到底部,从而判断是否需要自动滚屏

3、如果需要自动滚屏,通过消息方式通知background页面自动滚屏

4、background一边自动滚屏,同时还需要时刻判断页面是否已经滚动到底

a、注入脚本中,增加 MutationObserver,对页面的 attributes,childList,subtree的变化进行监控

var lastScrollHeight = new Array();
var lastScrollTop = new Array();

config = { attributes: true, childList: true, subtree: true };
callback = function (mutationsList, instance) {
  let scrollTop;
  if (document.documentElement && document.documentElement.scrollTop) {
    scrollTop = document.documentElement.scrollTop;
  } else if (document.body) {
    scrollTop = document.body.scrollTop;
  }
  lastScrollTop.push(scrollTop);
  lastScrollHeight.push(document.documentElement.scrollHeight);


};

var mutationObserver = new MutationObserver(callback);

b、MutationObserver 接收到状态变化通知,将最新的 scrollTop、scrollHeight 分别存入(push)到两个全局的数组中,用于记录最近一次滚屏对应的scrollTop、scrollHeight值

c、每一次滚屏后,取得最新的 scrollTop、scrollHeight,并分别push到两个全局的数组中

d、每一次滚屏后,判断是否滚屏到底部

对存放scrollTop、scrollHeight的两个全局数组做slice(-200,-1),也即截取最后200次(200*10=2秒)的scrollTop、scrollHeight,如果两个数组都相等,可以认为已经滚屏到底部,否则继续执行滚屏操作。

技巧在于:不是判断 (scrollTop + window.innerHeight) >= scrollHeight,而是判断最近200*10=2秒内的scrollTop、scrollHeight是否都相等。

以上算法,可以完美兼容瀑布流和惰性装载两种模式的自动滚屏判断。

 

自动滚屏的其他两个技术问题,后面文章继续阐述。

转载请注明:出家如初,成佛有余 » 一键转贴Chrome扩展开发经验总结9:自动滚屏处理

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址