gpt4 book ai didi

javascript - 实现 Bacon.JS 以查找每个用户在第三方小部件上花费的平均时间的问题

转载 作者:行者123 更新时间:2023-11-29 21:53:38 25 4
gpt4 key购买 nike

我目前正在为在线发布商开发第三方小部件,并希望跟踪其在不同网站上的表现。我想到了实现 Upworthy 的代码 ( http://upworthy.github.io/2014/06/implementing-attention-minutes-part-1/ ) 来计算每个用户在我的小部件上花费的平均时间。所以我决定分 3 个步骤实现它:

  1. 当我的小部件仅在视口(viewport)中可见时启动我的“焦点”事件(我的小部件通常嵌入在文章底部)
  2. 接下来,如 Upworthy 的方法所示,我会将自定义的“focus”事件与 blur 事件合并,以开发一个 isFocused 事件。
  3. 然后,我可以实现他们的 recentlyActive 方法来查明用户是否正在点击小部件,即他们是否正在与我的小部件进行交互。

我已经实现了上面的代码,源代码可以在这里找到:http://jsfiddle.net/q21gzjmf/13/

//simple jquery function to detect when my widget is visible   
function widgetFocus(){
$(window).scroll(function () {

if ($(window).scrollTop() + $(window).height() > $('.footer').offset().top) {
alert('visible');
return true;
}
else{
return false;
}
});
}

function merge(stream1, stream2) {
return stream1.merge(stream2);
}

function eventStream(eventName) {
return $(window).asEventStream(eventName);
}

var isFocused = eventStream("focus").map(widgetFocus)
.merge(eventStream("blur").map(false))
.toProperty(true);

var EVENT_NAMES = ["focus", "click", "scroll", "mousemove", "touchstart", "touchend", "touchcancel", "touchleave", "touchmove"];
var streams = _.map(EVENT_NAMES, eventStream);
var interactionStream = _.reduce(streams, merge);


var recentlyActive = interactionStream
.map(true)
.flatMapLatest(function() {
return Bacon.once(true).merge(Bacon.once(false).delay(DECAY));
})
.toProperty(false);

var isActive = (recentlyActive.and(isFocused));

var secondsActive = Bacon.mergeAll(isActive.changes(), isActive.sample(1000))
.map(function(isActive) {
return {
isActive: isActive,
timestamp: new Date().getTime()
};
})
.slidingWindow(2,2)
.filter(function(span) { return span[0].isActive; })
.map(function(span) { return span[1].timestamp - span[0].timestamp; })
.scan(0, function(x,y) { return x + y;})
.map(function(x) { return x / 1000; }) // milliseconds
.map(Math.floor);

secondsActive.assign($("#seconds"), "text");

但是,如果您在底部向下滚动,您会发现花费的时间计算为 0,并且不会像此处显示的 Upworthy 实现那样动态更新自身 http://jsfiddle.net/zanes/mbGBr/ .我对函数式响应式编程的概念还很陌生,并且仍在努力了解 Bacon.JS,所以我确定我一定犯了一个非常愚蠢的概念性错误,但我是来这里学习的。任何帮助将不胜感激。

最佳答案

要重复这些步骤在窗口小部件可见时启动焦点事件:

为此我们需要一个谓词来返回小部件是否可见:

function widgetFocus(){ 
return $(window).scrollTop() + $(window).height() > $('.footer').offset().top;
}

然后我们像您一样处理所有与滚动相关的事件:

function eventStream(eventName) {
return $(window).asEventStream(eventName);
}

var EVENT_NAMES = ["focus", "click", "scroll", "mousemove", "touchstart", "touchend", "touchcancel", "touchleave", "touchmove"];
var streams = _.map(EVENT_NAMES, eventStream);
var scrollEvents = Bacon.mergeAll(streams)
.debounceImmediate(50); // we debounce here, so we didn't get too much events

接下来,您可以映射 scrollEvents 以获取指示是否显示小部件的 bool 值流。

var isVisible$ = scrollEvents
.map(function () {
return widgetFocus();
})
.toProperty(false);

var secondsVisible = isVisible$.changes()
.map(function(isActive) {
return {
isActive: isActive,
timestamp: new Date().getTime()
};
})
.slidingWindow(2,2)
.filter(function(span) { return span[0].isActive; })
.map(function(span) { return span[1].timestamp - span[0].timestamp; })
.scan(0, function(x,y) { return x + y;})
.map(function(x) { return Math.floor(x / 1000); }); // milliseconds

secondsVisible.log("visible: ");

这是第一步,可能已经适合您了。

下一步是创建一个属性或流来判断页面是否处于事件状态(Upworthy 的简单版本):

var DECAY = 1000;

function decayingStream() {
return Bacon.once(true).merge(Bacon.once(false).delay(DECAY));
}

var isActive$ = scrollEvents
.flatMapLatest(decayingStream)
.toProperty(true);

接下来我们可以组合 isActive$isVisible$ 属性。我们只对小部件可见和页面处于事件状态的时间感兴趣!

var secondsVisibleAndActive = isActive$.and(isVisible$).changes()
.map(function(isActive) {
return {
isActive: isActive,
timestamp: new Date().getTime()
};
})
.slidingWindow(2,2)
.filter(function(span) { return span[0].isActive; })
.map(function(span) { return span[1].timestamp - span[0].timestamp; })
.scan(0, function(x,y) { return x + y;})
.map(function(x) { return Math.floor(x / 1000); }); // milliseconds

secondsVisibleAndActive.log("active & visible: ");
secondsVisibleAndActive.assign($("#seconds"), "text");

一如既往,从简单开始。


或者,您可以举例说明 Upworthy 的实现之美:最后一行:

var hasAttention = (recentlyActive.and(isFocused)).or(videoIsPlaying);

在您的情况下,您可以将其更改为:

var widgetHasAttention = recentlyActive.and(isFocused).and(widgetIsVisible);

工作 jsfiddle:http://jsfiddle.net/xkn3sc6y/3/

关于javascript - 实现 Bacon.JS 以查找每个用户在第三方小部件上花费的平均时间的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27641419/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com