Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > JavaScript: для новичков > Плавное изменение opacity


Автор: MagicDew 17.10.2011, 10:47
Добрый день, Уважаемые форумчане!

Я начинаю изучать JavaScript и хотелось бы решить следующую задачу: на странице есть несколько участков  текста, облаченных в тег <p></p> и ссылка-кнопка, при нажатии на которую у текста свойство "opacity" должно ПЛАВНО уменьшиться с 1 до 0.4. Вот то, что я смог наваять:

Код

<script type="text/javascript">
    var txtList = document.getElementsByTagName("p");
    function m_setOpacity(value){
        for (var i=0;i<txtList.length;i++){
            txtList[i].style.opacity = value/10;
        }
    }
    function m_changeOpacity(){
        for (var i=0;i<txtList.length;i++){
            setTimeout(setOpacity(i), 100);
        }
    return false;
    }
</script>


Код

<div id="content-column">
    <p>content column<p><br />
    <p>Lorem ipsum dolor sit amet...</p>
    <p>Lorem ipsum dolor sit amet...</p>
    <p>Lorem ipsum dolor sit amet...</p>
    <p>Lorem ipsum dolor sit amet...</p>
    <p>Lorem ipsum dolor sit amet...</p>
    <p>Lorem ipsum dolor sit amet...</p>

    <a href="#" onClick="m_changeOpacity()">Click Me!</a>
</div>


Вот суть проблемы:
я не понимаю как работает функция setTimeout() и как получить и проверить текущее значение свойства "opacity"

Автор: mcTep 17.10.2011, 14:21
setTimeout(foo, duration) говорит браузеру выполнять функцию foo c интервалом в duration миллисекунд. В foo вам надо передать именно функцию, которая будет выполняться с этим интервалом. Сейчас у вас `setOpacity(i)` это вызов функции, в результате которой возвращается какое-то значение, которое вряд ли будет функцией, судя по вашему примеру. 
Т.е. в вашем примере просто произойдет несколько вызовов фунции setOpacity и, увы, больше ничего.

Сделать стоит примерно следующее:

Код

function downgradeOpacity(elem) {
    var opa = elem.style.opacity;
    if (opa > 0.4) {
         elem.style.opacity = opa - 0.1;
    } else {
         clearInterval(elem.animationInterval);
    }
}

var pars = document.getElementsByTagName('p');
for (var i = 0, c = pars.length; i < c; i++) {
    var par = pars[i];
    par.animationInterval = setInterval(function downgradeOpacityForPar() {
        downgradeOpacity(par);
    }, 100);
}



Здесь мы заводим обработчики для каждого параграфа, и создаем ссылку на них в par.animationInterval для каждого элемента. При достижении значения  0.4 и меньше, мы этот обработчик сбрасываем через clearInteval. 

Автор: MagicDew 17.10.2011, 15:51
Поясните пожалуйста вот этот код:

Код

var pars = document.getElementsByTagName('p');
for (var i = 0, c = pars.length; i < c; i++) {
    var par = pars[i];
    par.animationInterval = setInterval(function downgradeOpacityForPar() {
        downgradeOpacity(par);
    }, 100);
}


и как вызывать и работать с этим функциями?

Автор: mcTep 18.10.2011, 08:59
Здесь мы берем нужные параграфы, потом проходясь по циклу каждому параграфу в свойство animationInterval добавляем интервал вызова функции downgradeOpacityForPar, в которой с интервалом 100 миллисекунд понижаем прозрачность конкретного параграфа. 
Этот участок кода можно обрамить в функцию и вызвать ее при, например при клике или когда вам угодно.

Код

function startAnimation() {
    var pars = document.getElementsByTagName('p');
    for (var i = 0, c = pars.length; i < c; i++) {
        var par = pars[i];
        par.animationInterval = setInterval(function downgradeOpacityForPar() {
            downgradeOpacity(par);
        }, 100);
    }
}


Код

<a href="javascript:void(0)" onclick="startAnimation()">Click Me!</a>

Автор: $дмитрий 18.10.2011, 14:20
Небольшая оптимизация
Код

setInterval(function downgradeOpacityForPar() {
            downgradeOpacity(par);
        }, 100);

Можно заменить на
Код

setInterval("downgradeOpacity(par)", 100);

Автор: mcTep 18.10.2011, 14:40
Данный подход подобен использованию eval(), где текст выполняется как код. Данный подход не рекомендуется.


Автор: $дмитрий 18.10.2011, 14:53
Не вижу смысла в функции которая не делает ничего, кроме вызова другой функции smile 

Автор: mcTep 18.10.2011, 15:19
Ваш пример делает тоже самое smile

Добавлено через 6 минут и 32 секунды
К томуже эта функция вызывает другую в нужном нам окружении. Мы могли бы конечно сделать что-то вроде 

Код

var pars = document.getElementsByTagName('p');
    for (var i = 0, c = pars.length; i < c; i++) {
        var par = pars[i];
        par.foo = downgradeOpacity;
        par.animationInterval = setInterval(par.foo, 100);
    }


и в downgradeOpacity обращаться к параграфу через this.

Автор: MagicDew 28.10.2011, 10:51
Уважаемые mcTep и $дмитрий, спасибо, что отозвались, но, увы, приведенный вами код у меня не работает. Вот то, что я написал по вашим советам:

Код

    <script type="text/javascript">
        function downgradeOpacity(elem) {
        var opa = elem.style.opacity;
            if (opa > 0.4) {
                elem.style.opacity = opa - 0.1;
            }
            else {
                clearInterval(elem.animationInterval);
            }
        }
        function startAnimation() {
        var pars = document.getElementsByTagName('p');
            for (var i = 0, c = pars.length; i < c; i++) {
                var par = pars[i];
                par.animationInterval = setInterval(function downgradeOpacityForPar() {
                downgradeOpacity(par);
                }, 100);
//                par.animationInterval = setInterval("downgradeOpacity(par)", 100); опробовал и такой вариант
            }
        }
    </script>


Код

<a href="javascript:void(0)" onclick="startAnimation()">Click Me!</a>



Автор: Absinthe 28.10.2011, 12:14
Цитата

Данный подход подобен использованию eval(), где текст выполняется как код. 
 Не правда.

Цитата

Данный подход не рекомендуется.
 Не правда.

Автор: MagicDew 2.11.2011, 15:39
Проблема осталась не решенной, помогите, плиз

Автор: magelan 2.11.2011, 17:31
MagicDew,
1я проблема - опасити изначально не определен, я с этим поборолся тупо, лень смотреть как по умному.
2я проблема - лоическая downgradeOpacityForPar вычисляется только один раз, в связи с чем только последний параграф будет высветляться.

Код

<script type="text/javascript">
function downgradeOpacity( elem )
{
    if ( elem.style.opacity > 0.4 )
        elem.style.opacity -= 0.1;
    else
        clearInterval( elem.animationInterval );
}
function startAnimation()
{
    var pars = document.getElementsByTagName( 'p' );

    for( var i = 0; i < pars.length; i++ )
    {
        var par = pars[i];
        par.style.opacity = 1;
        runElOpacity( par )      
    }
}
var runElOpacity = function( el )
{
    el.animationInterval = setInterval( function downgradeOpacityForPar() { downgradeOpacity( el ); }, 100 );
}
</script>


Автор: Absinthe 2.11.2011, 17:43
Цитата

Проблема осталась не решенной, помогите, плиз
 Я бы просто воспользовался .animate() в jQuery.
Без jQuery таким не занимался, т.к. не вижу смысла.

Автор: ksnk 2.11.2011, 20:16
Код

<script type="text/javascript">
function opacity(e,o){
   e.style.filter = "alpha(opacity=" + Math.round(o*100) + ")";
   e.style.opacity = o;
}

function fade(e,o_from,o_to,msec) {
   if (!msec) msec=2000;
   var
     delta=50,
     disp = (o_to-o_from)/(msec/delta),
     cnt = Math.round((o_to-o_from)/disp);
     x = function (){
        if (--cnt){
            o_from+=disp;
            opacity(e,o_from);
            setTimeout(x,delta);
        } else {
            opacity(e,o_to);
        }
     };
   setTimeout(x,delta);
}
</script>

<button onclick="fade(document.getElementById('test'),0,1);">fadein</button>
<button onclick="fade(document.getElementById('test'),1,0,4000);">fadeout</button>
<div id="test" style="background:red; height:100px;"></div>

Автор: SelenIT 3.11.2011, 01:16
Цитата(Absinthe @  28.10.2011,  12:14 Найти цитируемый пост)
Цитата
Данный подход не рекомендуется.
 Не правда. 

Absinthe, в пользу слов mcTepа высказываются https://developer.mozilla.org/en/DOM/window.setTimeout#Passing_string_literals и http://dev.opera.com/articles/view/efficient-javascript/?page=2#timeouts, да и это вроде как давно общепринятое мнение в сообществе. Я, как обычно, проспал какую-то революцию? Буду дико благодарен за ссылки!

Автор: Absinthe 3.11.2011, 12:45
SelenIT, прошу прошения, я думал, что это было высказывания про анонимные функции, не дочитал smile

Автор: mcTep 3.11.2011, 18:13
Цитата(magelan @  2.11.2011,  17:31 Найти цитируемый пост)
MagicDew,
1я проблема - опасити изначально не определен, я с этим поборолся тупо, лень смотреть как по умному.
2я проблема - лоическая downgradeOpacityForPar вычисляется только один раз, в связи с чем только последний параграф будет высветляться.


Ох, да.. Конкретно затупил.. :-( Простите, пожалуйста.



Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)