Kann nicht auf "style"-Attribut zugreifen
Daniela
- javascript
Hallo!
Ich hab schon einige Javascript-Erfahrung und bin dabei, meiner Schwester Nachhilfe zu geben. Sie muss für ihren Informatiktest "Dinge auf dem Bildschirm bewegen können", also mit Layers und so. Da ich das selber noch nicht gemacht habe, wollte ich vorher noch üben, und habe erst einmal in Anlehnung an das hier beschriebene Script: http://de.selfhtml.org/dhtml/modelle/dom.htm#css_eigenschaften (CSS-Eigenschaften dynamisch ändern) einen Textbereich bewegt. Hat auch prächtig funktioniert. Ich wollte dann mit denselben Methoden ein Übungsprogramm vorbereiten, welches es auf einem Bild schneien lässt. Diesmal steht das "div" eben nicht von Anfang an in der Datei, sondern wird dynamisch erzeugt:
var image = document.createElement("div");
image.setAttributeNode(document.createAttribute("style"));
image.appendChild(document.createElement("img"));
image.firstChild.src = "flocke.png";
document.getElementsByTagName("body")[0].appendChild(image);
Die zweite Zeile ist erst später dazu gekommen, vorher habe ich es ohne probiert. Wenn ich jetzt darauf zugreifen möchte ("num" ist nur eine Indexvariable):
this.obj = document.getElementsByTagName("div")[num];
this.obj.style.position = "absolute";
bekomme ich die Fehlermeldung: "this.obj has no properties". Aufgrund dieser Meldung habe ich dann die oben erwähnte zweite Zeile eingefügt, noch immer das selbe Spiel.
Bei meiner ersten Übung habe ich es aber fast genauso gemacht:
text = document.getElementById("text");
text.style.position = "absolute";
Da gab es aber keine Probleme. Das dynamische Erzeugen der Elemente hat funktioniert. Ich habe mit dem "DOM Inspector" vom Firefox nachgesehen und die sind dort wo sie hingehören. Was könnte es da haben?
Vielen Dank schon mal im Voraus.
Daniela
Hallo,
var image = document.createElement("div");
image.setAttributeNode(document.createAttribute("style"));
Ein style-Attribute brauchst du nicht erzeugen, das Objekt image.style existiert auch so und du kannst darüber die Eigenschaften setzen.
image.appendChild(document.createElement("img"));
image.firstChild.src = "flocke.png";
document.getElementsByTagName("body")[0].appendChild(image);
Du kannst auf das body-Element auch einfach über document.body zugreifen.
this.obj = document.getElementsByTagName("div")[num];
this.obj.style.position = "absolute";bekomme ich die Fehlermeldung: "this.obj has no properties".
Das Problem ist nicht der Zugriff auf das style-Attribut.
Der Fehler liegt schon in der ersten Zeile, document.getElementsByTagName("div")[num] gibt wahrscheinlich null zurück. Schau dir erst einmal an, was document.getElementsByTagName("div") zurückgibt. Ein NodeList-Objekt, also eine Liste mit Knoten - wieviele Knoten sind darin? Die length-Eigenschaft gibt entsprechende Auskunft.
var knotenliste = document.getElementsByTagName("div");
alert(knotenliste.length + " div-Elemente im Dokument gefunden");
Höchstwahrscheinlich gibt es in der Knotenliste, die document.getElementsByTagName("div") zurückgibt, kein Element mit der Nummer num. Vergleiche num mit der Anzahl der Knoten in der Knotenliste. Beachte, dass das erste Element in der Liste mit dem Index 0 angesprochen wird, das zweite mit dem Index 1 usw.
Mathias
Hallo,
var image = document.createElement("div");
image.setAttributeNode(document.createAttribute("style"));Ein style-Attribute brauchst du nicht erzeugen, das Objekt image.style existiert auch so und du kannst darüber die Eigenschaften setzen.
image.appendChild(document.createElement("img"));
image.firstChild.src = "flocke.png";
document.getElementsByTagName("body")[0].appendChild(image);Du kannst auf das body-Element auch einfach über document.body zugreifen.
this.obj = document.getElementsByTagName("div")[num];
this.obj.style.position = "absolute";bekomme ich die Fehlermeldung: "this.obj has no properties".
Das Problem ist nicht der Zugriff auf das style-Attribut.
Der Fehler liegt schon in der ersten Zeile, document.getElementsByTagName("div")[num] gibt wahrscheinlich null zurück. Schau dir erst einmal an, was document.getElementsByTagName("div") zurückgibt. Ein NodeList-Objekt, also eine Liste mit Knoten - wieviele Knoten sind darin? Die length-Eigenschaft gibt entsprechende Auskunft.
Tatsächlich -- beim zweiten Durchlauf kommt "undefined" zurück, beim ersten ist der Knotentyp 1, also Elementknoten. Die Anzahl der Knoten ist bei beiden Durchläufen 1. Und dabei dachte ich mir, dass schon beim ersten Durchlauf abgebrochen wird. Es ist auch nur ein "div"-Element da nach dem Abbruch, sollten aber zwei sein. Also funktioniert es beim ersten Mal noch.
Hallo,
var image = document.createElement("div");
image.setAttributeNode(document.createAttribute("style"));Ein style-Attribute brauchst du nicht erzeugen, das Objekt image.style existiert auch so und du kannst darüber die Eigenschaften setzen.
Ja, image.style existiert tatsächlich, aber das nützt mir nicht viel. image ist ja nur die Vorlage, von der alle "div"-Elemente in das Dokument geschrieben werden. Ich kann die Attribute nicht für image.style festlegen, da sie ja für jede Schnneflocke anders sein sollen.
Diese Zeilen werden nur einmal am Anfang ausgeführt:
var image = document.createElement("div");
//image.setAttributeNode(document.createAttribute("style"));
image.appendChild(document.createElement("img"));
image.firstChild.src = "flocke.png";
Und das wird in einer Schleife für jede Flocke einmal gemacht:
document.body.appendChild(image);
this.obj wird dann das neu erzeugte "div" zugewiesen, und über dieses will ich dann die Attribute setzen. Aber hier existiert kein style-Attribut mehr, und das ist das Problem.
image.appendChild(document.createElement("img"));
image.firstChild.src = "flocke.png";
document.getElementsByTagName("body")[0].appendChild(image);Du kannst auf das body-Element auch einfach über document.body zugreifen.
Ups. Danke für den Hinweis, muss ich wohl überlesen haben.
var image = document.createElement("div");
image.setAttributeNode(document.createAttribute("style"));
image.appendChild(document.createElement("img"));
image.firstChild.src = "flocke.png";
document.getElementsByTagName("body")[0].appendChild(image);
Du kannst übrigens auch ein Image auf dem bewegen, das DIV ist unnötig.
Die zweite Zeile ist erst später dazu gekommen, vorher habe ich es ohne probiert. Wenn ich jetzt darauf zugreifen möchte ("num" ist nur eine Indexvariable):
this.obj = document.getElementsByTagName("div")[num];
this.obj.style.position = "absolute";
Ich weiß zwar nicht, was this hier ist, aber du hast ja schon die Refrenz auf das Objekt:
var image = document.createElement("img");
Wenn du jetzt mehrere "Flocken" erzeugen willst, kannst das in deinem Objekt (ich vermute du hast eins, wegen dem this) benutzen.
Struppi.
var image = document.createElement("div");
image.setAttributeNode(document.createAttribute("style"));
image.appendChild(document.createElement("img"));
image.firstChild.src = "flocke.png";
document.getElementsByTagName("body")[0].appendChild(image);Du kannst übrigens auch ein Image auf dem bewegen, das DIV ist unnötig.
Ja schon, aber mit "div" ist es mir lieber. Ich spreche die Dinger nämlich über die Indexnummer an, und "div"-Elemente hab ich nur die im Dokument, die ich für die Flocken brauche. Bilder hab ich aber noch ein paar, und ich wollte die Flocken nicht mit document.getElementsByTagName("img")[num+2] ansprechen, denn immer wenn ich in einem Programm solche "Magic Numbers" einbaue, verwirren sie mich später. Das kenn ich schon aus Assembler, aber in jeder anderen Programmiersprache ist es dasselbe, weil mir nie ordentliche Variablennamen einfallen.
Die zweite Zeile ist erst später dazu gekommen, vorher habe ich es ohne probiert. Wenn ich jetzt darauf zugreifen möchte ("num" ist nur eine Indexvariable):
this.obj = document.getElementsByTagName("div")[num];
this.obj.style.position = "absolute";Ich weiß zwar nicht, was this hier ist, aber du hast ja schon die Refrenz auf das Objekt:
var image = document.createElement("img");
Wenn du jetzt mehrere "Flocken" erzeugen willst, kannst das in deinem Objekt (ich vermute du hast eins, wegen dem this) benutzen.
Ja, ich hab ein Objekt "Flocke", und für jede Flocke mach ich eine Instanz. this.obj bezeichnet das Bild, das mit dieser Flockeninstanz verknüpft ist. Die Flockenobjekte hab ich in ein Array getan, und die Indexnummer in diesem Array ist dieselbe wie die vom zugehörigen "div".
Ich werde es mal ohne "div" probieren, wenn's nur so geht, muss ich halt mehr Zeit in die Kommentare investieren *g*
Du kannst übrigens auch ein Image auf dem bewegen, das DIV ist unnötig.
Ja schon, aber mit "div" ist es mir lieber. Ich spreche die Dinger nämlich über die Indexnummer an, und "div"-Elemente hab ich nur die im Dokument, die ich für die Flocken brauche. Bilder hab ich aber noch ein paar, und ich wollte die Flocken nicht mit document.getElementsByTagName("img")[num+2] ansprechen, ...
Das ist Unsinn.
Wie ich dir schon schrieb, kannst du die Elemente in deinen Objekte merken, du brauchst sie nicht jedesmal mit getElementBy... neu zu holen.
Wenn du jetzt mehrere "Flocken" erzeugen willst, kannst das in deinem Objekt (ich vermute du hast eins, wegen dem this) benutzen.
Ja, ich hab ein Objekt "Flocke", und für jede Flocke mach ich eine Instanz. this.obj bezeichnet das Bild, das mit dieser Flockeninstanz verknüpft ist. Die Flockenobjekte hab ich in ein Array getan, und die Indexnummer in diesem Array ist dieselbe wie die vom zugehörigen "div".
Wenn du Objekte verwendest, verstehe ich nicht warum du nicht die Bilder in die Objekte einbaust.
function Flocke()
{
this.obj = document.createElement("img");
this.obj.src = "flocke.png";
this.obj.style.position = 'absolute';
}
Flocke.prototype.top( y)
{
this.obj.style.top = y + 'px';
}
Flocke.prototype.left( x)
{
this.obj.style.left = x + 'px';
}
und dann z.b. so erzeugst:
var flocke = new Flocke();
documentbody.appendChild( flocke.obj );
und jetzt kanst du hopsen:
function hops () {
i += 0.04;
if (i == 360) i = 0;
flocke.top( Math.round ((Math.sin(i) + 1) * 256));
window.setTimeout ("hops()", 50);
}
Struppi.
Hat sich gerade erledigt. Ich musste einfach die Anweisungen zum Vorbereiten des "div"-Elements in die Schleife reinschreiben, weil nur am Anfang einmal ausführen reicht nicht. Und jetzt schneit es mitten im Mai. Aber mein Rechner kommt ganz schön ins Schwitzen, dabei lasse ich doch nur einen kleinen Ausschnitt beschneien (512*256) und hab nur 256 Flocken. Die eigentlich geplante zusätzliche Bewegung entlang der x-Achse funktioniert zwar, macht das Ganze aber so langsam, dass man nimmer viel sieht, daher musste ich das rausnehmen.
Das ist IMHO DER Nachteil vom sonst so tollen Javascript; Mit Assembler macht man so was Vollbild und es braucht fast keine Rechnerleistung.
Danke nochmal für eure Hilfe.
Daniela
....Die eigentlich geplante zusätzliche Bewegung entlang der x-Achse funktioniert zwar, macht das Ganze aber so langsam, dass man nimmer viel sieht, daher musste ich das rausnehmen.
Das ist IMHO DER Nachteil vom sonst so tollen Javascript; Mit Assembler macht man so was Vollbild und es braucht fast keine Rechnerleistung.
Das Problem ist, dass du dein Skript mit Absicht langsam machst.
alle 10ms sagst du dem Browser, dass er das Dokument neu nach den Elementen durchsuchen soll, obwohl du die Elemente schon beim erzeugen hast, also nicht mehr mit getElementBy... suchen musst.
Aber natürlich, kannst du eine Animation innerhalb eines Browserfenster nicht mit einer, die du mit, DirectX programmierst vergleichen.
Struppi.
....Die eigentlich geplante zusätzliche Bewegung entlang der x-Achse funktioniert zwar, macht das Ganze aber so langsam, dass man nimmer viel sieht, daher musste ich das rausnehmen.
Das ist IMHO DER Nachteil vom sonst so tollen Javascript; Mit Assembler macht man so was Vollbild und es braucht fast keine Rechnerleistung.Das Problem ist, dass du dein Skript mit Absicht langsam machst.
alle 10ms sagst du dem Browser, dass er das Dokument neu nach den Elementen durchsuchen soll, obwohl du die Elemente schon beim erzeugen hast, also nicht mehr mit getElementBy... suchen musst.
Ich hab in der Schleife gar kein getElementBy... drinnen, dort greife ich nur über this.obj... zu. Das getElementBy... hab ich in der Initialschleife, die am Anfang alle Objekte erzeugt. Die läuft nur zu Beginn einmal durch, dann nicht mehr.
Aber natürlich, kannst du eine Animation innerhalb eines Browserfenster nicht mit einer, die du mit, DirectX programmierst vergleichen.
Was zur Hölle ist DirectX??? Ich programmiere in Assembler mit den POSIX-Standard Kernel-Interfaces, ohne irgendwelche Libraries.
Das Problem ist, dass du dein Skript mit Absicht langsam machst.
alle 10ms sagst du dem Browser, dass er das Dokument neu nach den Elementen durchsuchen soll, obwohl du die Elemente schon beim erzeugen hast, also nicht mehr mit getElementBy... suchen musst.
Ich hab in der Schleife gar kein getElementBy... drinnen, dort greife ich nur über this.obj... zu. Das getElementBy... hab ich in der Initialschleife, die am Anfang alle Objekte erzeugt. Die läuft nur zu Beginn einmal durch, dann nicht mehr.
Naja, gut auch das ist doppelt gemoppelt, du erzeugst dein Objekt und dann holst du das Objekt.
Ich hab's mal schnell umgesetzt:
http://jstruebig.de/web/javascript/spielereien/schneeflocken/schneeflocken.html
geht bei mir auch mit 250 Flocken.
Aber natürlich, kannst du eine Animation innerhalb eines Browserfenster nicht mit einer, die du mit, DirectX programmierst vergleichen.
Was zur Hölle ist DirectX??? Ich programmiere in Assembler mit den POSIX-Standard Kernel-Interfaces, ohne irgendwelche Libraries.
Ich dachte du vergleichst ein Programm, dass unter einer Grafischen Oberfläche, direkt auf den Bildschirmspeicher zugreifen kann, mit dem Skript, dass im Browser läuft. Gibt es sowas auch unter Linux? POSIX ist ja nun was komplett anderes, oder?
Struppi.
Das Problem ist, dass du dein Skript mit Absicht langsam machst.
alle 10ms sagst du dem Browser, dass er das Dokument neu nach den Elementen durchsuchen soll, obwohl du die Elemente schon beim erzeugen hast, also nicht mehr mit getElementBy... suchen musst.
Ich hab in der Schleife gar kein getElementBy... drinnen, dort greife ich nur über this.obj... zu. Das getElementBy... hab ich in der Initialschleife, die am Anfang alle Objekte erzeugt. Die läuft nur zu Beginn einmal durch, dann nicht mehr.
Naja, gut auch das ist doppelt gemoppelt, du erzeugst dein Objekt und dann holst du das Objekt.
Ich hab's mal schnell umgesetzt:
http://jstruebig.de/web/javascript/spielereien/schneeflocken/schneeflocken.html
geht bei mir auch mit 250 Flocken.
Wow, das hat ja viermal mehr Variablen als meins und ist viel schwieriger. Ich bin ja auch noch ein relativer Neuling (das "prototype" hab ich beispielsweise noch nie gesehen), aber wenn ich das meiner Schwester zu erklären versuche, haut sie ab *g*. Aber auch das zieht sich bei mir ganz schön, ich glaub mein PC ist einfach zu langsam. Bei meiner Version (unten angehängt) hab ich Schneeflocken verschiedener Größen und die kleinen bewegen sich langsamer. Ausserdem bleiben die Schneeflocken nicht unten liegen, sondern bekommen dann ein neues Objekt zugewiesen und fangen wieder von oben an. Die geplante x-Achsen-Bewegung ist auskommentiert, aber es sieht auch ohne sehr lieb aus. (Leider kann ich hier die Schneeflockengrafik und Hintergrundbilder nicht mitschicken).
Aber natürlich, kannst du eine Animation innerhalb eines Browserfenster nicht mit einer, die du mit, DirectX programmierst vergleichen.
Was zur Hölle ist DirectX??? Ich programmiere in Assembler mit den POSIX-Standard Kernel-Interfaces, ohne irgendwelche Libraries.
Ich dachte du vergleichst ein Programm, dass unter einer Grafischen Oberfläche, direkt auf den Bildschirmspeicher zugreifen kann, mit dem Skript, dass im Browser läuft. Gibt es sowas auch unter Linux? POSIX ist ja nun was komplett anderes, oder?
Ja, wenn man unter Linux was Grafisches programmieren möchte, kann man das natürlich auch unter einer grafischen Oberfläche tun, dazu muss man halt entsprechende Libraries einbinden (manche von denen sind gar nicht aufgebläht, das läuft dann auch schon sehr schnell, aber es kommt drauf an welches man nimmt, man hat viel Auswahl). Oder aber man schenkt sich die Libraries ganz, nimmt nur den Kernel und greift direkt auf die Grafikkarte zu. Saukompliziert, und so viel Erfahrung hab ich damit auch noch nicht, aber schneller als das geht's nun wirklich nicht.
So, und hier mein Schneegestöber (nicht wundern, ich hab 'nen kleinen Zweierpotenzentick):
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Testseite</title>
<script type="text/javascript">
<!--
//<![CDATA[
var flocke = new Array(256);
function Flocke (num) {
this.obj = document.getElementsByTagName("div")[num];
this.obj.style.position = "absolute";
with (this.obj.firstChild)
width = height = Math.round (Math.random() * 16);
this.x = num * 2 + Math.round (Math.random() * 4);
this.y = 0;
this.z = this.obj.firstChild.width;
this.xi = 0;
}
function init () {
for (i = 0; i < 256; i++) {
var image = document.createElement("div");
image.appendChild(document.createElement("img"));
image.firstChild.src = "flocke.png";
document.body.appendChild(image);
flocke[i] = new Flocke(i);
flocke[i].y = Math.round (Math.random() * 256);
flocke[i].obj.style.top = flocke[i].y + "px";
}
mv();
}
function mv () {
for (i=0; i < 256; i++) {
with (flocke[i]) {
// xi += 0.01;
// if (xi > 360) xi = 0;
// obj.style.left = Math.round (x + (Math.sin(xi) * z)) + "px";
obj.style.left = x + "px";
obj.style.top = (y += ((z >> 2) + 1)) + "px";
}
if (flocke[i].y > 256) {
delete flocke[i];
flocke[i] = new Flocke(i);
}
}
window.setTimeout ("mv()", 200);
}
//]]>
//-->
</script>
</head>
<body bgcolor="#000040" onload="init()">
</body>
</html>
http://jstruebig.de/web/javascript/spielereien/schneeflocken/schneeflocken.html
geht bei mir auch mit 250 Flocken.
Wow, das hat ja viermal mehr Variablen als meins und ist viel schwieriger.
Das einzige was schwieriger ist und mehr Variabeln erfordert, ist das ich die Fenstergröße mit berechnet habe.
Ich hab das mir der Fenstergrößenberechnung und mit dem prototyp rausgenommen woei, wenn du schon Objekte deklarierst gehört das natürlich dazu.
.... Bei meiner Version (unten angehängt) hab ich Schneeflocken verschiedener Größen und die kleinen bewegen sich langsamer.
Das liegt an der Sinusberechung, das kostet.
Ausserdem bleiben die Schneeflocken nicht unten liegen, sondern bekommen dann ein neues Objekt zugewiesen und fangen wieder von oben an.
Auch das ist nicht optimal. Ständig delete und new aufrufen verzögert unnötig.
...Oder aber man schenkt sich die Libraries ganz, nimmt nur den Kernel und greift direkt auf die Grafikkarte zu. Saukompliziert, und so viel Erfahrung hab ich damit auch noch nicht, aber schneller als das geht's nun wirklich nicht.
Naja, das ist natürlich etwas extrem anderes. Das wäre ungefähr so, wenn du sagst, der Trecker ist ganz schön langsam, mein Rennauto ist viel schneller, nur wirst du damit kaum einen Pflug ziehen können.
So, und hier mein Schneegestöber (nicht wundern, ich hab 'nen kleinen Zweierpotenzentick):
Ich hab's gemerkt ;-) (kommt wohl vom Assembler programmieren)
und auch in meiner Version eingebaut.
Struppi.
http://jstruebig.de/web/javascript/spielereien/schneeflocken/schneeflocken.html
geht bei mir auch mit 250 Flocken.
Wow, das hat ja viermal mehr Variablen als meins und ist viel schwieriger.
Das einzige was schwieriger ist und mehr Variabeln erfordert, ist das ich die Fenstergröße mit berechnet habe.
Ich hatte ursprünglich auch die Fenstergröße einbezogen, weil ich wollte ja Vollbild machen. hab mich dann aber wegen der Geschwindigkeit für einen kleinen fixen Ausschnitt entschieden.
Ich hab das mir der Fenstergrößenberechnung und mit dem prototyp rausgenommen woei, wenn du schon Objekte deklarierst gehört das natürlich dazu.
Immer langsam mit den jungen Pferden, ich hab gestern das erste Mal ein Objekt deklariert.
.... Bei meiner Version (unten angehängt) hab ich Schneeflocken verschiedener Größen und die kleinen bewegen sich langsamer.
Das liegt an der Sinusberechung, das kostet.
Die hab ich ja dann auskommentiert. Aber wie kriegt man die Dinger sonst dazu, sich elegant auf der x-Achse zu bewegen? Und ist die Zufallszahlenerzeugung nicht langsamer als Sinus? Ausserdem brauch ich den Sinus ja nur ungefähr, man muss die unendliche Reihe ja nicht so weit fortführen... Ich könnte ja mal versuchen, die Sinusfunktion zu emulieren... Wenn ich mir mal was in den Kopf setze...
Ausserdem bleiben die Schneeflocken nicht unten liegen, sondern bekommen dann ein neues Objekt zugewiesen und fangen wieder von oben an.
Auch das ist nicht optimal. Ständig delete und new aufrufen verzögert unnötig.
Ist ja nicht ständig, nur wenn eine unten ankommt, was ja pro Sekunde nicht so oft geschieht. Da ist die Sinusberechnung sicher langsamer.
...Oder aber man schenkt sich die Libraries ganz, nimmt nur den Kernel und greift direkt auf die Grafikkarte zu. Saukompliziert, und so viel Erfahrung hab ich damit auch noch nicht, aber schneller als das geht's nun wirklich nicht.
Naja, das ist natürlich etwas extrem anderes. Das wäre ungefähr so, wenn du sagst, der Trecker ist ganz schön langsam, mein Rennauto ist viel schneller, nur wirst du damit kaum einen Pflug ziehen können.
Machen kann man mit Assembler alles, daher ist das eher kein guter Vergleich. Ich würde eher sagen, das Rennauto ist viel schneller, dafür hast du aber auch mehr Arbeit mit der Wartung.
So, und hier mein Schneegestöber (nicht wundern, ich hab 'nen kleinen Zweierpotenzentick):
Ich hab's gemerkt ;-) (kommt wohl vom Assembler programmieren)
und auch in meiner Version eingebaut.
Ursprünglich hatte ich statt den Vergleichsoperatoren das bitweise UND verwendet, und statt allen Multiplikationen Bit-Shift-Operatoren (die wären sehr viel schneller gewesen, gehen hier aber leider nur für Integer... arrrrgh... da hab ich mir einige Haare ausgerissen, bis ich da draufgekommen bin). Das kommt auch alles von Assembler. Man kann ja überhaupt am Programmierstil gut erkennen, mit welchen anderen Programmiersprachen jemand viel zu tun hat.
Ich hatte ursprünglich auch die Fenstergröße einbezogen, weil ich wollte ja Vollbild machen. hab mich dann aber wegen der Geschwindigkeit für einen kleinen fixen Ausschnitt entschieden.
Naja, eben, daher war meine erste Version auch etwas umfangreicher als deine.
Das liegt an der Sinusberechung, das kostet.
Die hab ich ja dann auskommentiert. Aber wie kriegt man die Dinger sonst dazu, sich elegant auf der x-Achse zu bewegen? Und ist die Zufallszahlenerzeugung nicht langsamer als Sinus? Ausserdem brauch ich den Sinus ja nur ungefähr, man muss die unendliche Reihe ja nicht so weit fortführen... Ich könnte ja mal versuchen, die Sinusfunktion zu emulieren... Wenn ich mir mal was in den Kopf setze...
So eine Berechnung (sin, cos oder auch z.b. Wurzeln ziehen) ist immer aufwändig und zeitintensiv, sogar in Assembler. Die Zufallzahl dürfte um einige Faktoren schneller erzeugt sein.
Ausserdem bleiben die Schneeflocken nicht unten liegen, sondern bekommen dann ein neues Objekt zugewiesen und fangen wieder von oben an.
Auch das ist nicht optimal. Ständig delete und new aufrufen verzögert unnötig.
Ist ja nicht ständig, nur wenn eine unten ankommt, was ja pro Sekunde nicht so oft geschieht. Da ist die Sinusberechnung sicher langsamer.
Das stimmt. Aber du gibst den Speicher frei um ihn direkt danach wieder neu zu belegen. Dass ist überflüssig und auch nicht im Sinne von Objekt orientierter Programmierung.
...Oder aber man schenkt sich die Libraries ganz, nimmt nur den Kernel und greift direkt auf die Grafikkarte zu. Saukompliziert, und so viel Erfahrung hab ich damit auch noch nicht, aber schneller als das geht's nun wirklich nicht.
Naja, das ist natürlich etwas extrem anderes. Das wäre ungefähr so, wenn du sagst, der Trecker ist ganz schön langsam, mein Rennauto ist viel schneller, nur wirst du damit kaum einen Pflug ziehen können.
Machen kann man mit Assembler alles, daher ist das eher kein guter Vergleich. Ich würde eher sagen, das Rennauto ist viel schneller, dafür hast du aber auch mehr Arbeit mit der Wartung.
Meine Rede, du hast aber nur die Geschwindigkeit verglichen.
Ursprünglich hatte ich statt den Vergleichsoperatoren das bitweise UND verwendet, und statt allen Multiplikationen Bit-Shift-Operatoren (die wären sehr viel schneller gewesen, gehen hier aber leider nur für Integer... arrrrgh... da hab ich mir einige Haare ausgerissen, bis ich da draufgekommen bin). Das kommt auch alles von Assembler. Man kann ja überhaupt am Programmierstil gut erkennen, mit welchen anderen Programmiersprachen jemand viel zu tun hat.
Man kann in Assembler sicher auch keine Fließkommazahlen Bitweise bearbeiten, da der Aufbau dieser Zahlen unterschiedlich sein kann.
Statt Math.round kannst du in JS auch parseInt verwenden und dann sollte es gehen.
Struppi.
Das liegt an der Sinusberechung, das kostet.
Die hab ich ja dann auskommentiert. Aber wie kriegt man die Dinger sonst dazu, sich elegant auf der x-Achse zu bewegen? Und ist die Zufallszahlenerzeugung nicht langsamer als Sinus? Ausserdem brauch ich den Sinus ja nur ungefähr, man muss die unendliche Reihe ja nicht so weit fortführen... Ich könnte ja mal versuchen, die Sinusfunktion zu emulieren... Wenn ich mir mal was in den Kopf setze...
So eine Berechnung (sin, cos oder auch z.b. Wurzeln ziehen) ist immer aufwändig und zeitintensiv, sogar in Assembler. Die Zufallzahl dürfte um einige Faktoren schneller erzeugt sein.
Beim Sinus kann man wirklich net viel einsparen, hab ich gerade feststellen müssen, weil da kommt man um die FPU net herum (glaub ich zumindest, so gut bin ich in Mathe auch net). Aber wie ich mich kenne, werde ich jetzt sicher wieder tagelang an einer schnellen Näherungs-Implementation basteln, nur um mir zu beweisen dass es net geht. In Javascript hab ich gerade eine gemacht, aber die ist leider nur ungefähr so langsam wie die bereitgestellte Funktion. Ganzzahl-Wurzelziehen von großen Zahlen kann dagegen sehr schnell gehen, sofern man es nur näherungsweise braucht (wenn die Zahl nur gerade Bits hat, ist es sogar ganz exakt).
Ausserdem bleiben die Schneeflocken nicht unten liegen, sondern bekommen dann ein neues Objekt zugewiesen und fangen wieder von oben an.
Auch das ist nicht optimal. Ständig delete und new aufrufen verzögert unnötig.
Ist ja nicht ständig, nur wenn eine unten ankommt, was ja pro Sekunde nicht so oft geschieht. Da ist die Sinusberechnung sicher langsamer.
Das stimmt. Aber du gibst den Speicher frei um ihn direkt danach wieder neu zu belegen. Dass ist überflüssig und auch nicht im Sinne von Objekt orientierter Programmierung.
Das sehe ich ein. Aber kann ich denn den Konstruktor des Objekts nochmal aufrufen ohne es vorher zu löschen, damit es neue Anfangswerte erhält?? Oder muss ich das Belegen mit Anfangswerten in eine andere Funktion auslagern und diese vom Konstruktor (oder wie man das Ding hier nennt) aus aufrufen?
Man kann in Assembler sicher auch keine Fließkommazahlen Bitweise bearbeiten, da der Aufbau dieser Zahlen unterschiedlich sein kann.
Doch, kann man. Sehr gut sogar, dafür gibt's eigene OPcodes, und jeder, der direkt mit der FPU arbeitet, kommt um die wohl net herum. Damit verschiebt man doch eigentlich nur das Komma um eine Binärstelle, mehr ist es nicht.
Statt Math.round kannst du in JS auch parseInt verwenden und dann sollte es gehen.
Das versteh ich nicht, wie soll denn parseInt da helfen??
Hallo Daniela,
Beim Sinus kann man wirklich net viel einsparen, hab ich gerade feststellen müssen, weil da kommt man um die FPU net herum (glaub ich zumindest, so gut bin ich in Mathe auch net).
tatsächlich? Ich hab vor Jahren mal für eine Grafikanwendung, bei der es auch nicht auf absolute Genauigkeit ankam, eine schnelle Sinusfunktion in Assembler geschrieben. Der wesentliche Knackpunkt war, dass ich eine Tabelle mit Stützpunkten (wegen der Symmetrie reicht der Bereich 0..90°) verwendet habe und Werte dazwischen einfach linear interpoliert habe. Damit reduzierte sich eine "Sinus"-Berechnung auf einen Arrayzugriff, eine Verhältnisbildung und eine Addition.
Ganzzahl-Wurzelziehen von großen Zahlen kann dagegen sehr schnell gehen, sofern man es nur näherungsweise braucht (wenn die Zahl nur gerade Bits hat, ist es sogar ganz exakt).
Wie meinst du das? Dass nur gerade Zweierpotenzen auftreten? Etwa sowas wie
84 = 2^6 + 2^4 + 2^2 ?
Dann verrate mir doch bitte mal, wie du die Wurzel aus 84 "ganz exakt" berechnen willst. Nee, es interessiert mich ehrlich, auch wenn das jetzt vielleicht spöttisch klingen mag.
Doch, kann man. Sehr gut sogar, dafür gibt's eigene OPcodes, und jeder, der direkt mit der FPU arbeitet, kommt um die wohl net herum. Damit verschiebt man doch eigentlich nur das Komma um eine Binärstelle, mehr ist es nicht.
Und das geht in Assembler sogar ohne FPU schnell und effizient. :-)
Schönen Abend noch,
Martin
Hallo Daniela,
Beim Sinus kann man wirklich net viel einsparen, hab ich gerade feststellen müssen, weil da kommt man um die FPU net herum (glaub ich zumindest, so gut bin ich in Mathe auch net).
tatsächlich? Ich hab vor Jahren mal für eine Grafikanwendung, bei der es auch nicht auf absolute Genauigkeit ankam, eine schnelle Sinusfunktion in Assembler geschrieben. Der wesentliche Knackpunkt war, dass ich eine Tabelle mit Stützpunkten (wegen der Symmetrie reicht der Bereich 0..90°) verwendet habe und Werte dazwischen einfach linear interpoliert habe. Damit reduzierte sich eine "Sinus"-Berechnung auf einen Arrayzugriff, eine Verhältnisbildung und eine Addition.
Na gut, ich hab halt was gegen solche Tabellen in meinen Implementationen. Vielleicht bin ich einfach nur zu faul um sie anzulegen. Aber jetzt wo du es erwähnst, wenn man viele Sinusberechnungen machen muss, kann man die Tabellen ja zu Beginn generieren.
Ganzzahl-Wurzelziehen von großen Zahlen kann dagegen sehr schnell gehen, sofern man es nur näherungsweise braucht (wenn die Zahl nur gerade Bits hat, ist es sogar ganz exakt).
Wie meinst du das? Dass nur gerade Zweierpotenzen auftreten? Etwa sowas wie
84 = 2^6 + 2^4 + 2^2 ?
Dann verrate mir doch bitte mal, wie du die Wurzel aus 84 "ganz exakt" berechnen willst. Nee, es interessiert mich ehrlich, auch wenn das jetzt vielleicht spöttisch klingen mag.
Okay, mit den geraden Bits hab ich mich etwas vertan. Ich meinte, die Exponenten in den Zweierpotenzen müssen wieder Zweierpotenzen sein, weil dann "geht die Wurzel auf". Oder so. Wie gesagt, ich bin kein Mathegenie. Mir war nur einmal langweilig, und da hab ich versucht, im Hexadezimaleditor ganzzahlige Wurzeln zu ziehen, das war alles. Aber die Abweichungen sind teilweise noch sehr groß, da ist viel Raum für Verbesserung.
Doch, kann man. Sehr gut sogar, dafür gibt's eigene OPcodes, und jeder, der direkt mit der FPU arbeitet, kommt um die wohl net herum. Damit verschiebt man doch eigentlich nur das Komma um eine Binärstelle, mehr ist es nicht.
Und das geht in Assembler sogar ohne FPU schnell und effizient. :-)
Weiß ich. Ich hab bis jetzt noch überhaupt kein Programm geschrieben, wo ich kein Bit-Shifting verwendet hab. Und ich hab so eine Aversion gegen Divisionen in Schleifen, ich versuche so weit es geht nur durch Zweierpotenzen zu dividieren.
Hallo,
Wie meinst du das? Dass nur gerade Zweierpotenzen auftreten? Etwa sowas wie
84 = 2^6 + 2^4 + 2^2 ?
Dann verrate mir doch bitte mal, wie du die Wurzel aus 84 "ganz exakt" berechnen willst.
Okay, mit den geraden Bits hab ich mich etwas vertan. Ich meinte, die Exponenten in den Zweierpotenzen müssen wieder Zweierpotenzen sein, weil dann "geht die Wurzel auf".
Ah, verstehe.
Nee, dann ist die Aussage mit den "geraden" Zweierpotenzen schon richtig, denn wenn ich einen Ausdruck der Form 2^(2n) habe, ist die Wurzel daraus selbstverständlich 2^n. Aber sobald du eine Summe von mehreren Zweierpotenzen hast (also eine Ganzzahl mit *mehreren* gesetzten Bits), versagt das Verfahren.
Ich hab bis jetzt noch überhaupt kein Programm geschrieben, wo ich kein Bit-Shifting verwendet hab. Und ich hab so eine Aversion gegen Divisionen in Schleifen, ich versuche so weit es geht nur durch Zweierpotenzen zu dividieren.
*g* Great minds think alike. :-)
Schönen Tag noch,
Martin
Hallo,
Wie meinst du das? Dass nur gerade Zweierpotenzen auftreten? Etwa sowas wie
84 = 2^6 + 2^4 + 2^2 ?
Dann verrate mir doch bitte mal, wie du die Wurzel aus 84 "ganz exakt" berechnen willst.Okay, mit den geraden Bits hab ich mich etwas vertan. Ich meinte, die Exponenten in den Zweierpotenzen müssen wieder Zweierpotenzen sein, weil dann "geht die Wurzel auf".
Ah, verstehe.
Nee, dann ist die Aussage mit den "geraden" Zweierpotenzen schon richtig, denn wenn ich einen Ausdruck der Form 2^(2n) habe, ist die Wurzel daraus selbstverständlich 2^n. Aber sobald du eine Summe von mehreren Zweierpotenzen hast (also eine Ganzzahl mit *mehreren* gesetzten Bits), versagt das Verfahren.
Hmmm... da hast du recht. Aber alle Wurzeln die "aufgehen" kann man ganz exakt auch mit einem ungenauen Verfahren berechnen. Da gab es doch so eine Regel, welche Wurzeln "aufgehen" und welche nicht, ich dachte das wäre die mit den geraden Bits, oder so... Bin eben kein Mathegenie, aber wenn ich noch eins werde, seid ihr zwei daran schuld *g*. Die ganze Wurzel- und Sinusdiskusion hat mein Interesse (wieder) geweckt.
Das stimmt. Aber du gibst den Speicher frei um ihn direkt danach wieder neu zu belegen. Dass ist überflüssig und auch nicht im Sinne von Objekt orientierter Programmierung.
Das sehe ich ein. Aber kann ich denn den Konstruktor des Objekts nochmal aufrufen ohne es vorher zu löschen, damit es neue Anfangswerte erhält?? Oder muss ich das Belegen mit Anfangswerten in eine andere Funktion auslagern und diese vom Konstruktor (oder wie man das Ding hier nennt) aus aufrufen?
Dazu, habe ich z.b. in meinem Beispiel eine Initialisierungsfunktion (start())
Man kann in Assembler sicher auch keine Fließkommazahlen Bitweise bearbeiten, da der Aufbau dieser Zahlen unterschiedlich sein kann.
Doch, kann man. Sehr gut sogar, dafür gibt's eigene OPcodes, und jeder, der direkt mit der FPU arbeitet, kommt um die wohl net herum. Damit verschiebt man doch eigentlich nur das Komma um eine Binärstelle, mehr ist es nicht.
Na gut, ich hab nur rudimentäre Assembler Kenntnisse. Ich hatte das auch mit einer Diskussion verwechselt, wo es darum ging ob man in Perl mit Fließkommazahlen Bitweise arbeiten kann. Wenn ich die Diskussion richtig verfolgt habe, geht es dort nicht.
Statt Math.round kannst du in JS auch parseInt verwenden und dann sollte es gehen.
Das versteh ich nicht, wie soll denn parseInt da helfen??
Auch mein Fehler, ich bin davon ausgegangen, das man Fließkommazahlen nicht Shiften kann, kann man aber.
Struppi.
Hab gerade herausgefunden, dass es sich hier wohl um ein Browserproblem handeln muss. Dieses Anzeigebeispiel: http://de.selfhtml.org/dhtml/modelle/anzeige/denker.htm
funktioniert bei mir nämlich nicht, da kommt fast der selbe Fehler wie bei meinem Programm: document.BildAnzeige has no properties.
Das Beispiel, auf das ich im ersten Post verlinkt habe, läuft aber bei mir, und ein einfacheres Testprogamm von mir, das im Prinzip dieselben Methoden verwendet, macht auch keine Probleme. Ich schreib es mal hier rein:
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Testseite</title>
<script type="text/javascript">
<!--
//<![CDATA[
var text;
var i = 0;
function init () {
text = document.getElementById("text");
text.style.position = "absolute";
text.style.top = 256 + "px";
text.style.left = 256 + "px";
hops();
}
function hops () {
i += 0.04;
if (i == 360) i = 0;
text.style.top = Math.round ((Math.sin(i) + 1) * 256) + "px";
window.setTimeout ("hops()", 10);
}
//]]>
//-->
</script>
</head>
<body onload="init()">
<div id="text"><h1> Hoppa hoppa Reiter </h1></div>
</body>
</html>
Hab gerade herausgefunden, dass es sich hier wohl um ein Browserproblem handeln muss. Dieses Anzeigebeispiel: http://de.selfhtml.org/dhtml/modelle/anzeige/denker.htm
funktioniert bei mir nämlich nicht, da kommt fast der selbe Fehler wie bei meinem Programm: document.BildAnzeige has no properties.
Hast du dir mal angeschaut, für welche Browser dieses Beispiel gedacht ist.
Struppi.