Есть несколько улучшений, которые будут сделаны:
- первых, вы в настоящее время пропуская каждый второй процент, потому что вы выполняете
i++
/i--
дважды в функции, один после чего вы установите ширину на 0%
и отобразите 1%
, а затем установите ее на 2%
и отобразите 3%
, и т.д.)
- второго, вы можете использовать
requestAnimationFrame
(для более старых версий браузеров включают polyfill), чтобы получить гораздо более высокую производительность
- треть, вы можете перестроить свой код так, что это не так, повторяющийся путем вычисления направления (
1
или -1
в зависимости от того, если вы хотите i
для увеличения или уменьшения), и только имея одну bar
/baz
функции
Вот мой взгляд на него:
function foo(elem, num) {
var initialWidth = elem.style.width;
var i = initialWidth ? num : 0;
var direction = initialWidth ? -1 : 1;
function bar() {
elem.style.width = i + '%';
elem.innerHTML = '' + i;
i += direction;
if (i <= num && i >= 0)
window.requestAnimationFrame(bar);
}
window.requestAnimationFrame(bar);
return function reset() {
elem.style.width = initialWidth;
elem.innerHTML = '';
}
}
var animated = false,
reset1, reset2;
document.getElementsByClassName('grower-parent')[0].onclick = function() {
if (!animated) {
animated = true;
reset1 = foo(document.getElementsByClassName('grower-1')[0], 50);
reset2 = foo(document.getElementsByClassName('grower-2')[0], 50);
return;
}
animated = false;
reset1();
reset2();
};
.grower-1,
.grower-2 {
display: block;
background-color: blue;
height: 1em;
color: white;
width: 0;
}
<div class="grower-parent">
<div class="grower-1" style="width:50%"></div>
<div class="grower-2"></div>
</div>
Edit: Теперь первый щелчок запускает анимацию и второй щелчок сбрасывает его.
Edit 2: гораздо более сложная программа, которая на самом деле может переключаться между оживляющий к цели или вернуться к исходному значению (и переключение между px
и %
единиц). Теперь вы можете начать видеть, почему у нас есть специализированные библиотеки анимации, что мы можем просто заткнуть в наши проекты, чтобы не изобретать колесо :) (попробовать GSAP, это является удивительным)
function animateTo(element, to) {
if (to === undefined) return function() {};
var animating = true;
var width, match;
var unit = (to === Number(to)) ? (width = to, 'px') : (match = to.match(/(\d+)\s*(px|%)/), width = Number(match[1]), match[2]);
var initialWidth = unit === 'px' ? element.offsetWidth : (match = element.style.width.match(/(\d+)\s*%/)) ? Number(match[1]) : Math.round(element.offsetWidth/((element.offsetParent || element).offsetWidth) * 100);
var currentWidth = initialWidth;
var direction = initialWidth <= width ? 1 : -1;
function animate() {
element.style.width = currentWidth + unit;
element.innerHTML = currentWidth + unit;
currentWidth += direction;
if (direction * currentWidth <= direction * width) {
if (animating) window.requestAnimationFrame(animate);
} else {
animating = false;
}
}
function stopAnimation() {
animating = false;
}
window.requestAnimationFrame(animate);
return stopAnimation;
}
function toggleWidth(element, to) {
var initial = element.style.width ? element.style.width : element.offsetWidth + 'px';
var toAnimation = true;
var stopAnimation;
return function toggle() {
if (stopAnimation) stopAnimation();
if (toAnimation) {
stopAnimation = animateTo(element, to);
} else {
stopAnimation = animateTo(element, initial);
}
toAnimation = !toAnimation;
}
}
var toggle = toggleWidth(document.getElementsByClassName('grower-1')[0], '10%');
var toggle2 = toggleWidth(document.getElementsByClassName('grower-2')[0], '200px');
document.getElementsByClassName('grower-parent')[0].onclick = function() {
toggle();
toggle2();
};
.grower-1,
.grower-2 {
display: block;
background-color: blue;
height: 1em;
color: white;
width: 0;
}
<div class="grower-parent">
<div class="grower-1" style="width:400px"></div>
<div class="grower-2" style="width:5%"></div>
</div>
Другое чем возможность использования библиотек, это довольно правильный подход. Кроме того, я бы использовал 'setInterval' и очистил его, когда закончил, а не' setTimeout', но только я – casraf