埋点之眼球曝光

埋点曝光需求要求在页面在用户的视野中就发送一个曝光日志,一个页面的一个模块最多发送一次,也就是首次曝光才发送,之后在进入视野中就不用在发曝光日志了

一、当看到这个需求的时候我们第一点肯定想到要监听滚动事件

1
2
3
window.addEventListener('scroll', function(){
console.log('监听滚动')
});

二、然后优化下滚动事件,加上throttle。

1
2
3
4
5
6
7
8
9
10
11
window.addEventListener('scroll',newScroll(exposure,500));
const newScroll = function(realFunc,time){
let timeout = null;
return function (){
clearTimeout(timeout);
timeout = setTimeout(realFunc,time)
}
};
function exposure() {
console.log('监听滚动增加throttle')
}

三、然后优化下滚动事件,加上throttle。
注意scroll监听的匿名事件是不可以取消监听事件的,我想要的是页面中所有需要曝光的地方曝光结束后,取消监听事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//需要曝光的点
const exposureList = [
{
selector: 'aaaa',
aid: '6790'
},
];
window.addEventListener('scroll',newScroll);
const newScroll = function(realFunc,time){
let timeout = null;
return function (){
clearTimeout(timeout);
timeout = setTimeout(realFunc,time)
}
}(exposure,500);
function exposure() {
if(exposureList.length == 0){
window.removeEventListener("scroll", newScroll);
}
exposureList.forEach(function(value,index) {
const currentDom = document.getElementById(value.selector);
if(currentDom){
const currentClientRect = currentDom.getBoundingClientRect();
const bottomToTopView = currentClientRect.top >0 && window.innerHeight/3*2>currentClientRect.top;
const topToBottomView = currentClientRect.top <0 && currentClientRect.top > - currentDom.offsetHeight/2;
if(bottomToTopView ||topToBottomView){
//发送曝光事件
exposureList.splice(index,1);
}
}
}

tips: 这里用到了getBoundingClientRect文章出处

getBoundingClientRect用于获得页面中某个元素的左,上,右和下分别相对浏览器视窗的位置。getBoundingClientRect是DOM元素到浏览器可视范围的距离(不包含文档卷起的部分)。

该函数返回一个Object对象,该对象有6个属性:top,lef,right,bottom,width,height;

1.兼容性
getBoundingClientRect()最先是IE的私有属性,现在已经是一个W3C标准。所以你不用当心浏览器兼容问题,不过还是有区别的:IE只返回top,lef,right,bottom四个值,不过可以通过以下方法来获取width,height的值

1
2
document.getElementById(value.selector).offsetHeight();
document.getElementById(value.selector). clientHeight();
1
2
3
4
5
6
7
8
9
10
11
12
13
var ro = object.getBoundingClientRect();
var Width = ro.right - ro.left;
var Height = ro.bottom - ro.top;

//兼容所有浏览器写法:

var ro = object.getBoundingClientRect();
var Top = ro.top;
var Bottom = ro.bottom;
var Left = ro.left;
var Right = ro.right;
var Width = ro.width||Right - Left;
var Height = ro.height||Bottom - Top;