浏览器收起或切换页签,定时器造成动画紊乱

在写文字翻滚动画效果,遇到定时器紊乱问题,也就是切换浏览器页签或收起浏览器时,定时器仍然在运行,但是页面并没有执行动画,而是等到打开浏览器动画才执行。

动画使用是通过不断增加rotateX值来实现的。

                frontDom.style.transform = 'rotateX(' + (parseInt(frontAngle) + 180) + 'deg)';
                backDom.style.transform = 'rotateX(' + (parseInt(backAngle) + 180) + 'deg)';

写了一个小demo,代码有些长,目前我的解决方法是统计定时器执行时间,超出定时器执行时间则不翻转。有没其他更好方法,目前我想到的只有浏览器失焦这另一个方法。

<!DOCTYPE html>
<html>
<head>
    <title></title>
<link rel="stylesheet" type="text/css" href="iconfont.css">
<style type="text/css">

.box {
    position: relative;
    perspective: 200px;
    display: inline-block;
    width: 20px;
    height: 20px;
    margin: 200px;
}

.box > * {
    position: absolute;
    font-size: 50px;
    top: 0;
    left: 0;
    backface-visibility: hidden;
    transition: transform 500ms;
}
</style>
</head>
<body>
<div id="a">
    3
</div>
</body>
<script>
function getRotateXValue(matrix) {
        var groups = matrix.match(/(?:[^,]+,){5}\s*([^,]+),\s*([^,]+)/);
        var angle;
        if (groups) {
            var numbers = groups.slice(1).map(function(n) { return Number(n); });
            angle = Math.atan(numbers[1] / numbers[0]) / Math.PI * 180 + (numbers[0] < 0 ? 180 : 0);
            if (angle < 0) {
                angle += 360;
            }
        } else {
            angle = 0;
        }
        return parseInt(angle);
}

function replaceNumber2Html(nubmer) {
    //return '<i class="iconfont icon-number' + nubmer +'"></i>';
    return '<span>' + number + '</span>'
}

function createBoxElement(number) {
    var box = document.createElement('div');
    box.className = 'box';
    var numberHtml = replaceNumber2Html(number);
    box.innerHTML = numberHtml + numberHtml;
    box.childNodes[0].style.transform = 'rotateX(0deg)';
    box.childNodes[1].style.transform = 'rotateX(180deg)';
    return box;
}

function getChangeDom(box) {
    var nodes = box.childNodes;
    var angle = getRotateX(nodes[0].style.transform);
    return angle % 360 == 0 ? nodes[1] : nodes[0];
}

function getRotateX(transform) {
    var match = /rotateX\((-?\d*)deg\)/.exec(transform);
    if (!match) {
        console.log('无法获得rotateX')
        return 0;
    } else {
        return match[1];
    }
}

function addZero(number, length) {
    var zeroString = '';
    for (var i = 0; i < length; i++) {
        zeroString += '0';
    }
    return (zeroString + number).slice(-length);
}

function randomValue() {
    return Math.floor(Math.random() * 20) + 11;
}

var wordContainer = document.getElementById('a');
var number = parseInt(wordContainer.innerText);
while (wordContainer.firstChild) {
    wordContainer.removeChild(wordContainer.firstChild);
}

number.toString().split('').forEach(function(item) {
    var box = createBoxElement(item);
    wordContainer.appendChild(box);
});


function rotateWord(newNumber) {
    if (newNumber) {
        var newNumberStr = newNumber.toString();
        var numberStr = number.toString();
        var isAdd = false;
        if (newNumberStr.length != numberStr.length) {
            var newBox = createBoxElement(newNumberStr.substring(0, 1));
            wordContainer.insertBefore(newBox, wordContainer.firstElementChild);
            isAdd = true;
        }

        if (isAdd) {
            numberStr = addZero(numberStr, newNumberStr.length);
        }

        var interval = newNumberStr.split('').map(function (newNumberChar, index) {
            return newNumberChar - numberStr[index];
        });
        var boxNodes = wordContainer.childNodes;
        interval.forEach(function (changeNumber, index) {
            if (changeNumber != 0) {
                var changeDom = getChangeDom(boxNodes[index]);
                //changeDom.className = changeDom.className.replace(/\d/, newNumberStr[index]);
                changeDom.innerText = newNumberStr[index];
                var frontDom = boxNodes[index].childNodes[0];
                var backDom = boxNodes[index].childNodes[1];
                var frontAngle = getRotateX(frontDom.style.transform);
                var backAngle = getRotateX(backDom.style.transform);
                frontDom.style.transform = 'rotateX(' + (parseInt(frontAngle) + 180) + 'deg)';
                backDom.style.transform = 'rotateX(' + (parseInt(backAngle) + 180) + 'deg)';
            }
        });
        number = parseInt(newNumber);
    }
};

var time = 1000;
var lastTime = Date.now();
var deltaTime = 0;

setTimeout(function timeoutTimer() {
    var now = Date.now();
    deltaTime = now - lastTime;
    lastTime = now;
    if (deltaTime < time * 1.2) {
        var newNumber = number + randomValue();
        rotateWord(newNumber);
    }
    setTimeout(timeoutTimer, time);
}, time);

</script>
</html>
阅读 4.4k
3 个回答

切换浏览器页签或收起浏览器,总的来说就是浏览器失去了焦点,所以只需用window.onblur来处理,当浏览器失去焦点的时候关闭定时器,获得焦点的时候,再打开

setTimeout===>requestAnimationFrame

这种用css3处理比较好。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题