Функция, вызванная settimeout, не заканчивается

Проблема: в слайд-шоу функция затухания ниже продолжает вызывать функции затухания/затухания, пожалуйста, JsFiddle и запустите его примерно на десять секунд, чтобы увидеть проблему. Не работает в IE, не позволяйте jsfiddle работать слишком долго, это может привести к сбою вашего браузера!

JsFiddle: http://jsfiddle.net/HdYmH/

Подробности (для тех, кто заинтересован): Привет, извините за публикацию вопроса с таким большим куском кода. Я все еще изучаю javascript и пытаюсь понять, как сделать слайд-шоу. Я знаю, что существует множество js-слайд-шоу, но я хотел понять это как опыт обучения. Так что имейте в виду, что в этом коде есть очень плохие части. Проблема, вероятно, связана с методом слайд-шоу changeSlide().

Я использовал firebug, чтобы узнать, какой метод вызывается чаще всего, через несколько секунд fadeOut будет вызываться более 20 000 раз :|

// Generic fade function that fades in or out
function fade(pElem, pStartOpac, pEndOpac, fps, sec) {
    if ((typeof (pElem) !== "string") || (typeof (pStartOpac) !== "number")
            || (typeof (pEndOpac) !== "number") || (typeof (fps) !== "number")
            || (typeof (sec) !== "number")) {
        console.log("Parameters incorrect format has to be (string) Element Id, (double) Starting Opacity, (double) End Opacity, (integer) frames per second, (integer) seconds to run");
        return;
    }
    // The CSS opacity property only works from 1 to 0
    if (pStartOpac < 0) {
        pStartOpace = 0;
    }
    if (pStartOpac > 1) {
        pStartOpac = 1;
    }
    if (pEndOpac < 0) {
        pEndOpac = 0;
    }
    if (pEndOpac > 1) {
        pEndOpac = 1;
    }

    // Stop the fps from going over 60 or under 1 (The eye will barely notice
    // improvements above 60fps and fractional fps are not supported)
    if (fps > 60) {
        fps = 60;
    }
    if (fps < 1) {
        fps = 1;
    }

    var totalFrames = (fps * sec);
    var opacityChangePerSecond = (Math.abs(pStartOpac - pEndOpac) / sec);
    var opacityChangePerFrame = (opacityChangePerSecond / fps);
    var timeOutInterval = 1000 * (1 / fps);

    // console.log("totalFrames: "+totalFrames);
    // console.log("Opacity change per second: " + opacityChangePerSecond);
    // console.log("Opacity change per frame: " + opacityChangePerFrame);
    // console.log("Time out interval: " + timeOutInterval + " milliseconds");

    var opacity = pStartOpac;
    var timeoutVar;
    var elemId = document.getElementById(pElem);
    elemId.style.opacity = opacity;

    if (pStartOpac < pEndOpac) {
        fadeIn();
        return;
    } else {
        fadeOut();
        return;
    }

    function fadeIn() {
        opacity = opacity + opacityChangePerFrame;
        if (opacity > pEndOpac) {
            clearTimeout(timeoutVar);
            return;
        }
        elemId.style.opacity = opacity;
        timeoutVar = setTimeout(fadeIn, timeOutInterval);
        return;
    }

    function fadeOut() {
        if (opacity < pEndOpac) {
            clearTimeout(timeoutVar);
            return;
        }
        opacity = opacity - opacityChangePerFrame;
        if (opacity < 0) {
            opacity = 0;
        }
        elemId.style.opacity = opacity;
        timeoutVar = setTimeout(fadeOut, timeOutInterval);
        return;
    }

}

person ksrb    schedule 03.09.2012    source источник


Ответы (1)


Есть проблема: когда непрозрачность становится ‹0, вы устанавливаете ее на 0, а затем делаете: if (opacity < pEndOpac). pEndOpac равен 0, поэтому 0‹0 оценивается как false, а тайм-аут никогда не сбрасывается. Решение состоит в том, чтобы сделать if (opacity <= pEndOpac):

function fadeIn() {
    opacity = opacity + opacityChangePerFrame;
    if (opacity >= pEndOpac) {
        clearTimeout(timeoutVar);
        return;
    }
    elemId.style.opacity = opacity;
    timeoutVar = setTimeout(fadeIn, timeOutInterval);
    return;
}

function fadeOut() {
    if (opacity <= pEndOpac) {
        clearTimeout(timeoutVar);
        return;
    }
    opacity = opacity - opacityChangePerFrame;
    if (opacity < 0) {
        opacity = 0;
    }
    elemId.style.opacity = opacity;
    timeoutVar = setTimeout(fadeOut, timeOutInterval);
    return;
}
person mornaner    schedule 03.09.2012
comment
Спасибо за ответ, я попробовал предложенное вами изменение, к сожалению, оно не сработало. Я также не вижу, чем это отличается от того, что у меня есть сейчас, timeoutVar очищается только тогда, когда элемент достигает конечной непрозрачности. При том, как я использую, он очищается только тогда, когда непрозрачность равна 0. - person ksrb; 03.09.2012
comment
@ user1490379 Вы правы, я кое-что упустил. Я отредактировал свой ответ, чтобы показать вашу проблему. - person mornaner; 03.09.2012
comment
Вау, хороший глаз, я чувствую себя глупо, лол, большое спасибо за быструю отладку и ответ! - person ksrb; 03.09.2012