在写文字翻滚动画效果,遇到定时器紊乱问题,也就是切换浏览器页签或收起浏览器时,定时器仍然在运行,但是页面并没有执行动画,而是等到打开浏览器动画才执行。
动画使用是通过不断增加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>
切换浏览器页签或收起浏览器,总的来说就是浏览器失去了焦点,所以只需用window.onblur来处理,当浏览器失去焦点的时候关闭定时器,获得焦点的时候,再打开