2015-12-15 2 views
1

Как я могу создать функцию, которая увеличит (уменьшит) ширину данного элемента html? Ниже моя попытка сделать это, но я думаю, что это очень плохо. Как я могу улучшить свой код?Анимация ширины элемента html

function foo(elem, num) { 
 
    var i = 0; 
 

 
    if (!elem.style.width) { 
 
    setTimeout(function bar() { 
 
     if (i < num) { 
 
     elem.style.width = i++ + '%'; 
 
     elem.innerHTML = i++; 
 
     } 
 

 
     setTimeout(bar, 30); 
 
    }, 30); 
 
    } else { 
 
    i = num; 
 
    setTimeout(function baz() { 
 
     if (i > 0) { 
 
     elem.style.width = i-- + '%'; 
 
     elem.innerHTML = i--; 
 
     } 
 

 
     setTimeout(baz, 30); 
 
    }, 30); 
 
    } 
 
}
div { 
 
    height: 25px; 
 
    width: 25px; 
 
    background: red; 
 
    cursor: pointer; 
 
}
<div onclick="foo(this, 75)">0%</div>

+0

Другое чем возможность использования библиотек, это довольно правильный подход. Кроме того, я бы использовал 'setInterval' и очистил его, когда закончил, а не' setTimeout', но только я – casraf

ответ

1

Есть несколько улучшений, которые будут сделаны:

  • первых, вы в настоящее время пропуская каждый второй процент, потому что вы выполняете 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>

+0

Отлично! И как сделать элемент после второго щелчка занимает первоначальную ширину? – Aleksandr

+1

Какой второй клик? Вы хотите, чтобы они вернулись к первоначальной ширине при нажатии?(например, когда они добираются до 0% ширины, так как нет ничего, на что можно щелкнуть - возможно, проще поставить событие click на родительский элемент или кнопку или что-то подобное. И вы можете просто запомнить предыдущее значение ширины и сбросьте его –

+0

> Вы хотите, чтобы они вернулись к исходной ширине при нажатии? Да. – Aleksandr

0

Почему бы вам не использовать CSS Transitions?

$(function() { 
 

 
    $('#myButton').on('click', function() { 
 
    
 
    $('#myDiv').addClass('transition-class'); 
 
    }); 
 
    
 
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> 
 
<!DOCTYPE html> 
 
    <html> 
 
    <head> 
 
    <style> 
 
    div { 
 
     width: 100px; 
 
     height: 100px; 
 
     background: red; 
 
     -webkit-transition: width 2s; /* For Safari 3.1 to 6.0 */ 
 
     transition: width 2s; 
 
    } 
 
    
 
    div:hover { 
 
     width: 300px; 
 
    } 
 
    .transition-class { 
 
     width: 500px; 
 
     height: 200px; 
 
    } 
 
    </style> 
 
    </head> 
 
    <body> 
 
    
 
    <p><b>Note:</b> This example does not work in Internet Explorer 9 and earlier versions.</p> 
 
    
 
    <div id="myDiv"></div> 
 
    
 
    <p>Hover over the div element above, to see the transition effect.</p> 
 
    
 
    <button id="myButton">click me</button> 
 
    </body> 
 
    </html>

+0

№. Я забыл сказать, что мне нужно использовать JavaScript. – Aleksandr

+0

Я только что отредактировал ответ с javascript – thiagoh

+0

Нет. Только родной JavaScript. Нет CSS, нет JQuery. – Aleksandr

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