Исчезать исчезать в JavaScript - PullRequest
       21

Исчезать исчезать в JavaScript

4 голосов
/ 30 декабря 2011

Продолжаю работу над: https://codereview.stackexchange.com/questions/7315/fade-in-and-fade-out-in-pure-javascript

Как лучше всего определить, завершены ли постепенное исчезновение или затухание перед установкой новой функции. Это мой путь, но я думаю, что есть гораздо лучший способ?

Я добавил оповещения, чтобы вам было легче их видеть.

Почему я хочу это сделать, потому что: если вы нажмете кнопки до завершения цикла for, анимация будет выглядеть плохо.

Я хочу, чтобы кнопки работали только после завершения затухания.

<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
</head>

<body>
        <div>
        <span id="fade_in">Fade In</span> | 
        <span id="fade_out">Fade Out</span></div>
        <div id="fading_div" style="display:none;height:100px;background:#f00">Fading Box</div>
    </div>
</div>

<script type="text/javascript">
var done_or_not = 'done';

// fade in function
function function_opacity(opacity_value, fade_in_or_fade_out) { // fade_in_or_out - 0 = fade in, 1 = fade out
    document.getElementById('fading_div').style.opacity = opacity_value / 100;
    document.getElementById('fading_div').style.filter = 'alpha(opacity='+opacity_value+')';
    if(fade_in_or_fade_out == 1 && opacity_value == 1)
    {
        document.getElementById('fading_div').style.display = 'none';
        done_or_not = 'done';
        alert(done_or_not);
    }
    if(fade_in_or_fade_out == 0 && opacity_value == 100)
    {
        done_or_not = 'done';
        alert(done_or_not);
    }

}





window.onload =function(){

// fade in click
document.getElementById('fade_in').onclick = function fadeIn() {
    document.getElementById('fading_div').style.display='block';
    var timer = 0;
    if (done_or_not == 'done')
    {
        for (var i=1; i<=100; i++) {
            set_timeout_in = setTimeout("function_opacity("+i+",0)", timer * 10);
            timer++;
            done_or_not = 'not_done'
        }
    }
};

// fade out click
document.getElementById('fade_out').onclick = function fadeOut() {
    clearTimeout(set_timeout_in);
    var timer = 0;
    if (done_or_not == 'done')
    {
        for (var i=100; i>=1; i--) {
            set_timeout_out = setTimeout("function_opacity("+i+",1)", timer * 10);
            timer++;
            done_or_not = 'not_done'
        }
    }
};



}// END window.onload
</script>
</body>
</html>

Ответы [ 4 ]

4 голосов
/ 30 декабря 2011

Я согласен с некоторыми комментариями. Есть много хороших библиотек JavaScript, которые не только облегчают написание кода, но и устраняют некоторые проблемы совместимости браузера.

Сказав это, вы можете изменить свои функции замирания для принятия обратного вызова:

function fadeIn(callback) {
    return function() {
        function step() {
            // Perform one step of the animation

            if (/* test whether animation is done*/) {
                callback();   // <-- call the callback
            } else {
                setTimeout(step, 10);
            }
        }
        setTimeout(step, 0); // <-- begin the animation
    };
}

document.getElementById('fade_in').onclick = fadeIn(function() {
    alert("Done.");
});

Таким образом, fadeIn вернет функцию. Эта функция будет использоваться в качестве обработчика onclick. Вы можете передать fadeIn функцию, которая будет вызываться после выполнения последнего шага анимации. Внутренняя функция (возвращаемая fadeIn) по-прежнему будет иметь доступ к callback, потому что JavaScript создает вокруг нее замыкание .

Ваш анимационный код все еще может быть значительно улучшен, но это в двух словах то, что делает большинство библиотек JavaScript:

  • Выполнять анимацию пошагово;
  • Проверьте, готово ли вы;
  • Вызвать обратный вызов пользователя после последнего шага.

И еще одна последняя вещь: анимация может быть довольно сложной. Если, например, вам нужен надежный способ определения продолжительности анимации, вам нужно использовать функции анимации (также то, что делают большинство библиотек). Если математика не ваша сильная сторона, это может быть не очень приятно ...


В ответ на ваш комментарий: вы говорите, что хотите, чтобы он продолжал работать так же; "Если функция bussy, ничего не произойдет."

Итак, если я правильно понимаю, вы хотите, чтобы анимация блокировалась. На самом деле, я могу сказать вам две вещи:

  1. Ваша анимация не блокируется (по крайней мере, не сами анимации - читайте ниже).
  2. Вы все равно можете заставить его работать так, как вам нравится, с любыми видами асинхронной анимации.

Это то, для чего вы используете done_or_not. Это, на самом деле, общая схема. Обычно вместо строки используется логическое значение (true или false), но принцип всегда тот же:

// Before anything else:
var done = false;

// Define a callback:
function myCallback() {
    done = true;
    // Do something else
}

// Perform the asynchronous action (e.g. animations):
done = false;
doSomething(myCallback);

Я создал простой пример того вида анимации, который вы хотите выполнять, только с использованием jQuery. Вы можете посмотреть на это здесь: http://jsfiddle.net/PPvG/k73hU/

var buttonFadeIn = $('#fade_in');
var buttonFadeOut = $('#fade_out');
var fadingDiv = $('#fading_div');

var done = true;

buttonFadeIn.click(function() {
    if (done) {
        // Set done to false:
        done = false;

        // Start the animation:
        fadingDiv.fadeIn(
            1500, // <- 1500 ms = 1.5 second
            function() {
                // When the animation is finished, set done to true again:
                done = true;
            }
        );
    }
});

buttonFadeOut.click(function() {
    // Same as above, but using 'fadeOut'.
});

Из-за переменной done кнопки будут реагировать только после завершения анимации. И, как вы можете видеть, код действительно короткий и читаемый. Это преимущество использования библиотеки, такой как jQuery. Но, конечно, вы можете создать собственное решение.

Относительно производительности: большинство библиотек JS используют анимацию для выполнения анимации, которая обычно более производительна, чем фиксированные шаги. Это определенно выглядит более плавно для пользователя, потому что позиция зависит от пройденного времени , а не от количества пройденных шагов .

Надеюсь, это поможет. : -)

1 голос
/ 30 декабря 2011

вы можете переместить свой код затухания в его собственную функцию

var alpha = 100
function fade() { 
    if (alpha > 0) {
        alpha -= 1;    
        *your opacity changes*
        (e.g.: .opacity = (alpha/100);
        .style.filter = 'alpha(opacity='+alpha+')';)
    }
    else {
        *complete - modify the click event*
    }
 }

, вы можете добавить .MozOpacity, чтобы добавить .opacity и .filter.как уже упоминалось в комментариях выше, однако, отмена или форсирование завершенного замирания может быть лучше, чем предотвращение новых кликов во время работы цикла.

ps: я уважаю вас за то, что вы сами его кодировали.библиотеки javascript используются слишком часто и часто не нужны.

0 голосов
/ 04 января 2012

Вы должны использовать jquery. Вы можете запустить функцию после анимации

$('#clickthis').click(function(){
     //jquery has really easy way of animating css properties
     //the 5000 is the duration in milliseconds
     $('#animatethis').animate({opacity:0},5000,function(){

         //this will only run once the animation is complete
         alert('finished animating');

     });

     //or use the function..
     $('#animatethis').fadeOut(5000,function(){
          //this will only run once the animation is complete
         alert('finished fading out'); 
     });
});

это должно сделать это. Я не проверял, так что прости меня, если есть ошибки.

-L

0 голосов
/ 30 декабря 2011

Это может быть решено несколькими способами.Пожалуйста, взгляните на код на заглушке моей домашней страницы. http://marek.zielonkowski.com/thescript.js Я сделал это, очистив тайм-аут (думаю, я не очень хорошо помню, потому что это было несколько лет назад) clearInterval(isMoving); или

this.fadeIn = function (){
    iCurrentAlpha = (iCurrentAlpha===null) ? alpha : iCurrentAlpha;
    clearInterval(isFading);
    isFading = setInterval(function(){changeFading(1);},timer);
}

Или Вы можете закодировать свои пользовательские события и отправить что-то вроде 'onFadeOutStop' слушателю.

И, пожалуйста, не используйте setTimeout ('function_name ()') с кавычками - потому что это плохой хаббит (set Timeout ведет себя тогда как eval, который должен быть злым:)

...