cross browser random pictures
Sebastian Becker
- browser
0 Harry
Hallo,
ich möchte gerne auf einer Seite ein Zufallsbild einbinden.
(Test --> http://www.incontri-berlin.de/index_js.htm)
Folgendes Skript funktioniert im IE 5.5, führt aber auf manchen anderen Browsern bzw. Versionen, die ich leider nicht auf meinem Rechner installiert habe, zur Ausgabe von "undefined":
--------------------------------------------------------------
// Zahl der Bilder hier konfigurieren
var picCount = 5;
// Standard-alt-Text hier konfigurieren
var defaultText = 'INCONTRI - Ristorante Italiano';
randPic = new Array;
picWidth = new Array;
picHeight = new Array;
picTxt = new Array;
altTxt = new Array;
// Array mit Bildnamen hier konfigurieren
randPic[0] = 'restaurant2.jpg';
picWidth[0] = '240';
picHeight[0] = '160';
picTxt[0] = 'Ristorante';
randPic[1] = 'nudelgabel.gif';
picWidth[1] = '120';
picHeight[1] = '180';
picTxt[1] = 'Maccaroni & Gabel';
randPic[2] = 'bar1.jpg';
picWidth[2] = '180';
picHeight[2] = '120';
picTxt[2] = 'Bar';
randPic[3] = 'osteria.jpg';
picWidth[3] = '180';
picHeight[3] = '120';
picTxt[3] = 'C. Bloch, In un osteria romana, 1860';
randPic[4] = 'gabel.jpg';
picWidth[4] = '180';
picHeight[4] = '120';
picTxt[4] = 'Olive & Gabel';
// ---------- Ab hier nichts mehr verändern! ----------
// Standard-alt-Text
for (i = 0; i < picCount; i++)
{
if ( picTxt[i] == '' || picTxt[i] == undefined ) altTxt[i] = defaultText;
else altTxt[i] = picTxt[i];
}
// Zufallsfunktion
var num = Math.round((picCount - 1) * Math.random());
// Ausgabe des HTML-Quelltextes
function ranPic()
{
var str = '<a href="index.htm" onMouseOver="window.status='';return true;" onMouseOut="window.status='';return true;"><img src="img/' + randPic[num] + '" width="' + picWidth[num] + '" height="' + picHeight[num] + '" border="0" alt="' + altTxt[num] + '"></a>';
document.write(str);
// alert(str); // test
}
--------------------------------------------------------------
Ich kann den Fehler beim besten Willen nicht finden. Vielleicht kann mir jemand weiterhelfen?!
Mit Dank und Grüßen aus Berlin,
Sebastian
Tag
Das Problem scheinen die Anführungszeichen gewesen zu sein, sowohl bei den Größenangaben als auch bei der Ausgabe (falsche Verschachtelung).
Jetzt geht's (zumindet mit IE5 und NC4):
-------------------------------------------------
// Zahl der Bilder hier konfigurieren
var picCount = 5;
// Standard-alt-Text hier konfigurieren
var defaultText = 'INCONTRI - Ristorante Italiano';
randPic = new Array();
picWidth = new Array();
picHeight = new Array();
picTxt = new Array();
altTxt = new Array();
// Array mit Bildnamen hier konfigurieren
randPic[0] = 'restaurant2.jpg';
picWidth[0] = 240;
picHeight[0] = 160;
picTxt[0] = 'Ristorante';
randPic[1] = 'nudelgabel.gif';
picWidth[1] = 120;
picHeight[1] = 180;
picTxt[1] = 'Maccaroni & Gabel';
randPic[2] = 'bar1.jpg';
picWidth[2] = 180;
picHeight[2] = 120;
picTxt[2] = 'Bar';
randPic[3] = 'osteria.jpg';
picWidth[3] = 180;
picHeight[3] = 120;
picTxt[3] = 'C. Bloch, In un osteria romana, 1860';
randPic[4] = 'gabel.jpg';
picWidth[4] = 180;
picHeight[4] = 120;
picTxt[4] = 'Olive & Gabel';
// ---------- Ab hier nichts mehr verändern! ----------
// Standard-alt-Text
for (i = 0; i < picCount; i++)
{
if ((picTxt[i] == '') || (picTxt[i] == 'undefined')) altTxt[i] = defaultText;
else altTxt[i] = picTxt[i];
}
// Zufallsfunktion
var num = Math.round((picCount - 1) * Math.random());
// Ausgabe des HTML-Quelltextes
function ranPic()
{
var str = "<a href="index.htm" onMouseOver="window.status='';return true;" onMouseOut="window.status='';return true;"><img src="./img/" + randPic[num] + "" width="" + picWidth[num] + "" height="" + picHeight[num] + "" border="0" alt="" + altTxt[num] + ""></a>";
document.write(str);
alert(str); // test
}
ranPic();
-------------------------
Ciao,
Harry
Moin!
Das Problem scheinen die Anführungszeichen gewesen zu sein, sowohl bei den Größenangaben als auch bei der Ausgabe (falsche Verschachtelung).
Sicher, dass es daran lag? Ich hab mir den String nicht genauer angesehen, aber da ist mindestens noch ein weiterer Fehler drin.
Das klammern wir mal aus und stellen es weiter unten automatisch fest:
/*
// Zahl der Bilder hier konfigurieren
var picCount = 5;
*/
// Standard-alt-Text hier konfigurieren
var defaultText = 'INCONTRI - Ristorante Italiano';
»»
randPic = new Array();
picWidth = new Array();
picHeight = new Array();
picTxt = new Array();
altTxt = new Array();
»»
// Array mit Bildnamen hier konfigurieren
randPic[0] = 'restaurant2.jpg';
picWidth[0] = 240;
picHeight[0] = 160;
picTxt[0] = 'Ristorante';
»»
randPic[1] = 'nudelgabel.gif';
picWidth[1] = 120;
picHeight[1] = 180;
picTxt[1] = 'Maccaroni & Gabel';
»»
randPic[2] = 'bar1.jpg';
picWidth[2] = 180;
picHeight[2] = 120;
picTxt[2] = 'Bar';
»»
randPic[3] = 'osteria.jpg';
picWidth[3] = 180;
picHeight[3] = 120;
picTxt[3] = 'C. Bloch, In un osteria romana, 1860';
»»
randPic[4] = 'gabel.jpg';
picWidth[4] = 180;
picHeight[4] = 120;
picTxt[4] = 'Olive & Gabel';
// Zahl der Bilder feststellen
var picCount = randPic.length;
// ---------- Ab hier nichts mehr verändern! ----------
Warum denn nicht?
// Standard-alt-Text
for (i = 0; i < picCount; i++)
{
if ((picTxt[i] == '') || (picTxt[i] == 'undefined')) altTxt[i] = defaultText;
^ ^
Das war im Original schon richtig - ohne Anfuehrungszeichen. Eine Variable auf Nichtexistenz testen entweder:
if (x == undefined)
oder
if (typeof(x) == "undefined")
else altTxt[i] = picTxt[i];
}
// Zufallsfunktion
var num = Math.round((picCount - 1) * Math.random());
Das geht so nicht. Damit kannst Du auch gut mal num == -1 bekommen, und da num dann als Index in die Arrays verwendet wird, wuerde das ein gelegentliches undefined ganz gut erklaeren. Besser:
var num = Math.floor(picCount * Math.random() - 1);
// Ausgabe des HTML-Quelltextes
function ranPic()
{
var str = "<a href="index.htm" onMouseOver="window.status='';return true;" onMouseOut="window.status='';return true;"><img src="./img/" + randPic[num] + "" width="" + picWidth[num] + "" height="" + picHeight[num] + "" border="0" alt="" + altTxt[num] + ""></a>";
document.write(str);
alert(str); // test
}
ranPic();
So long
// Zufallsfunktion
var num = Math.round((picCount - 1) * Math.random());
Das geht so nicht. Damit kannst Du auch gut mal num == -1 bekommen, und da num dann als Index in die Arrays verwendet wird, wuerde das ein gelegentliches undefined ganz gut erklaeren. Besser:
var num = Math.floor(picCount * Math.random() - 1);
Vorsicht! Da machst eher DU den Fehler!
Math.random() liefert eine Zahl zwischen 0 und 1 (<1) zurück.
picCount * Math.random() - 1 kann also gut mal -1 ergeben,
während (picCount - 1) * Math.random() nur negative Werte ergibt, falls es keine Bilder gibt (picCount = 0). Der Fehler in der ursprünglichen Formel liegt eher beim Math.round, daß wohl bei eingen Browsern nur abrundet, bei anderen manchmal auch aufrundet (4.5 ergibt dann 5).
Um also bei picCount = 5 nur Zahlen von 0 bis 4 zu erzeugen muß keine der beiden vorigen sondern folgende Formel verwendet werden:
var num = Math.floor(picCount * Math.random());
Der Faktor picCount=5 wird dann mit einer Zahl zwischen 0 und 1 (<1) multipliziert. Das ergibt etwas zwischen 0 und 4.99999... , also abgerundet nur die Zahlen 0 bis 4. Die Zahl 5 ergibt sich nie, da Math.random() immer kleiner 1 ist!
Teste mal folgende Schleife mit einer der Zufallsformeln:
for (i=0; i<50; i++)
{
num = Math.floor(5*Math.random());
document.write(num);
document.write("<br>");
}
Das ergibt dann eine Seite mit 50 Zufallszahlen. Damit kann man dann ganz gut Testen, in welchen Zahlenbereich die Ergebnisse fallen.
var num = Math.floor(picCount * Math.random() - 1);
Vorsicht! Da machst eher DU den Fehler!
Math.random() liefert eine Zahl zwischen 0 und 1 (<1) zurück.
picCount * Math.random() - 1 kann also gut mal -1 ergeben,
Stimmt. Da hab ich wohl solange drueber nachgedacht, dass ich am Ende auch nicht mehr wusste, was ich eigentlich wollte. *g* Der langen Ueberlegung hat es uebrigens bedurft (bedurft? Ist das wirklich das Praeteritum von beduerfen?), weil mir naemlich gar nicht so klar war, dass Math.random() nicht vielleicht doch mal eine glatte 1 zurueckliefert. Das wird naemlich keineswegs so in der JS-Doku gesagt. Dort steht nur "zwischen 0 und 1", aber inklusive oder exklusive 0 und 1? Das steht dort nicht. Am Ende habe ich mich aber auch dafuer entschieden, dass die 1 wohl nie vorkommen wird, weil das schlisslich in jeder anderen Programmiersprache auch so ist, und da ja JS auch nur in C++ geschrieben ist... Dann hab ich wohl dummerweise die -1 wieder mit reingeruehrt.
während (picCount - 1) * Math.random() nur negative Werte ergibt, falls es keine Bilder gibt (picCount = 0).
Na gut, ich denke, den Fall koennen wir ausklammern.
Der Fehler in der ursprünglichen Formel liegt eher beim Math.round, daß wohl bei eingen Browsern nur abrundet, bei anderen manchmal auch aufrundet (4.5 ergibt dann 5).
Wirklich? Welche sind denn das? Meines Wissens rundet Math.round() und Math.floor rundet *ab*.
Der Faktor picCount=5 wird dann mit einer Zahl zwischen 0 und 1 (<1) multipliziert. Das ergibt etwas zwischen 0 und 4.99999... , also abgerundet nur die Zahlen 0 bis 4. Die Zahl 5 ergibt sich nie, da Math.random() immer kleiner 1 ist!
Hoffentlich, aber woher *weisst* Du das? Ginge es um was wichtiges, wuerde ich mich nicht drauf verlassen.
Hallo Calocybe,
Die Zahl 5 ergibt sich nie, da Math.random() immer kleiner 1 ist!
Hoffentlich, aber woher *weisst* Du das? Ginge es um was wichtiges,
wuerde ich mich nicht drauf verlassen.
Also testen und ggf. nochmal würfeln?
Viele Grüße
Michael
Hi!
Also testen und ggf. nochmal würfeln?
Gut, ab wieviel Versuchen siehst Du als gesichert an, dass die 1 nie auftritt? Oder so: 0.5 liegt eindeutig im Wertebereich, aber wenn ich jetzt draufloswuerfel um die 0.5 zu finden, wie hoch ist die Wahrscheinlichkeit, dass sie innerhalb der ersten Milliarde Versuche auftritt? Imho eher gering, wenn man bedenkt, wieviele verschiedene Zahlen sich in einer 8-Byte-Floatingpoint-Variable (ich nehme mal an, die rechnen mit doubles) darstellen lassen. Was meinst Du?
So long
Hallo Calocybe,
Also testen und ggf. nochmal würfeln?
Gut, ab wieviel Versuchen siehst Du als gesichert an,
dass die 1 nie auftritt?
Keine konstante Zahl, sondern eine Schleife, die erst bei einem
Würfelergebnis echt kleiner 1 verlassen wird (also fast immer nach
dem ersten Wurf).
Viele Grüße
Michael
Hi!
Keine konstante Zahl, sondern eine Schleife, die erst bei einem
Würfelergebnis echt kleiner 1 verlassen wird (also fast immer nach
dem ersten Wurf).
Ach so, ja. Auch waere moeglich, vielleicht sowas wie
Math.floor(Math.random() * (picCount - 0.001))
zu verwenden, was die Wahrscheinlichkeitsverteilung zwar minimal verschiebt, aber sicherstellt, dass eine auftretende 1 entschaerft wird.
So long
Hallo, Calocybe,
Danke für die Hilfe ...
// Zufallsfunktion
var num = Math.round((picCount - 1) * Math.random());
Das geht so nicht. Damit kannst Du auch gut mal num == -1 bekommen, und da num dann als Index in die Arrays verwendet wird, wuerde das ein gelegentliches undefined ganz gut erklaeren. Besser:
var num = Math.floor(picCount * Math.random() - 1);
Das stimmt meines Erachtens nicht; Math.random() liegt im Original-Skript immer zwischen 0 und 1, picCount ist mindestens 2, somit ist der Wert immer positiv und wird im vorliegenden Fall durch Math.round auf Werte zwischen 0 und 4 gerundet. Das ergibt auch die Ausgabe per alert(num).
In der vorgeschlagenen Alternative kann num hingegen zu -1 werden, wenn picCount * Math.random() kleiner als 1 wird, was zu undefined als Ausgabe führt.
Bitte korrigiere mich, falls ich mich irre!
Gut sind auf jeden Fall die Hinweise auf die wohl falsche Korrektur der Abfrage nach undefined und auf die automatische Feststellung der Bildanzahl durch var picCount = randPic.length. Dadurch wird die Gefahr, sich bei einer Neukonfiguration der Bilder zu vertun, geringer.
Grüße, Sebastian
Ciao, Harry (aus Big Brother? ;-) ),
Danke für die Hilfe ...
Ich hab den String jetzt mal nach Deinem Vorschlag geändert und noch ein paar andere Änderungen in das Skript eingefügt, kann das Funktionieren aber nur im IE 5.5 und NS 4.7 überprüfen. Vielleicht funktioniert's ja jetzt in allen Browsern!
Grüße, Sebastian
Die Bilder dienen übrigens hauptsächlich zum Testen und sollen durch weitere ergänzt bzw. ersetzt werden.