在《一键转贴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:自动滚屏处理