width in procent < 1

Status
Niet open voor verdere reacties.

That Guy

Meubilair
Lid geworden
28 nov 2006
Berichten
5.010
Hi allemaal,

ik was druk bezig met een projectje, nu zit daar een piece-bar in, gemaakt met Javascript. Alles was leuk en goed, behalve dat de 'delen' van de bar dus in % zijn opgedeeld. Stel er zijn 5 stukken, is elk dus 20%.

Nu, het probleem is dus dat het kan zijn dat er meer dan 100 stukken in zo'n bar zitten. Dan heb je dus aparte waardes, als 0.016934%.

En het probleem is dus dat niet alle browsers (geen eigenlijk) dit compleet goed doet. Er blijft dan een stukje links dat niet gevuld wordt. En dat's natuurlijk niet de bedoeling.

De CSS1 spec zegt hier niets zinnigs over, dus ik neem aan dat browsers dit zelf invullen, en vandaar dus de verschillen. Zie de bijlage voor wat voorbeelden.




Wie kan mij vertellen hoe dit op te lossen is. Of, of er wel een oplossing voor is!


V. :thumb:
 

Bijlagen

  • widthproc.png
    widthproc.png
    3,2 KB · Weergaven: 54
Hoi Vegras,
Op 't ogenblik regeert CSS2.1, maar ook daar kan ik niets over percentage-afronding vinden.
Als ik je plaatje bekijk, bedoel je dan dat het Firefox-staafje op 1px van de linkerkant af begint, in tegenstelling tot de rest?
  • M'n eerste impuls was, dat je er dan wellicht een stukje background-img achter kunt zetten, dat er altijd is: en bij een spleetje dat spleetje ongemerkt opvult.
  • M'n tweede impuls was, dat je dan misschien het script de afronding tot hele px kunt laten verzorgen, voordat een browser ermee aan de haal kan gaan.
Maar ik heb geen flauw idee hoe je (javascript) die staafbarretjes genereert, en waar de width: 1.08696% op slaat, of hoe die in de figuur geduid moet worden.
  • Dus als dit 't niet is, de bekende vraag: linkje, code? :)
Met vriendelijke groet,
CSShunter
 
Hi,

Zie de bijlage voor een werkend voorbeeld.

De javascript kan mooier (className is niet echt strak, maargoed) maar dat is nu even niet het punt. De code wordt zo aangeroepen:[JS] var bar = new UI.progressBar(document.body, 133); /* stop m in de body. heeft 133 stukjes */[/JS]in zo'n geval heeft ie dus 100 / 133 = 0.751... % breedte per stukje.
Hij maakt dan dus 133 divjes aan met breedte 0.751...% die ie in de container-div stopt - deze heeft 100% breedte.

achtergrond-plaatjes zitten in de map progress/.

De bijlage heeft alle bestanden, en een demo-file. Open test.html in een willekeurige browser, en zie het probleem!


alvast bedankt :thumb:
 

Bijlagen

  • test.zip
    2,9 KB · Weergaven: 30
Laatst bewerkt:
Na nog wat testjes zijn dit de tussenstanden:
IE - afronden naar 2 decimalen
Firefox: - in pixels, dus relatief aan breedte scherm, maar afgerond op 5 decimalen
Safari - ook in pixels, maar alleen hele getallen
Opera - doet het niet (... waar hebben ze het developers console gestopt in de nieuwe versie?)
Chrome - hele getallen
mocht je het zelf willen proberen, open dan de testpagina, en plak dit in de adres-balk, en dan enter:[JS]javascript: alert(getStyle(document.getElementById('pbi-4'), 'width'));[/JS]


Het lijkt er dus op dat de browsers het zelf invullen, wat wel moet als de spec die er niets over zegt.... Overgens is de kleine misser van firefox (soms mist ie 1px) niet erg, maar de andere browsers... tsja. De vraag blijft, hoe is dit het beste op te lossen? :)


:thumb:
 
Laatst bewerkt:
Ik heb 't nooit wetenschappelijk getest of zo, maar mijn ervaring is dat 't boven tienden van procenten onmiddellijk uiteen gaat lopen tussen browsers. Dat komt dus aardig overeen met jouw experiment, hoewel jij 't daadwerkelijk hebt getest.
Ook niet zo vreemd misschien. Uiteindelijk moet 't in px worden weergegeven, en 't heeft weinig zin om dan in duizendsten van procenten te gaan rekenen. En kennelijk 'bewaren' die browsers dus niet (allemaal) (op dezelfde manier) de afrondings-overschotten om die later netjes af te handelen.
Ik ben absoluut geen JavaScript-kenner, maar kun je in je JavaScript niet iets inbouwen dat boven elke tweede/derde/vierde (uitproberen) berekening wordt afgerond naar het bovenste gehele getal of zo? Of 't bovenste tiende procent? Dus de browsers als het ware dwingen wél iets te doen met de afrondingsverschillen, en allemaal op dezelfde manier?
Ik zie trouwens mogelijk hetzelfde verschijnsel bij het zoomen van dunne borders (1px breed). De ene browsers maakt er eerder 2px van dan de ander. Ik heb altijd vermoed dat dat met afronden te maken had.
 
Laatst bewerkt:
Hm, ik heb even wat lopen klooien met afronden, maar uiteindelijk wordt het er niet beter op. Hoewel er een overflow-hidden op zit, is het natuurlijk niet de bedoeling dat delen onzichtbaar worden omdat de breedte uitkomt op 105%.

Ben maar overgestapt op een 'normale' progressbar. In ieder geval bedankt voor het kijken.



:thumb:
 
Tja, je maakt het jezelf en de browsers ook niet gemakkelijk! :D

Wat gebeurt er feitelijk? Ik doe even alsof ik een universele browser ben...

  • Ik krijg als instructie dat ik een .progressbar-outer moet aanmaken met een breedte van 100% van de body plus een bordertje links van 1px en een bordertje rechts van 1px.
  • De breedte van mijn .progressbar-outer is dus (body*100% + 2px) en daarmee géén percentage van mijn body.
  • De 100% breedte van mijn body is in px uitgedrukt afhankelijk van de resolutie.
  • De breedte van mijn .progressbar-outer heeft dus niet standaard een vaste verhouding tot mijn body-breedte.
  • Als ik .progressbar-outer{border-width: [ietsmoois]px 0px;} krijg toegediend is dat wel zo: dan is mijn .progressbar-outer precies even breed als mijn body-breedte.
  • De 100% breedte van mijn body is ervan afhankelijk, welke browser ik ben: want de margin-left/right en de padding-left/right van mijn body zijn niet gedefinieerd.
  • Als ik body{margin: 0; padding: 0;} krijg toegediend, is deze browser-afhankelijkheid er niet: dan is mijn body en mijn .progressbar-outer precies schermbreedtevullend.
  • Maar ik ben er nog niet!
  • De 100% breedte van mijn body is ervan afhankelijk, of mijn baas mijn browser-vensterbreedte wellicht heeft verkleind.
  • De 100% breedte van mijn body is ervan afhankelijk, of ik al (IE e.a.) of niet (FF) ruimte reserveer voor een rechter-scrollbar.
  • Als er html {height: 101%;} wordt toegevoegd, is die afhankelijkheid er niet (altijd scrollbar, ook in FF).
  • De 100% breedte van mijn body is ervan afhankelijk, hoeveel die voor de scrollbar gereserveerde ruimte is. Ai, dat is ervan afhankelijk wie ik ben; want dat verschilt per browser.
  • Ook bij een bepaalde resolutie en 100% windowbreedte valt dus met geen mogelijkheid te voorspellen, hoe breed in px mijn body is.
  • Dat maakt al met al het universeel afronden "van wat?" behoorlijk onvoorspelbaar!
We gaan maar even verder.
Stel ik ben ingesteld op geen scrollbar in FF.
  • (voor de veiligheid het Doctype nog even op Strict ingesteld, en utf-8 als charset)
  • Volgens de gegenereerde broncode gaat FF de 100/133 afronden naar 0.75188%.
  • Dat is wel héél erg onnauwkeurig. ;)
  • Mijn WinRekenmachine zegt: 100/133 = 0.75187969924812030075187969924812.
Maar hoe dan ook: er moet niet alleen een afrondingsfout(je) plaatsvinden, er wordt bovendien een systematische fout ingebakken, die zichzelf niet corrigeert.

Elk 1/133 partje wordt er namelijk als zelfstandig partje ingezet, met (opnieuw) z'n afrondingsbenadering.
De som van de 133 partjes geeft dan 133 keer de afrondingsfout te zien, en niet 1 keer!
  • Als de verschillende browsers een verschillend afhak-punt (of: een verschillende afhakmetode) hanteren voor het afronden (en dat doen ze!), dan kunnen er dus op het eind aanzienlijke verschillen ontstaan.
  • Hoe grover de afronding plaatsvindt, hoe erger de systematische fout. En omdat kennelijk naar beneden afgerond wordt: hoe groter het gat in de niet volgelopen progressbar is.
  • Het valt me trouwens nog mee, wat de browsers er van maken op het eind.
Goed - zo kom je er aan, maar hoe kom je er van af? :D

Als de browsers niet goed kunnen smokkelen (afronden), moet er een eigen smokkelmachine uitgevonden worden. Ik zie daarvoor in principe twee mogelijkheden:

1. De systematische fout vermijden.
  • Dit zou kunnen door het script zodanig aan te passen, dar er niet telkens opnieuw een partje bijgeplaatst wordt, maar het eerste partje steeds vervangen wordt door een nieuw partje.
  • Bij elk nieuw partje wordt de %-berekening opnieuw uitgevoerd.
  • Op het laatst kan je dan hooguit 1px verkeerd uitkomen.
  • Dat kan weggesmokkeld worden, door er standaard aan het begin een partje van 1px breed in te zetten.
2. de systematische fout corrigeren.
  • Dit is wat eerder mijn tweede impuls was (het script de afronding tot hele px laten verzorgen, voordat een browser ermee aan de haal kan gaan), en wat door Goeroeboeroe wat gedétailleerder aangeleverd is.
  • Ik denk dat je dan zou moeten uitkomen op een "schrikkeljaren-politiek".
  • Eerst laten uitrekenen op hoeveel het totaal uitkomt, als je een pure javascript-afronding per partje doorvoert.
  • Dus kom je tekort, met een bekend aantal "tekorte pixels".
  • Laten delen op het totaal, en je krijgt dat er telkens na x partjes met standaard-afronding één partje met standaard+1px tussen moet.
  • Maar om zoiets te destilleren uit de percentage-gewijze body-breedte kan best wel eens erg gecompliceerd worden!
Met vriendelijke groet,
CSShunter
 
Hi CSSHunter,



bedankt voor de (uitgebreide) uitleg danwel info. Heb het even doorgenomen, en vind je 2e oplossing geweldig - ik ga vanavond even klooien met de tekort-aan-pixels-opnieuw-rekenen techniek. :D



:thumb:
 
Hoi Vegras,
Jij klooien, ik klooien. :)
Ik bedacht nog een derde mogelijkheid:

3. De vraag wijzigen :D
Als ik het doel van de hele operatie omschrijf als:
  • "Maak een progressbar/benchmark-bar die bij elke resolutie en bij elke vensterbreedte exact de maximaal beschikbare breedte gebruikt."
... dan zou het met wat eenvoudig javascript te fabrieken moeten zijn.
D.w.z. ik ben geen held in js, en daarom eerst de js-code van de FF-Developer-toolbar opengetrokken, want die kan bij elk element altijd de precieze pixelmaat laten zien. Het trefwoord blijkt te zijn: "element.clientWidth". Daar kunnen we wel iets mee:
  • Nu zijn we van de 2px voor de bordertjes af.
  • Bij elk scherm weten we nu precies het aantal pixels van de "100%" bar, zeg 981px.
  • [edit]Hoe de in gebruik zijnde browser daaraan gekomen is (welke resolutie, welke vensterbreedte, welke scrollbar-breedte, welke afronding): dat willen we niet eens weten. ;)[/edit]
  • We maken partjes van precies 1pixel breed, en daarvan moeten we er dus in dit geval 981 hebben.
  • Nooit geen centje pijn: altijd prijs.
Alleen nog even in een functie gieten. Ik begon met de 1px-staafjes als achtergrond in een innerHTML te laten verschijnen.
  • Dat werkt: www.developerscorner.nl/csshunter/test-staafjes-a.htm,
    maar vraag niet hoe.
  • Want de bar wordt dan wel precies mooi tot het eind opgevuld, maar he-re-mijn-tijd-wat-kan-dat-in-som-mi-ge-brow-sers-vre-se-lijk-lang-duren ...
  • Met de stopwatch: Opera doet het in 7 sec., Safari in 5 sec., maar FF3.0 doet over dit simpele rekensommetje ... 44 sec., en IE7 heeft 55 sec. nodig. :confused:
  • Wel een script dat aardig geschikt is voor een browser-snelheidstest, maar niet voor dagelijkse consumptie in een progressbar.
  • En nu had ik het achtergrond-img al van 15px breed tot 1px breedte teruggebracht (van een 957 bytes png naar een 189 bytes png), en toen ik merkte dat er 16 kleuren in zaten naar een 16-kleurig gifje van slechts 84 bytes. Dat zou de zaak toch moeten bespoedigen, zou je denken - maar nee hoor.
Toen hetzelfde geprobeerd door de staafjes als domino-steentjes naast elkaar te laten zetten als voorgrond-images. > geen noemenswaardige verbetering.
Toen jouw originele code erbij gepakt, want daarin deed ie het toch wel snel.
Afijn, de css en dat script waar maar enigszins mogelijk uitgedund, en toen kwam ik op:
  • Een aardige progress/benchmark-bar, al zeg ik het zelf:
    www.developerscorner.nl/csshunter/test-staafjes-b.htm. :)

  • Met cross-browser speed, en ook goed voor zo nauwkeurig mogelijke percentages bij een gegeven resolutie.
  • Geen pixel teveel of te weinig! :p
  • En weer wat javascript geleerd (met dank).
Maar, om terug te komen op de openingszet, met deze herformulering van de vraag heb ik geen flauw idee of dit nog wel tegemoet kan komen aan het doel. Want wat waren bv. de diepe gronden waarom die 1/133 breedte uit de lucht kwam vallen? Waarom niet 1/134 breedte? Ik kan zomaar niet bevroeden wat dat in heb.

Dus mocht dit niet passen in de bedoeling: "omschrijf de vraag helder en duidelijk". ;)

Met vriendelijke groet,
CSShunter
 
Laatst bewerkt:
Hi CSSHunter,


Oef, gisteren was ik net aan het klooien, toen ik in gevecht raakte met een stuk of 30 BSOD's. Dus van veel klooien is het niet gekomen, athans, niet met Javascript. Wel met Asus drivers :rolleyes:


Het hele idee van de 'piecebar' was dat het in tegenstelling tot een progressbar niet liniear hoeft vol te lopen. Mocht je een torrent-programma hebben, deze geven op deze manier meestal ook de beschikbare delen aan in een zwerm. Zie hier wat ik bedoel (excuses voor het slechte plaatje, kon zo snel even niets beters vinden): klik (in het midden, blauwe balk).

Het punt is dus dat bijvoorbeeld 'stukje' nummer 15 eerder 'klaar' is dan stukje nummer 3. Daarom moet er een referentie zijn naar elk stukje, zodat je de kleur kan veranderen.

Het aantal 133 was zomaar even uit de lucht gegrepen (nouwja, bijna - het is een niet-mooi delend getal, vandaar). Het kan net zogoed 42 of 1337 stukjes hebben. Het punt is dat het goed moet werken voor alle mogelijke stukjes. Uitzondering is natuurlijk als er meer stukjes zijn dan pixels mogelijk.


Over het snelheidsprobleem van je eerste pagina: dat kwam door je innerHTML regel. Elke keer in de loop moet-ie opnieuw de DOM vragen wat nou precies het innerHTML is, daar de extra div als string achter plakken, en deze terugstoppen, en dan nogmaals parsen (in mijn geval 1258 keer - en deze universiteits-computers zijn al zo snel)! Als je in plaats van dit:[JS] for (i=0; i<w; i++) {
bar.innerHTML = bar.innerHTML + '<div class="'+barColor+'"><\/div>';
}
[/JS]zoiets doet, zoals in je 2e voorbeeld:[JS] for (i=0; i<w; i++) {
var newInner = document.createElement('div');
newInner.setAttribute('class', barColor)
bar.appendChild(newInner);
}
[/JS]zou het een stuk sneller gaan. Denk ik.


Ik heb tijdelijk voor het project (waar de piecebar voor bedoeld was) maar een simpele, 'normale' progressbar gebruikt, die iets 'slimmers' (lees: simpelers) doet - alleen html en css (div in div, binnenste div heeft breedte in % die je wilt hebben). En het mooiste is nog dat-ie ook mee resized.

Hopelijk doet windows 7 vandaag niet zo vervelend en kan ik weer wat proberen!



:thumb:
 
Laatst bewerkt:
Hier heb ik eventjes een redelijke implementatie van oplossing #3 gemaakt. Het klopt opeens een stuk beter, maar nogsteeds niet optimaal - maargoed. Hier de aangepaste js-code:[JS]
var UI = {}



function getStyle(el, styleProp)
{
if(el.currentStyle)
{
return el.currentStyle[styleProp];
}else if(window.getComputedStyle)
{
return document.defaultView.getComputedStyle(el, null)[styleProp];
}
return null;
}

UI.progressBar = function(loc, parts)
{
this.parts = parts;

///this.pWidth = 100 / this.parts; // dit werkt dus niet, omdat niet alle browsers
// niet-afronden (= browsers ronden af). Erg
// vervelend, want nu werkt dit dus niet. Maar
// niet gevreesd, een oplossing is onderweg!

this.pWidth = 0;





this.setPart = function(part, toc)
{
if(!this.inner[part])
{
part = parseInt(part, 10);
}

switch(toc)
{
case 'green': this.inner[part].className = 'progressbar-inner green'; break;
case 'red': this.inner[part].className = 'progressbar-inner red'; break;
case 'blue': this.inner[part].className = 'progressbar-inner blue'; break;
case 'yellow': this.inner[part].className = 'progressbar-inner yellow'; break;
}
}

this.setAllParts = function(color)
{
for(var i=0; i<this.parts; i++)
{
this.inner.className = 'progressbar-inner ' + color;
}
}

this.outer = document.createElement('div');
this.texth = document.createElement('span');
this.inner = [];

this.outer.setAttribute('class', 'progressbar-outer');
this.texth.setAttribute('class', 'progressbar-text');

this.outer.setAttribute('style', 'width: 100%');

var i;

loc.appendChild(this.outer);



/* Bereken de goede breedte-script */


//this.pWidth moet gelijk zijn aan 1/parts -e van de totale breedte van onze this.outer.
//dus, verkrijg deze eens:

var outerWidth = parseInt(getStyle(this.outer, 'width'), 10);


//Browsers ronden in het ergste geval af tot hele getallen
//om daar een stokje voor te steken gaan we het eens zelf doen:

var fWidth = (outerWidth / this.parts).toFixed(0);
var fMiss = outerWidth - (fWidth * this.parts);


document.write('elk van de ' + this.parts + ' stukjes is ' + fWidth + 'px - dat brengt een totaal van ' + (fWidth * this.parts) + 'px<br />');
document.write('oh noes! De gehele breedte van de stukjesstrook is ' + outerWidth + ' - dan missen we ' + fMiss + 'px!<br />');


//mkay, we hebben dus fMiss px te weinig. Deze gaan we dus eens even doorrekenen
//op alle stukjes - het komt er eigenlijk op neer dat alle stukjes dus breedte fWidth
//hebben, en fMiss stukjes 1px meer.

//omdat om-de-zoveel-stukjes-een-pixel-meer makkelijker is (klinkt moeilijker,
//is makkelijker) gaan we dat eens doen. Rond af, want loopen gaat met stap 1.
//dit geeft dus *weer* een afrondingsfout. Maarja, je kan niet alles hebben */


var omDeHoeveelStukjesEenPixelMeer = (this.parts / fMiss).toFixed(0);

document.write('om de ' + omDeHoeveelStukjesEenPixelMeer + ' stukjes eentje met een pixeltje moar!<br />');


this.pWidth = fWidth;

/* einde bereken goede breedte-script */

var w;

for(i=0; i<this.parts; i++)
{
w = this.pWidth;
this.inner = document.createElement('div');
this.inner.setAttribute('class', 'progressbar-inner');
this.inner.setAttribute('id', 'pbi-' + i);

if(i % omDeHoeveelStukjesEenPixelMeer == 0)
{
w++;
}

this.inner.setAttribute('style', 'width: ' + w + 'px');


this.outer.appendChild(this.inner);
}


};
[/JS]als je dit verwisseld met de huidige code voor UI.progressBar krijg je ook mooi wat debug-code op je scherm.



Nog wat geleerd: 3 modulus oneindig is 3. :p
 
Laatst bewerkt:
Hier heb ik eventjes een redelijke implementatie van oplossing #3 gemaakt. Het klopt opeens een stuk beter, maar nogsteeds niet optimaal - maargoed. Hier de aangepaste js-code:[JS]
var UI = {}



function getStyle(el, styleProp)
{
if(el.currentStyle)
{
return el.currentStyle[styleProp];
}else if(window.getComputedStyle)
{
return document.defaultView.getComputedStyle(el, null)[styleProp];
}
return null;
}


UI.progressBar = function(loc, parts)
{
this.parts = parts;

///this.pWidth = 100 / this.parts; // dit werkt dus niet, omdat niet alle browsers
// niet-afronden (= browsers ronden af). Erg
// vervelend, want nu werkt dit dus niet. Maar
// niet gevreesd, een oplossing is onderweg!

this.pWidth = 0;





this.setPart = function(part, toc)
{
if(!this.inner[part])
{
part = parseInt(part, 10);
}

switch(toc)
{
case 'green': this.inner[part].className = 'progressbar-inner green'; break;
case 'red': this.inner[part].className = 'progressbar-inner red'; break;
case 'blue': this.inner[part].className = 'progressbar-inner blue'; break;
case 'yellow': this.inner[part].className = 'progressbar-inner yellow'; break;
}
}

this.setAllParts = function(color)
{
for(var i=0; i<this.parts; i++)
{
this.inner.className = 'progressbar-inner ' + color;
}
}

this.outer = document.createElement('div');
this.texth = document.createElement('span');
this.inner = [];

this.outer.setAttribute('class', 'progressbar-outer');
this.texth.setAttribute('class', 'progressbar-text');

this.outer.setAttribute('style', 'width: 100%');

var i;

loc.appendChild(this.outer);



/* Bereken de goede breedte-script */


//this.pWidth moet gelijk zijn aan 1/100e van de totale breedte van onze this.outer.
//dus, verkrijg deze eens:

var outerWidth = parseInt(getStyle(this.outer, 'width'), 10);


//Browsers ronden in het ergste geval af tot hele getallen
//om daar een stokje voor te steken gaan we het eens zelf doen:

var fWidth = (outerWidth / this.parts).toFixed(0);
var fMiss = outerWidth - (fWidth * this.parts);


document.write('elk van de ' + this.parts + ' stukjes is ' + fWidth + 'px - dat brengt een totaal van ' + (fWidth * this.parts) + 'px<br />');
document.write('oh noes! De gehele breedte van de stukjesstrook is ' + outerWidth + ' - dan missen we ' + fMiss + 'px!<br />');


//mkay, we hebben dus fMiss px te weinig. Deze gaan we dus eens even doorrekenen
//op alle stukjes - het komt er eigenlijk op neer dat alle stukjes dus breedte fWidth
//hebben, en fMiss stukjes 1px meer.

//omdat om-de-zoveel-stukjes-een-pixel-meer makkelijker is (klinkt moeilijker,
//is makkelijker) gaan we dat eens doen. Rond af, want loopen gaat met stap 1.
//dit geeft dus *weer* een afrondingsfout. Maarja, je kan niet alles hebben */


var omDeHoeveelStukjesEenPixelMeer = (this.parts / fMiss).toFixed(0);

document.write('om de ' + omDeHoeveelStukjesEenPixelMeer + ' stukjes eentje met een pixeltje moar!<br />');


this.pWidth = fWidth;

/* einde bereken goede breedte-script */

var w;

for(i=0; i<this.parts; i++)
{
w = this.pWidth;
this.inner = document.createElement('div');
this.inner.setAttribute('class', 'progressbar-inner');
this.inner.setAttribute('id', 'pbi-' + i);

if(i % omDeHoeveelStukjesEenPixelMeer == 0)
{
w++;
}

this.inner.setAttribute('style', 'width: ' + w + 'px');


this.outer.appendChild(this.inner);
}


};
[/JS]als je dit verwisseld met de huidige code voor UI.progressBar krijg je ook mooi wat debug-code op je scherm.

De .toFixed(0) in plaats van Math.round() is zodat we zeker weten dan we te 'weinig' hebben - het haalt immers de decimalen gewoon 'weg'. Dit is denk ik beter dan round, omdat je zo makkelijker kan rekenen en er geen rekening mee hoeft te houden dat je mischien wel een te breedt stukje hebt.

Overgens klopt het niet helemaal, soms heb ik 'negatieve' pixels over, wat logisch gezien dus teveel is - maar dit is niet waar, want de stukjesreep is dan nogsteeds niet helemaal vol.


:thumb:
 
Aha!
Ik dacht eerst dat het om een tijdsafhankelijke progressbar zou gaan, waarbij de vulling kan plaatsvinden met partjes van 1px breed die elkaar konden opvolgen.
Maar het is dus een "partjes-afhankelijke" progressbar: ik vergelijk 'm maar met een defragmentatie-balk, waarvan je ook de partjes van kleur kunt zien verschieten als ze klaar zijn.
Dan moet inderdaad met 133 of 517 of een ander mooi ondeelbaar getal aan partjes rekening gehouden worden.

Om eerlijk te zijn, ik kan je redenering met het aftrekken van de negatieve afgeronde tekorten niet helemaal volgen. :rolleyes:
Het zal wel goed zijn, dacht ik eerst: dit gaat gewoon even boven mijn pet.
Maar toen ik je code in een testbestandje zette, begon ik daaraan te twijfelen:
  • Dit is een screenshot van enkele resultaten, met de opgemeten tekorten erbij gezet.
  • En dit is het geknipte en geplakte testbestand waarmee de screenshots geschoten zijn..
Het lijkt wel alsof het laatste partje gewoon niet geplaatst wordt (omdat het "negatief tekort is", en dus over de balk heen zou struinen?). - Bij 133 partjes valt het niet zo op dat het een heel missend partje is, daar lijkt het alsof het om een afronding van het totaal gaat.

Mijn "positieve tekort" beredenering op zijn jan-boeren-fluitjes:
  • 1008px ter beschikking.
  • 133 partjes gevraagd.
  • 1008/133= 7,5789...enz. aan pixels breedte van een partje nodig.
  • Dat bestaat niet. Dus gehakt, en 133 partjes van 7px breed gemaakt.
  • Geeft 133x7= 931 totale breedte.
  • Maar er is 1008 beschikbaar, dus 1008-931= 77px overschot op de totaalbalk.
  • Die moet uitgesmeerd worden over de 133 partjes.
  • 77px op de 133 partjes = 77/133= 58% van de partjes moet 1px meer krijgen. Dat ligt tussen de 1 en 1/2 (reeks: 1, 1/2, 1/3, 1/4, 1/5 enz.), dus nemen we de kleinste (1/2) om niet over de balk heen te schieten.
  • Dan krijgt elk tweede partje de ene px extra.
  • Na twee partjes hebben we 7+8= 15px opgevuld.
  • Na 132 partjes hebben we 132/2= 66 keer die 15px gemaakt.
  • Dan is er dus 66x15= 990px gevuld.
  • Laatste partje geven we ook 8px in plaats van 7px.
  • Dan is er 998px van de balk van 1008px gevuld.
  • Door alle afrondingen is hier dus nog een schoonheidsfout van 10px tekort op de balk.
  • Op deze manier kan het nooit fout gaan: of het klopt toevallig, of er is een onafgedekt tekort op de balk.
  • Maar de balk kan nooit overstromen! :)
Kan je het op zo'n manier in javascript-code omzetten?

O ja, voor de finishing touch om de schoonheidsfout weg te werken heb ik een eitje van Columbus uitgebroed.

Wordt vervolgd!
Met vriendelijke groet,
CSShunter
 
Laatst bewerkt:
Vervolg.
Columbus zegt:
Als alles uitgerekend is, kan je alle in werkelijkheid weergegeven partjes bij elkaar optellen.
Die som is dus ietsjepietsje <= de startbreedte van 100%.
Maar daar zitten we niet mee: dan geven we achteraf de progressbar precies de lengte van de optelsom:
this.outer.style= 'width: '+optelsom+'px';

:D
Alleen met een heel trage processor zal je de progressbar even op 100% zien, om 'm daarna te zien terugfloepen naar de optelsom.
Dat lijkt me wel een aardige smokkelroute. - Klaar is Vegras?

Met vriendelijke groet,
CSShunter
 
Laatst bewerkt:
Hi,


Helaas niet zo heel veel tijd gehad de laatste tijd - en het wordt eens tijd dat ik er aan werk. Mocht ik hem afhebben, of toch nog ergens tegenaan lopen, horen jullie 't!


Groet, Vegras :thumb:
 
Hoi Vegras,
Ik kwam er ook de laatste weken niet aan toe iets verder te doen met mijn jan-boerenfluitjes-logica en eieren van Columbus.
Maar onderhuids heeft 't kennelijk zitten broeden, want ik bedacht: waarom zou eigenlijk het resultaat van de overschietende pixels perse op gelijke afstanden verdeeld moeten worden over de progressbar? Voor het mooi?
  • Dat kan wel, maar als je het goed wilt doen, krijg je in feite te maken met een soortement van staartdeling die je in een loop vangt: in de eerste ronde de breedte delen op het tekort, afronden & uitsmeren > geeft nieuw (kleiner) tekort > breedte delen door nieuwe tekort, afronden en uitsmeren > enz., net zolang tot je op het laatst een waarde van <1 (pixel) overhoudt, dan kan de loop stoppen).
Toen viel me in dat het helemaal niet zo ingewikkeld hoeft, en de verschillende brokjes op de progressbar toch op het oog even mooi (en misschien wel mooier/onopvallender) kunnen zijn, als je niet boven de ca. 200 brokjes uit komt:
Natuurlijk heeft IE weer nukken en grillen: in IE8 komt ie voortijdig met het resultaat op de proppen :)eek: ?), en IE7 rekent het wel goed uit (ook on-the-fly), maar toont het resultaat niet. - Dat zal aan de ophanging of de css liggen vermoed ik, en daar zou uit te komen moeten zijn (IE6 beschouw ik maar als afgelopen).
Waar ik achter kwam, was dat toFixed() toch naar boven of naar beneden afrondt, net als Math.round().
  • Dat zou te ondervangen zijn met een vergelijking van de onafgeronde en de afgeronde waarde (als de afgeronde waarde groter is, dan moeten er {afgerond-1} stukjes komen, anders {afgerond}.
Maar parseInt() doet dit gewoon uit zichzelf, da's makkelijker.

Met vriendelijke groet,
CSShunter
 
Wauw, helemaal geweldig. Mn excuses voor het late bericht overgens.




Bedankt!
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan