0

I am trying to make the show button bring back the h1 tag but it stops after reaching opacity: 0.1 instead of continuing all the way to opacity: 1.

I have tried debugging on Firebug for hours but cannot seem to crack it. Please help.

<!DOCTYPE html>
<html>
<head>
<title>Flesh and Bone</title>
</head>
<body>
<h1>Flesh and Bone</h1>
<button id="fade">Fade</button>
<button id="show">Bring Back</button>
<h2>The Killers</h2>
<script>
    var el = document.querySelector("h1");
    var fade = document.getElementById("fade");
    var show = document.getElementById("show");
    var fader = function () {
        el.style.opacity = 1;
        var timer = setInterval(function (){
            el.style.opacity -= 0.1;
            if (el.style.opacity == 0) {
                clearInterval(timer);
            }
        }, 40);
    }
    var shower = function () {
        el.style.opacity = 0;
        var timer = setInterval(function (){
            el.style.opacity += 0.1;
            if (el.style.opacity == 1) {
                clearInterval(timer);
            }
        }, 40);
    }
    fade.onclick = fader;
    show.onclick = shower;
</script>
</body>
</html>

3 Answers3

2

This is due to the behaviour of floating point arithmetic. Which is explained in this question. The opacity is never actually reaching 0, so the timer is never cleared.

The solution is to use toFixed(1) when you are performing your subtraction and addition:

var timer = setInterval(function (){
        el.style.opacity = (el.style.opacity - 0.1).toFixed(1);
        if (el.style.opacity == 0) {
            clearInterval(timer);
        }
    }, 40);

JSfiddle example is here: http://jsfiddle.net/28XNK/2/

Community
  • 1
  • 1
Jivings
  • 22,834
  • 6
  • 60
  • 101
2

A few things are contributing to this:

  1. el.style.opacity is always a String, so += will concatenate rather than add. Keep the opacity in a separate variable so it remains a Number.

  2. Numbers aren't so precise as to == 1 or == 0 exactly at the end. Use >= 1 and <= 0 instead.


var fader = function () {
    var opacity = 1;
    el.style.opacity = opacity;
    var timer = setInterval(function () {
        opacity -= 0.1;
        el.style.opacity = Math.max(opacity, 0);
        if (opacity <= 0) {
            clearInterval(timer);
        }
    }, 40);
}

http://jsfiddle.net/qBgJY/

Community
  • 1
  • 1
Jonathan Lonowski
  • 121,453
  • 34
  • 200
  • 199
1

opacity is a string property so you need to convert it to float to modify it:

el.style.opacity = parseFloat(el.style.opacity) + 0.1;
Derick Leony
  • 421
  • 2
  • 7