0

Пример: http://codepen.io/anon/pen/xgZMVd/Javascript анимация идет неправильно, когда вкладка неактивна

HTML файл:

<div class="game-page"> 
</div> 

CSS файл:

.game-page { 
    width: 1024px; 
    height: 768px; 
    position: absolute; 
    background-color: grey; 
} 

.stick { 
    position: absolute; 
    left: 50%; 
    margin-left: -94px; 
    top: -60px; 
    width: 188px; 
    height: 50px; 
    background-color: black; 
} 

расслоение плотной файла:

$(document).ready(function() { 
    init(); 
}); 

var CSS_CLASS = { STICK: "stick" }, 
    changeSpeedTime = 1000, //in milliseconds 
    gameTime = 60, //in seconds 
    timer = 1, //in seconds 
    windowWidth = 1024, 
    windowHeight = 768, 
    stickTop = -60, 
    restStickTime = 0, //in milliseconds 
    initialStickInterval = 1000, //in milliseconds 
    stickInterval = null, //in milliseconds 
    initialStickDuration = 7, //in seconds 
    stickDuration = null, //in seconds 
    stickTweensArray = [], 
    changeSpeedInterval = null, 
    countdownTimerInterval = null, 
    generateSticksInterval = null, 
    generateSticksTimeout = null, 
    $gamePage = null; 

function init() { 
    initVariables(); 
    initGamePage(); 
} 

function changingSpeedFunction(x){ 
    var y = Math.pow(2, (x/20)); 
    return y; 
} 

function initVariables() { 
    $gamePage = $(".game-page"); 
    stickDuration = initialStickDuration; 
    stickInterval = initialStickInterval; 
} 

function initGamePage() { 
    TweenMax.ticker.useRAF(false); 
    TweenMax.lagSmoothing(0); 
    initGamePageAnimation(); 
} 

function initGamePageAnimation() { 
    generateSticks(); 

    changeSpeedInterval = setInterval(function() { 
    changeSpeed(); 
    }, changeSpeedTime); 

    countdownTimerInterval = setInterval(function() { 
    updateCountdown(); 
    }, 1000); 
} 

function changeSpeed() { 
    var x = timer; 
    var y = changingSpeedFunction(x); //change speed function 
    stickDuration = initialStickDuration/y; 
    stickInterval = initialStickInterval/y; 

    changeCurrentSticksSpeed(); 
    generateSticks(); 
} 

function changeCurrentSticksSpeed() { 
    stickTweensArray.forEach(function(item, i, arr) { 
    var tween = item.tween; 
    var $stick = item.$stick; 

    var oldTime = tween._time; 
    var oldDuration = tween._duration; 
    var newDuration = stickDuration; 
    var oldPosition = stickTop; 
    var newPosition = $stick.position().top; 
    var oldStartTime = tween._startTime; 

    var distance = newPosition - oldPosition; 
    var oldSpeed = distance/oldTime; 
    var newSpeed = oldSpeed * oldDuration/newDuration; 
    var newTime = distance/newSpeed; 
    var currentTime = oldStartTime + oldTime; 
    var newStartTime = currentTime - newTime; 

    item.tween._duration = newDuration; 
    item.tween._startTime = newStartTime; 
    }); 
} 

function generateSticks() { 
    if (restStickTime >= changeSpeedTime) { 
    restStickTime -= changeSpeedTime; 
    restStickTime = Math.abs(restStickTime); 
    } else { 
    generateSticksTimeout = setTimeout(function() { 
     generateSticksInterval = setInterval(function() { 
     generateStick(); 
     restStickTime -= stickInterval; 
     if (restStickTime <= 0) { 
      clearInterval(generateSticksInterval); 
      restStickTime = Math.abs(restStickTime); 
     } 
     }, stickInterval); 
     generateStick(); 
     restStickTime = changeSpeedTime - Math.abs(restStickTime) - stickInterval; 
     if (restStickTime <= 0) { 
     clearInterval(generateSticksInterval); 
     restStickTime = Math.abs(restStickTime); 
     } 
    }, restStickTime); 
    } 
} 

function generateStick() { 
    var $stick = $("<div class='" + CSS_CLASS.STICK + "'></div>").appendTo($gamePage); 

    animateStick($stick); 
} 

function animateStick ($stick) { 
    var translateYValue = windowHeight + -stickTop; 

    var tween = new TweenMax($stick, stickDuration, { 
    y: translateYValue, ease: Power0.easeNone, onComplete: function() { 
     $stick.remove(); 
     stickTweensArray.shift(); 
    } 
    }); 

    stickTweensArray.push({tween:tween, $stick:$stick}); 
} 

function updateCountdown() { 
    timer++; 

    if (timer >= gameTime) { 
    onGameEnd(); 
    clearInterval(changeSpeedInterval); 
    clearInterval(countdownTimerInterval); 
    clearInterval(generateSticksInterval); 
    clearTimeout(generateSticksTimeout); 
    } 
} 

function onGameEnd() { 
    var $sticks = $gamePage.find(".stick"); 
    TweenMax.killTweensOf($sticks); 
} 

S o, как я исследовал, у меня есть следующая ситуация:

  1. TweenMax (так как использует requestAnimationFrame) зависает, когда вкладка неактивна.
  2. setInterval продолжать движение, когда вкладка неактивна (также может зависеть ее задержка, если вкладка неактивна, зависит от браузера)
  3. Есть ли какая-либо другая функция javascript, которая изменяется, когда вкладка неактивна?

Тогда у меня есть 2 решения:

  1. Замораживание вся игра, когда вкладка неактивна.
  2. Продолжайте движение, когда вкладка неактивна.

С первым решением у меня есть следующая проблема: в TweenMax использует requestAnimationFrame, он работает правильно в соответствии с этим решением (замерзает анимацию), но как я могу заморозить интервалы и время ожидания, когда вкладка неактивна, а затем возобновить интервалы и время ожидания?

Со вторым решением я могу использовать TweenMax.lagSmoothing (0) и TweenMax.ticker.useRAF (false) для анимации, и это работает, но в любом случае что-то не так с интервалами и/или таймаутами. Я ожидал, что анимация пойдет не так из-за изменения задержки интервала до 1000+ мс, когда вкладка неактивна (согласно http://stackoverflow...w-is-not-active), но я отключил ускорение и установил задержки на 2000 мс, и это не помогло.

Пожалуйста, помогите мне хотя бы с одним решением. Лучше, чтобы оба имели разновидность.

ответ

0

Решенная проблема с первым решением: заморозить всю игру. Просто использовалась функция TweenMax.delayedCall() вместо setTimeout, а setInterval и целая анимация синхронизированы довольно хорошо.

 Смежные вопросы

  • Нет связанных вопросов^_^