Door
The Ultimate
op 19-12-2010 13:46
gewijzigd op 19-12-2010 14:58
9.518 views
Hallo,
Ik ben een total noob als het aankomt op javascript. So bare with me please...
Ik ben bezig met een website. Deze website maakt gebruik van een database. In deze database staan entries met geldbedragen. Deze geldbedragen laat ik de database bij elkaar optellen en dat is dus het bedragTotaal (o.i.d.). Het script en de database hiervoor moet ik nog maken.
Op deze website wil ik graag een realtime teller tonen (javascript?) die iedere seconde controleert wat het bedragTotaal is. Wanneer dit omhoog is gegaan dient de teller naar boven te worden bijgesteld. Het liefst zie ik dan de cijfers naar boven 'wegrollen' zoals je bij een gasmeter ook hebt. Dit zal dus een soort transitie of animatie moeten zijn.
Wie kan mij op weg helpen want ik heb gezocht, maar kom geen script tegen waar ik iets mee kan.
Helaas werkt het nog niet. Vreemd, want op de developers page werkt het uitstekend. Maar hoe kan ik er voor zorgen dat het script iedere seconde het bedragTotal controleert en optelt vanaf het huidige bedragTotal naar het nieuwe bedragTotal? En is het dan mogelijk om een soort van transitie toe te voegen? Bijvoorbeeld dat de eerste en laatste cijfers langzamer gaan dan de middelste?
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Untitled Document</title>
</head>
<body>
<h1>Jquery Number Ticker - By Damien Howley</h1>
<div class="counter-wrap">
<div class="counter-number">
</div>
</div>
<div>
<style>
.counter-wrap {
height:18px;
overflow:hidden;
}
.counter-number {
height:198px;
width:12px;
position:relative;
background-image:url(img/counter_ticker_bg.gif);
float:left;
}
</style>
<a href="#" onclick="loadticker(0786554)">load ticker - 786554</a><br/><br/>
<a href="#" onclick="loadticker(01767697234789837)">load ticker - 1767697234789837</a><br/><br/>
<a href="#" onclick="loadticker(01988989)">load ticker - 1988989</a><br/><br/>
</div>
<script src="js/jquery-1.4.4.min.js" type="text/javascript"></script>
<script type="text/javascript">
Deki.$(".counter-number").each( function(i) {
Deki.$(this).attr('id','num'+i);
});
function loadinput() {
var newval = Deki.$("#numgo").val();
loadticker(newval);
}
function loadticker(ticnum) {
var fticnum = add_commas(ticnum);
var numheight=18;
addticker(fticnum);
if (ticnum && ticnum != 0) {
var s = String(fticnum);
for (i=s.length;i>=0; i--)
{
var onum=s.charAt(i);
Deki.$("#num"+i).attr('value',onum);
}
Deki.$(".counter-number").each( function() {
var nval=Deki.$(this).attr("value");
if (!isNaN(nval)) {
var nheight = Number(nval)*numheight*-1;
Deki.$(this).animate({ top: nheight+'px'}, 1500 );
}
if (nval==','){
Deki.$(this).animate({ top: '-180px'}, 1500 );
}
});
}
}
function addticker(newnum) {
var digitcnt = Deki.$(".counter-number").size();
var nnum = String(newnum).length;
var digitdiff = Number(nnum - Number(digitcnt));
if (digitdiff <0) {
var ltdig = (Number(nnum)-1);
Deki.$(".counter-number:gt(" + ltdig + ")").remove();
}
for(i=1;i<=digitdiff;i++) {
Deki.$(".counter-wrap").append('<div class="counter-number" id="num' + (Number(digitcnt+i-1)) + '"> </div>');
}
}
function add_commas(nStr) {
nStr += '';
x = nStr.split('.');
x1 = x[0];
x2 = x.length > 1 ? '.' + x[1] : '';
var rgx = /(\d+)(\d{3})/;
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + ',' + '$2');
}
return x1 + x2;
}
</script>
</body>
</html>
Dit het mijne (ik ben iets zuiniger met whitespace :) )
<html>
<head>
<script src="jquery.js" type="text/javascript"></script>
<script type="text/javascript">
$(document).ready(function() { startCount(); });
var cStart = 0;
var cEnd = 0;
function startCount() {
// Beginwaarde en eindwaarde ophalen
timerStartValue();
timerEndValue(); // start meteen de gasmeter-teller
}
// wachtlus-teller
function checkEndValue() {
// Oude timerEndValue opslaan
cEndOld = cEnd;
// Nieuwe timerEndValue opvragen
timerEndValue();
// Oude en nieuw timerEndValue met elkaar vergelijken
if (cEndOld < cEnd) {
// Teller opnieuw starten
timedCount();
} else {
// Over 10 seconden weer controleren
setTimeout("checkEndValue()",1000);
}
}
function timedCount() {
cStart=cStart+1; // Wat moet er met de waarde gebeuren
$("#displayCounter").html(cStart); // Waarde in HTML object plaatsen
// Stoppen wanneer de Timer op cEnd staat
if (cStart < cEnd) { // zolang we er nog niet zijn, doortellen
setTimeout("timedCount()",300);
} else {
checkEndValue();
}
}
function timerStartValue() {
$.get('get_amount.php',
function(data) {
cStart = data - 10;
cEnd = data;
// Beginwaarde tonen
$("#startValue").html(cStart);
$("#endValue").html(cEnd);
// Timer starten
timedCount();
}
);
}
function timerEndValue() {
$.get('get_amount.php',
function(data) {
cEnd = data;
// Eindwaarde tonen
$("#endValue").html(cEnd);
}
);
}
</script>
</head>
<body>
<p>De startwaarde is <span id="startValue"></span></p>
<p>De eindwaarde is <span id="endValue"></span></p>
<p>De timer staat nu op: <span id="displayCounter"></span></p>
</body>
</html>
Wow, zeer wazig. Jouw script ziet er (zo zonder al die whitespace) een stuk beter uit en werkt om de een of andere vage reden bij mij wel. Super!
Oh man, ik had het bijna aan de kant gesmeten....
Nog een vraagje:
Je kent ongetwijfeld die transitions (easyInOut,etc) die ze bij foto-albums vaak gebruiken. Zou het denk je mogelijk zijn om een dergelijke transitie in het optellen te verwerken, zodat de eerste en laatste cijfers langzaam wegtikken terwijl de middelste snel? Dus stel dat je van 1 naar 100 gaat dan gaat 1 supertraag, 2 al iets minder traag, 3 traag, 4 langzaam, 5 normaal, 6 t/m 10 snel, 10 t/m 80 supersnel, 80 t/m 96 snel, 97 langzaam, 98, zeer langzaam en uiteindelijk 100 superlangzaam.
Als je tips hebt om het netter te maken dan hoor ik het uiteraard graag!
Edit:
Trouwens, als je een waarde in de database toevoegt gaat de teller niet opnieuw lopen, terwijl er wel iedere 5 sec wordt gecontroleerd op nieuwe waardes. Weet jij hoe dit komt?
Hmm... dat kun je bereiken door de setTimeout in timedCount() een variabel interval mee te geven. Bereken het interval bijvoorbeeld door het domein van de doorteller in drie stukken te verdelen; het middelste stuk krijgt een kort interval, de twee randstukken ofwel een langer interval, ofwel zelfs een verlopende waarde (voor extra vloeiende overgang).
0. detecteer een oploop-verzoek: in checkEndValue en timerStartValue, helaas dus op twee plaatsen. Refactor.
1. markeer eenmaal het domein en de segmenten:
var dist = cEnd - cStart;
var seg0 = cStart + dist/10; // 10% aan de randen
var seg1 = cEnd - dist/10;
Let op de scope van de variabelen!
2. beslis in elke stap (if cStart < cEnd) je intervalgrootte:
timediff = 30; // supersnel
if (cStart < seg0) timediff = 300 - (seg0 - cStart)*270/seg0;
if (cStart > seg1) timediff = 300 + (cStart - seg1)*270/seg1;
3. Go!
setTimeout(timedCount, timediff);
De 'air code' waarschuwing is van overeenkomstige toepassing. Ik heb wel wat wiskunde toegepast voor de timediff-vergelijkingen :)
Ja, aan zo'n soort oplossing zat ik zelf ook al te denken. Dat zou ik dan zelf nog uit kunnen breiden met meer verdeling zodat het vloeiender loopt.
Is het jou ook opgevallen dat wanneer de totale SUM van de database veranderd dat de teller dan niet opnieuw begint te tellen? Heb je enig idee hoe dat komt?
Hahaha, werkt als een trein! Wow, had vanmiddag even niet gedacht dat dit nog zou gaan lukken. Nou moet ik wel zeggen dat jij het mij zo ongeveer voorgekauwd hebt aangeleverd, maar toch...
Mijn dank is groot en mijn bewondering (voor het getoonde geduld) ook. Ondanks dat ik er nog veel moeite mee heb is dit wel de eerste goede stap richting meer javascripts voor mij!
Trouwens, die versnelling en verlangzaming (is dit een woord?) werkt echt supersmooth!
vertraging (verlangzaming :) ik reken het goed, maar dat is meer mijn ervaring met Esperanto)
De berekening is nog lineair, en het snelheidsverloop krijgt daardoor een schok op de overgang naar het 'supersnel'-gedeelte. Je ziet het nauwelijks.
Er valt nog wel wat te winnen op de struktuur van de javascript; dit is een vrij oude stijl van programmeren, het kan ook meer object-georienteerd. Vaak komt dat de onderhoudbaarheid ten goede.
vertraging (verlangzaming :) ik reken het goed, maar dat is meer mijn ervaring met Esperanto)
Thanks
Bas Cost Budde op 20/12/2010 19:17:32
De berekening is nog lineair, en het snelheidsverloop krijgt daardoor een schok op de overgang naar het 'supersnel'-gedeelte. Je ziet het nauwelijks.
Nee, valt nauwelijks op. Vooral wanneer je de snelheden verandert naar 30 en 300.
Bas Cost Budde op 20/12/2010 19:17:32
Er valt nog wel wat te winnen op de struktuur van de javascript; dit is een vrij oude stijl van programmeren, het kan ook meer object-georienteerd. Vaak komt dat de onderhoudbaarheid ten goede.
Moet je er - om het te moderniseren - een classe van maken (heet dit classe in javascript?). Dus bijv:
var Timer = function(){ hier he script }
En dan uiteraard de functies aanpassen naar this.functie() =
Zoiets?