Jump to content

JavaScript/Smooth counting

From Wikiversity

Smooth counting means that a number will increase steeply at the beginning and then will level off. This can be accomplished with the help of mathematical functions.

<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<meta name="keywords" content="HTML, CSS, JavaScript, social media">
	<meta name="author" content="Elominius, en.wikiversity.org">
	<meta name="license" content="CC0 1.0 public domain">

<style type="text/css">
body { 
	background-color: #333;
	color: #ccc;
	font-family:'noto sans',ubuntu,'bitstream vera sans','segoe ui',arial,helvetica,sans-serif;
}
a { color: lightblue; }
#count_box { font-size:24pt; }
.count_glow { animation: 1.5s 2 alternate count_glow; }

@keyframes count_glow {
  from {
    text-shadow: 0 0 0px yellow;
  }
  to {
    text-shadow: 0 0 15px yellow;
  }
}
</style>
</head>

<body>
<div id="count_box" class="">0</div>

<div>
<label for="count_input">Choose a number to count to:</label>
<input id="count_input" type="number"></input>
<button id="count_start_button" onclick="count(count_input.value);" label="Count to this number">Count to this number</button>
</div>
</body>

<footer>
<hr />
<div id="credit" style="font-size:small;">Created by <a href="https://en.wikiversity.org/wiki/User:Elominius">Elominius from Wikiversity</a>. Released into the public domain under <a href="https://creativecommons.org/publicdomain/zero/1.0/">CC0 1.0</a>.</div>
<!-- JS in footer so it loads last. No window.onload wrapper needed. -->
<script type="text/javascript">
/* declare variables early for global scope */
var count_memory=new Object({});
	count_memory.old=0;
	count_memory.displayed=0;
	count_memory.new=0;
var countUp_interval;
var tanh_animation=0;
var counting_in_progress=false;



function increaseCount() { 
	counting_in_progress=true;
	count_memory.displayed=Math.round( count_memory.old + (count_memory.new-count_memory.old)*Math.tanh(tanh_animation/10) );
	tanh_animation++;
	count_box.innerHTML=count_memory.displayed;
	if ( Math.abs(count_memory.new-count_memory.displayed) < 0.8 /* target number reached */ ) 
	/* Math.abs() allows it to be for counting downwards too. */ {
		clearInterval(countUp_interval); /* stop changing number */
		count_box.innerHTML=count_memory.new; /* set to target number */
		count_memory.old=count_memory.new; /* remember for next time */
		tanh_animation=0; /* reset */
		counting_in_progress=false;
	};
};

function count(input_number){
	if (input_number == count_memory.old) return false; /* reject if number unchanged */
	if (counting_in_progress) return false; /* reject if counting already in progress */
	count_memory.new=parseInt(input_number); /* parseInt forces the object type into number instead of string */
	countUp_interval=setInterval(increaseCount,50); /* increase count every 0.05 seconds */
	count_box.classList.add("count_glow"); /* glowing animation */
	setTimeout(remove_count_glow,3100);  /* stop glowing */
}
function remove_count_glow() { count_box.classList.remove("count_glow"); }

var count_box=document.getElementById("count_box");
var count_input=document.getElementById("count_input");
var count_start_button=document.getElementById("count_start_button");

count_input.onkeydown = function() {
	if (event.keyCode == 13) // Keycode 13 is for enter key, both main and on NUM pad.
	{ 
		count(count_input.value);
	}
};

count_input=document.getElementById("count_input");
</script>
</footer>

</html>