(SVG): setCurrentTime im onload?
Margin-Auto
- xml-derivat
Hi,
in einer SVG-Animation möchte ich eine historische Entwicklung darstellen. Der Einfachheit halber nehme ich dafür den zeitlichen "Maßstab"
1 Jahr (Realität)=1 Sekunde (Animation)
Damit man jetzt nicht ne halbe Stunde warten muss, bis man was sieht, setze ich im onload-Ereignis mittels
SVGDocument = evt.target.ownerDocument;
SVGRoot = SVGDocument.documentElement;
SVGRoot.setCurrentTime(1900);
die Zeit auf 1900. Leider funktioniert das in diesem Ereignis nicht. Wenn ich es sonst irgendwo in dem Dokument versuche (beim Click auf einen Link bspw.) geht es. Gibt es keine Möglichkeit, im onload-Ereignis die Zeit zu setzen?
Die Möglichkeit, einfach nur "zweistellige" Jahreszahlen zu nehmen ist mir natürlich auch gekommen, erscheint mir aber nicht so elegant, zumal es vielleicht auch mal irgendwann ins 19. Jahrhundert gehen könnte.
Any ideas?
TIA
Margin-Auto
Hallo,
Damit man jetzt nicht ne halbe Stunde warten muss, bis man was sieht, setze ich im onload-Ereignis mittels
SVGDocument = evt.target.ownerDocument;
SVGRoot = SVGDocument.documentElement;SVGRoot.setCurrentTime(1900);
die Zeit auf 1900. Leider funktioniert das in diesem Ereignis nicht. Wenn ich es sonst irgendwo in dem Dokument versuche (beim Click auf einen Link bspw.) geht es. Gibt es keine Möglichkeit, im onload-Ereignis die Zeit zu setzen?
Hast Du auch das Wurzelelementobjekt zuvor abgefragt?
Dieser Test funktioniert problemlos:
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
onload="Init(evt,1900)">
<defs>
<script type="text/javascript">
<![CDATA[
function Init(evt,t)
{
var svgroot=evt.target.ownerDocument.documentElement;
svgroot.setCurrentTime(t);
alert(svgroot.getCurrentTime());
}
]]>
</script>
</defs>
</svg>
Hier noch ein Beispiel zu get/setCurrentTime().
MfG, Thomas
Hi,
Dieser Test funktioniert problemlos:
[...]
Danke für den Hinweis. An onload scheint es *nicht* zu liegen: wenn ich die Zeit wie in deinem Beispiel unmittelbar danach abfrage, stimmt es.
Ich definiere mit
setInterval('neueZeit()',1000);
jedoch noch eine weitere Funktion, die jede Sekunde eine "Uhr" aktualisiert.
function neueZeit(){
var t=parseInt(svgroot.getCurrentTime());
elem=svgdoc.getElementById("uhr");
elem.getFirstChild().setNodeValue(t);
}
Wenn ich darin jetzt die aktuelle Zeit abfrage, bekomme ich immer nur Werte wie 1,2,3... (natürlich jeweils Komma irgendwas)
Kollidiert das evt. mit dem setInterval?
TIA
Margin-Auto
Hallo,
Wenn ich darin jetzt die aktuelle Zeit abfrage, bekomme ich immer nur Werte wie 1,2,3... (natürlich jeweils Komma irgendwas)
Kollidiert das evt. mit dem setInterval?
get/setCurrentTime() beziehen sich auf die bisherige Ladezeit des aktuellen SVG-Dokuments (also bezogen auf onload --> 0s).
Mit setCurrentTime() kann man diese Zeit veraendern (siehe das genannte Beispiel) und somit das Timing von SMIL-Animationen beeinflussen. Inwiefern setCurrentTime() mit setInterval() interagiert, habe ich noch nicht untersucht.
MfG, Thomas
Hi,
Mit setCurrentTime() kann man diese Zeit veraendern (siehe das genannte Beispiel) und somit das Timing von SMIL-Animationen beeinflussen. Inwiefern setCurrentTime() mit setInterval() interagiert, habe ich noch nicht untersucht.
Offenbar scheint es doch nicht am setInterval zu liegen. Ich habe dein Beispiel mal folgendermaßen abgeändert:
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
onload="Init(evt,1900)">
<defs>
<script type="text/javascript">
<![CDATA[
var svgroot;
function Init(evt,t)
{
svgroot=evt.target.ownerDocument.documentElement;
svgroot.setCurrentTime(t);
alert(svgroot.getCurrentTime());
}
]]>
</script>
</defs>
<circle cx='100' cy='100' r='10' onclick="alert(svgroot.getCurrentTime());"/>
</svg>
und bei dem Klick auf den Kreis kommt auch wieder nur die "normale" Zeit ohne 1900. svgroot müsste bei dieser Deklaration doch überall verfügbar sein, oder nicht?
Margin-Auto
Hallo,
Offenbar scheint es doch nicht am setInterval zu liegen. Ich habe dein Beispiel mal folgendermaßen abgeändert:
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
onload="Init(evt,1900)"><defs>
<script type="text/javascript">
<![CDATA[
var svgroot;
function Init(evt,t)
{
svgroot=evt.target.ownerDocument.documentElement;
svgroot.setCurrentTime(t);
alert(svgroot.getCurrentTime());
}]]>
</script></defs>
<circle cx='100' cy='100' r='10' onclick="alert(svgroot.getCurrentTime());"/>
</svg>
>
> und bei dem Klick auf den Kreis kommt auch wieder nur die "normale" Zeit ohne 1900. svgroot müsste bei dieser Deklaration doch überall verfügbar sein, oder nicht?
Das Poblem ist, dass getCurrentTime immer bei 0 anfängt.
Du musst die Zeit also immer wieder neu setzen und dabei die vergangene Zeit dazuaddieren:
\----------------------------------------------
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="Init(evt,1900)">
<defs>
<script type="text/javascript">
<![CDATA[
var svgroot;
var z;
function Init(evt,t) {
svgroot=evt.target.ownerDocument.documentElement;
svgroot.setCurrentTime(t);
alert(svgroot.getCurrentTime());
z = svgroot.getCurrentTime();
}
function sZeit() {
zeit = z;
svgroot.setCurrentTime(zeit);
alert(svgroot.getCurrentTime());
z = svgroot.getCurrentTime();
}
]]>
</script>
</defs>
<circle id="c1" cx='100' cy='100' r='10' onclick="sZeit();"/>
</svg>
\---------------------------------------
alert() muss du dann aus sZeit() entfernen.
Grüße
Thomas (der andere)
Hi,
Das Poblem ist, dass getCurrentTime immer bei 0 anfängt.
?? Bei jedem Aufruf wird die Zeit auf 0 gesetzt, oder wie? Sorry, hab ich nicht ganz kapiert.
Wieso funktioniert dann der Aufruf unmittelbar nach dem Setzen aus dem Beispiel des anderen Thomas?
Margin-Auto
Hallo,
Das Poblem ist, dass getCurrentTime immer bei 0 anfängt.
?? Bei jedem Aufruf wird die Zeit auf 0 gesetzt, oder wie? Sorry, hab ich nicht ganz kapiert.
------------------------
getCurrentTime
Returns the current time in seconds relative to the start time for the current SVG document fragment.
setCurrentTime
Adjusts the clock for this SVG document fragment, establishing a new current time.
------------------------
Also beim Laden des Dokuments wird die Zeit gesetzt und gleich wieder ausgegeben.
Beim Klick wird die Zeit abgefragt und da gilt: relativ zur Startzeit!
Also ab dem Ladezeitpunkt. Beim Klick wird also immer die Zeit angezeigt, die seit dem Laden des Dokuments vergangen ist.
Außerdem, ich glaube ich habe dir vorhin einen Blödsinn gepostet:
So sollte es eigentlich reichen:
Grüße
Thomas
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="Init(evt,1900)">
<defs>
<script type="text/javascript">
<![CDATA[
var svgroot;
var z;
function Init(evt,t) {
svgroot=evt.target.ownerDocument.documentElement;
svgroot.setCurrentTime(t);
alert(svgroot.getCurrentTime());
z = t
}
function sZeit() {
t2 = svgroot.getCurrentTime();
zeit = t2+z;
alert(zeit)
}
]]>
</script>
</defs>
<circle id="c1" cx='100' cy='100' r='10' onclick="sZeit();"/>
</svg>
Hi,
Also beim Laden des Dokuments wird die Zeit gesetzt und gleich wieder ausgegeben.
Beim Klick wird die Zeit abgefragt und da gilt: relativ zur Startzeit!
Also ab dem Ladezeitpunkt. Beim Klick wird also immer die Zeit angezeigt, die seit dem Laden des Dokuments vergangen ist.
Ja aber durch setCurrentTime setze ich ja die Uhr neu, so dass auch getCurrentTime die neue Uhrzeit verwendet. Und das funktioniert ja eingeschränkt auch.
Im onload:
/*Zeit liegt bei ein paar Millisekunden oder so*/
svgroot.setCurrentTime(1900);
/*Zeit liegt jetzt bei 1900 Sekunden + ein paar Zerquetschte; wird auch korrekt angezeigt*/
alert(svgroot.getCurrentTime());
Warum funktioniert getCurrentTime dann offenbar anders, wenn ich es später in einer anderen Funktion aufrufe?
Margin-Auto
Hallo,
Warum funktioniert getCurrentTime dann offenbar anders, wenn ich es später in einer anderen Funktion aufrufe?
Verstehe ich nicht. Die Funktionalitaet von setCurrentTime() via onload hatten wir geklaert und die Moeglichkeit des beliebigen Setzens und Abfragens der Laufzeit zeigt doch mein genanntes Beispiel. Stelle mal Deinen Code online und erlaeutere das Ziel genauer.
MfG, Thomas
Hallo Thomas,
Warum funktioniert getCurrentTime dann offenbar anders, wenn ich es später in einer anderen Funktion aufrufe?
Verstehe ich nicht.
Ich glaube das Problem liegt wo anderes, siehe mein Posting (wann wird onload ausgeführt).
Bei deinem Beispiel kann man das auch beobachten: der Zeit-Counter und der Rest wird schon angezeit, aber erst nach etwa 2 Sekunden fägt die Zeit zum Laufen an.
Grüße
Thomas
Hallo,
Ja aber durch setCurrentTime setze ich ja die Uhr neu, so dass auch getCurrentTime die neue Uhrzeit verwendet. Und das funktioniert ja eingeschränkt auch.
Warum funktioniert getCurrentTime dann offenbar anders, wenn ich es später in einer anderen Funktion aufrufe?
Berechtigte Frage!
Nach paar Tests: Es gibt offensichtlich ein Unterschied in der Interpretation des "onload"-Events zwischen dem SVG-Viewer vom Adobe (ich habe hier 3.03 Build 94) und andere SVG-Implementierungen.
Rufst du die Datei mit dem SVG-Viwer auf, passiert das was ich schon beschreiben habe, rufst du die Datei im Opera (habe jetzt mit 9p1 getestet (im 8.5 funktioniert der Script nicht (ebenso nicht im Firefox))) auf, verhält sich die Zeitabfrage, so wie du es erwartest.
Der SVG-Veiwer führt den Script erst aus, wenn die Seite geladen wurde und betrachtet offensichtlich die Funktion nach dem die Seite geladen wurde auch als beendet und bei einer neuen Abfrage der Zeit, gibt es eben nur die Zeit aus, die Seit dem vergangen sind.
Füge mal:
<circle id="c0" cx="150" cy="150" r="10" fill="red" onload="alert(svgroot.getCurrentTime())" onclick="sZeit()" />
in die Datei ein und teste dann. Da kann man sehen, dass _während_ des Ladens der Seite 'svgroot' noch nicht zur Verfügung steht.
Grüße
Thomas
Hallo,
Nach paar Tests: Es gibt offensichtlich ein Unterschied in der Interpretation des "onload"-Events zwischen dem SVG-Viewer vom Adobe (ich habe hier 3.03 Build 94) und andere SVG-Implementierungen.
Da gibt es tatsaechlich eine "gefuehlte" Verzoegerung von ca. 1s. Dagegen reagiert der ASV 6 Preview 1 bei mir selbst auf einer mehr als > 10x langsameren Maschine ohne Verzoegerung.
MfG, Thomas
Hallo Thomas
Nach paar Tests: Es gibt offensichtlich ein Unterschied in der Interpretation des "onload"-Events zwischen dem SVG-Viewer vom Adobe (ich habe hier 3.03 Build 94) und andere SVG-Implementierungen.
Da gibt es tatsaechlich eine "gefuehlte" Verzoegerung von ca. 1s. Dagegen reagiert der ASV 6 Preview 1 bei mir selbst auf einer mehr als > 10x langsameren Maschine ohne Verzoegerung.
Es ist nicht nur gefüht:
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="Init(evt,1900)">
<defs>
<script type="text/javascript">
<![CDATA[
var svgroot;
function Init(evt,t) {
svgroot=evt.target.ownerDocument.documentElement;
svgroot.setCurrentTime(t);
z = svgroot.getCurrentTime();
alert(svgroot.getCurrentTime());
}
]]>
</script>
</defs>
<circle id="c1" cx='100' cy='100' r='10' onload="alert('hallo')" onclick="alert(svgroot.getCurrentTime())" />
</svg>
Sowohl bei dem SVG-Viewer als bei Opera wird zuerst hallo ausgegeben und erst später das Script ausgeführt.
Ich bin mir nicht sicher, aber mir scheint, dass der SVG-Viewer hier zwar in der Funktion die Zeit setzt, betrachtet die Seite aber erst nach Ausführung des Scripts als geladen und so misst er die Zeit auch erst ab diesem Zeitpunkt.
Grüße
Thomas
Hallo,
Sowohl bei dem SVG-Viewer als bei Opera wird zuerst hallo ausgegeben und erst später das Script ausgeführt.
Ich bin mir nicht sicher, aber mir scheint, dass der SVG-Viewer hier zwar in der Funktion die Zeit setzt, betrachtet die Seite aber erst nach Ausführung des Scripts als geladen und so misst er die Zeit auch erst ab diesem Zeitpunkt.
Waehrend mir ASV 3.03 und Opera 9TP1 bzw. TP2 einen Wert von ~1900.0001 ausgeben, zeigt der ASV 6 nach dem alert() exakt 1900.
MfG, Thomas
Hallo Thomas,
Ich bin mir nicht sicher, aber mir scheint, dass der SVG-Viewer hier zwar in der Funktion die Zeit setzt, betrachtet die Seite aber erst nach Ausführung des Scripts als geladen und so misst er die Zeit auch erst ab diesem Zeitpunkt.
Waehrend mir ASV 3.03 und Opera 9TP1 bzw. TP2 einen Wert von ~1900.0001 ausgeben, zeigt der ASV 6 nach dem alert() exakt 1900.
Jetzt habe ich mir den 6-Prev. auch installiert.
Es ändert sich dadurch nichts: klick man jetzt auf dem Kreis (aus meinem letzen Code) so zeigt er noch immer nicht 1900.xxxx.
D.h. auch der 6-er betrachtet die Seite erst wirklich geladen, wenn der Code ausgeführt wurde.
Tausche in deinem verlinkten Script die Zeile so aus:
<text x="250" y="120" onload="ZeitSetzen(5415)">
^^^^^^
Und schau was beim Laden der Datei passiert.
Grüße
Thomas
Hallo,
Tausche in deinem verlinkten Script die Zeile so aus:
<text x="250" y="120" onload="ZeitSetzen(5415)">
^^^^^^
Und schau was beim Laden der Datei passiert.
OK, ist auch mit ASV 6 nachvollziehbar. Vielleicht koennte das ein Workaround sein:
onload="setTimeout('ZeitSetzen(5415)',1)"
MfG, Thomas
Hallo Thomas (und "Margin-Auto" [toller Name]),
Tausche in deinem verlinkten Script die Zeile so aus:
<text x="250" y="120" onload="ZeitSetzen(5415)">
^^^^^^
Und schau was beim Laden der Datei passiert.OK, ist auch mit ASV 6 nachvollziehbar. Vielleicht koennte das ein Workaround sein:
onload="setTimeout('ZeitSetzen(5415)',1)"
Ja, das funktioniert (jetzt weiss ich nur nicht mehr, wozu eigentlich Init(evt) dienen sollte):
<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" onload="Init(evt);setTimeout('ZeitSetzen(1900)',1)">
<defs>
<script type="text/javascript">
<![CDATA[
var svgroot;
function Init(evt) {
svgroot=evt.target.ownerDocument.documentElement;
}
function ZeitSetzen(t) {
svgroot.setCurrentTime(t);
}
]]>
</script>
</defs>
<circle id="c1" cx='100' cy='100' r='10' onclick="alert(svgroot.getCurrentTime())" />
</svg>
Grüße
Thomas
Hallo,
Ja, das funktioniert (jetzt weiss ich nur nicht mehr, wozu eigentlich Init(evt) dienen sollte):
Es wird die globale Variable svgroot mit dem Wurzelelementobjekt belegt. Mein Beispiel ist nicht so zeitkritisch (svgroot wird ohne Funktion initialisiert), da erst ein Benutzerklick erfolgen muss.
MfG, Thomas
Hi,
Ja, das funktioniert (jetzt weiss ich nur nicht mehr, wozu eigentlich Init(evt) dienen sollte):
[...]
OMG, dass mein Problem solche fundamentalphilosophischen Ursachen hat, hätte ich nicht gedacht.
Nochmal, nur um sicherzugehen, dass ich es richtig verstanden habe: Der Viewer interpretiert das Ende von onload als Nullpunkt für seine Zeitrechnung und macht sämtliche vorher gemachten Änderungen wieder rückgängig (?). Also gut, wenn er meint.
Ich habe jetzt das mit dem setTimeout bei mit eingebaut und es funktioniert. Bestaunen kann man es unter http://www.kleinheitz.de/vag.svg. Ja, ich weiss: Animationen gibt es noch keine zu sehen und auch sonst sind noch ein paar Ungereimtheiten drin.
Das Intervall für die Aktualisierung der Uhr habe ich jetzt mal auf 500ms gestellt, da er sonst manchmal einen Schritt überspringt.
Auf jeden Fall Danke an euch beide für die Hilfe.
Margin-Auto
Hallo,
OMG, dass mein Problem solche fundamentalphilosophischen Ursachen hat, hätte ich nicht gedacht.
Na ja, der Weg zur Erkenntnis ist manchmal eben steinig ;-)
Und dieses Verhalten des Viewers zu verstehen war eben nicht leicht.
Nochmal, nur um sicherzugehen, dass ich es richtig verstanden habe: Der Viewer interpretiert das Ende von onload als Nullpunkt für seine Zeitrechnung und macht sämtliche vorher gemachten Änderungen wieder rückgängig (?).
Ja.
Wenn du das Beispiel (zu get- und setCurrentTime) von Thomas mit der Änderung die ich vorschlug ausführst, kannst du dieses Verhalten gut nachvollziehen.
Ich habe jetzt das mit dem setTimeout bei mit eingebaut und es funktioniert. Bestaunen kann man es unter http://www.kleinheitz.de/vag.svg. Ja, ich weiss: Animationen gibt es noch keine zu sehen und auch sonst sind noch ein paar Ungereimtheiten drin.
Wenn es keine zwingenden Gründe für SVG 1.1 gibt, solltest du SVG 1.0 benützen (sonst meckert der Veiwer z.B. über die DOCTYPE):
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd" [
<!ATTLIST svg xmlns:xlink CDATA #FIXED "http://www.w3.org/1999/xlink">
]>
Grüße
Thomas
Hallo,
Wenn es keine zwingenden Gründe für SVG 1.1 gibt, solltest du SVG 1.0 benützen (sonst meckert der Veiwer z.B. über die DOCTYPE):
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd" [
<!ATTLIST svg xmlns:xlink CDATA #FIXED "http://www.w3.org/1999/xlink">
]>
Das ist auch meine Empfehlung, wobei die einst in der DTD vergessene Angabe des xlink:href-Attributes mittlerweile ergaenzt wurde.
Allerdings macht genau dieses eingeschobene DTD-Fragment [...] neuerdings Probleme mit Opera 9TP2 (aber nicht mit TP1 und 8.x): "XML parsing failed: syntax error (Line: 0, Character: 0)". Das Problem ist als Bug gemeldet.
Erfreulicherweise rendert TP2 aber wieder besser als TP1 und 8.5, z. B. bei drei aneinander gefuegten Polygonen, die einen 3D-Balken ergeben sollen (8.5 zeigt oben graue Kanten, TP1 rechts eine weiße):
Das TP2-Ergebnis entspricht wiederum dem von IE+ASV und Firefox 1.5 (unter XP getestet).
@Margin-Auto:
Bitte aendere in Deinem Code die Zeile
elem.getFirstChild().setNodeValue(t);
in die standardkonforme Schreibweise
elem.firstChild.nodeValue=t;
um kuenftige Probleme mit Firefox oder Opera zu vermeiden, siehe SVG Authoring Guidelines : "Don't use Adobe's getter and setter extensions".
MfG, Thomas
Hi,
Wenn es keine zwingenden Gründe für SVG 1.1 gibt, solltest du SVG 1.0 benützen
elem.firstChild.nodeValue=t;
Danke für die Hinweise, ist beides gefixt (nur noch nicht online).
Margin-Auto