2014-12-24 1 views
2

현재 온라인 게시자 용 타사 위젯을 개발 중이며 다른 웹 사이트에서 성능을 추적하고 싶습니다. 위젯 코드 (http://upworthy.github.io/2014/06/implementing-attention-minutes-part-1/)를 사용하여 사용자 당 평균 시간을 계산할 수 있다고 생각했습니다. 로, 내 위젯은 (내 위젯이 일반적으로 문서의 하단에 내장되어) 뷰포트 Bacon.JS를 구현하여 타사 위젯에 대한 사용자 별 평균 시간을 확인하는 데 문제가 있습니다.

  • 다음에서 볼 때 내 "초점"이벤트를 시작
    1. : 그래서 3 단계를 구현하기로 결정 Upworthy의 메서드에서 볼 수 있듯이, 사용자 정의 된 "focus"이벤트를 blur 이벤트와 병합하여 isFocused 이벤트를 개발합니다.
    2. 그런 다음 recentActive 메소드를 구현하여 사용자가 위젯을 클릭하고 있는지, 아니면 내 위젯과 상호 작용하고 있는지를 확인할 수 있습니다.

    내가 구현 한 위의 소스 코드는 여기에서 찾을 수 있습니다 : 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/. Functional Reactive 프로그래밍의 개념을 처음 접했고 여전히 Bacon 주위에서 머리를 터지려고 노력하고 있습니다 .JS 그래서 나는 어리석은 개념상의 실수를 범했을 것입니다.하지만 저는 배울 곳입니다. 어떤 도움이라도 대단히 감사하겠습니다.

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

    그런 다음 우리는 모든 스크롤 관련 이벤트를 진행 : 우리는 위젯이 표시되는지 여부를 반환하는 조건을 필요로하는 내용은

    : 위젯 볼 때 포커스 이벤트를 시작 단계를 반복하려면

  • 답변

    2

    그랬던 것처럼 :

    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를 매핑하여 다음과 같은 불리언 스트림을 얻을 수 있습니다. 위젯이 표시되는지 여부.

    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/

    +0

    굉장하고 자세히 설명해 주셔서 감사합니다. 나는 Upworthy의 구현을 생각해야한다고 인정해야합니다. – ankits

    관련 문제