2 5 17 52 0 0 0

Zeitunterschiede

animateMotion und JavaScript

Ein Vergleichstest zwischem dem SVG eigenen animateMotion, CSS3 animation und einer JavaScript-Steuerung.

0 0% 1sec 10% 2sec 20% 3sec 30% 4sec 40% 5sec 50% 6sec 60% 7sec 70% 8sec 80% 9sec 90% 10sec 100%

refresh

Wenn die Frage gestattet ist, was das soll? Dann möchte ich in Abhängigkeit der Browser mit der Frage antworten:
„Was sind denn nun 10 Sekunden?“
Diese Testreihe habe ich mir vorgenommen auf Grund eines anderen Web-Beispiels. 10 Sekunden lang soll sich ein Objekt bewegen, dann eine zufällig lange Pause einnehmen, um anschließend wieder zu beginnen. Das dann später, wenn ich das erste Problem verstanden habe, also die Lösung.
Das Problem besteht in der Interpretation, was 10 Sekunden sein sollen. Firefox flitzt regelrecht davon. Opera und Chrome sind da gemächlicher, aber überholen irgendwann auch die javascript-gesteuerte rote Kugel. Dazu gesellt sich nun auch das Transparenzverhalten. Nach 2sec soll die gelbe Kugel volle Deckkraft erhalten und ab der 8.sec wieder verblassen. Ja und? Nach einer Sekunde hat diese bereits die volle Deckkraft erreicht. Also was soll das!
Das Transparenzverhalten der orangefarbenen und roten Kugel wird über Javascript gesteuert, woraus ersichtlich ist:
Dat passt nich!

1. Auszug: SVG-Element3 Kreis id="yellowbull", id="oranbull" animateMotion Definition

61
62
63
64
65
66
67
68
69
70
 <circle id="yellowbull" cx="0" cy="0" r="6" fill="yellow">
  <animateMotion dur="10s" repeatCount="indefinite" >
   <mpath xlink:href="#ypath"/>
  </animateMotion>
 </circle> 
 <circle id="oranbull" cx="0" cy="0" r="6" fill="orange">
  <animateMotion dur="10s" repeatCount="indefinite" >
   <mpath xlink:href="#opath"/>
  </animateMotion>
 </circle>

2. Auszug: CSS für das Element id="yellowbull"

19
20
21
22
23
24
25
#yellowbull{ animation: myOpac 10s infinite }
@keyframes myOpac {
    0% { opacity: 0; }
   20% { opacity: 1; }
   80% { opacity: 1; }
  100% { opacity: 0; }
}

3. Auszug: JavaScript für die rote Kugel (externe Datei)

0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<script type="application/ecmascript">  
var 
_svgNS 'http://www.w3.org/2000/svg';
var 
_xlinkNS 'http://www.w3.org/1999/xlink';
var 
obj_redbull document.getElementById ('redbull') ;
var 
obj_yelbull document.getElementById ('yellowbull') ;
var 
obj_oranbull document.getElementById ('oranbull') ;
var 
x=10xm=0aktxpos=0y=40strecke=480zeitschritt=20 ;
obj_redbull.style.top "px" ;
var 
i=0opac=0opacz=;
obj_redbull.setAttributeNS(null,'opacity'0) ;

function 
AMPFAD(){
 
obj_redbull.setAttribute('cx',aktxpos) ;
 if ( 
xm <= 100 opaczxm  ;     
 
// 100 entsprechen 2sec = auf der Skala 20%, Deckkraft anheben
 
if ( xm 100 && xm 400 opacz 
 
// 2.Sek. bis 8.Sek (20% bis 80%) volle Deckkraft
    
if ( xm >= 400 opacz=100-Math.abs(400-xm) ;
    
// ab 8.Sek (80%) Deckkraft mindern
    
opac opacz/100 ;
    
obj_redbull.setAttributeNS(null,'opacity'opac) ;
    
obj_oranbull.setAttributeNS(null,'opacity'opac) ;
 
xm++ ;
 
aktxpos x+xm ;
 
// Zeitgleich der Versuch die Position der gelben Kugel zu ermitteln ergibt cx=0
 
var anibullx obj_yelbull.getAttribute('cx') ;
 
// die Ausgabe ist auskommentiert
 // document.getElementById ('gelb-x').innerHTML = anibullx ; 
 
setTimeout(AMPFADzeitschritt) ;
 if ( 
xm == 500xm ;
}
AMPFAD() ;
</script>

Animation mit einer Unterbrechung

0 1sec 2sec 3sec 4sec 5sec 6sec 7sec 8sec 9sec 10sec

Ziel ist, einen Bewegungsfluss am Ende seiner Strecke zufällig zu unterbrechen. Die Dauer der Unterbrechung wird per Zufall ausgegeben und kann um einen Faktor/Devisor geändert werden. Eine größere Pause als hier im Beispiel ist besser. Das ist nur Demo. Zwei Möglichkeiten können hierfür Anwendung finden. Der Strecke bis zum Nullpunkt wird ein Vorlauf gegeben (hier angewendet), oder ein Timeout mit der ausgegeben Pause wird gesetzt.
So soll verhindert werden, dass eine Animation nicht mit einer drögen ständigen Wiederholung in Erscheinung tritt.
Sowas nervt ganz schnell.

4. Auszug: Script, dass eine Unterbrechnung ausgibt

179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
<script>
var 
obj_soll document.getElementById ('soll') ;
obj_soll.setAttributeNS(null,'opacity'0) ;
var 
xs=10xms=0aktxposs=;
obj_soll.style.top "px" ;
var 
is=0opacs=0opaczs=;
var 
pause=0insec=;
function 
MITPAUSE(){
 
obj_soll.setAttribute('cx',aktxposs) ;
 if ( 
xms <= 100 opaczsxms  ;     
 if ( 
xms 100 && xms 400 opaczs 
 if ( 
xms >= 400 opaczs=100-Math.abs(400-xms) ;
 
opacs opaczs/100 ;
 
obj_soll.setAttributeNS(null,'opacity'opacs) ;
 
aktxposs xs+xms ;
 if ( 
xms <= 500setTimeout(MITPAUSEzeitschritt) ; 
 else {
 
pause Math.round(Math.random()*100)/10 ;
 
xms 50 * (-pause) ;    
 
setTimeout(MITPAUSEpause)
 }
 
insec Math.round(xms/.5)/100 ;
 
document.getElementById ('prand').innerHTML "Unterbrechung: "+pause+"sec, Messung: "+insec 
 
xms++ ;
}
MITPAUSE() ;
</script>

Für MSIE oder Edge gilt der Hinweis hier, falls einer der beiden in Benutzung!

Solange die Bewegung sich auf eine geradliniegen Achse mit elem.setAttribute('cx',aktx) bezieht, ist mit JavaScript diesem Problem beizukommen. Für die Animation „Stern auf Pfad“ habe ich keine Entsprechung für JavaScript finden können. Vielleicht geht das auch garnicht. Hier muss somit wieder auf animateMotion zurückgegriffen werden.

animateMotion und Ablauffolge in Sets

Nun, eine Rettung hat sich aufgetan. Eine Wiederholungsrate von 4 wird gesetzt und in 4 Sets wird dem Stern je eine Sichtbarkeit visible,hidden,hidden,hidden gesetzt. So wird alle 40 Sekunden der Stern nur aufgehen. Der Start erfolgt nach 10 Sekunden. Wenigstens was!

5. Auszug: SVG-Element „stern“ erhält in Sets eine der beiden Varianten für die Sichtbarkeit.

249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
<svg width="150" height="90" class="mP" xmlns:xlink="http://www.w3.org/1999/xlink" >
 <defs> 
  <radialGradient id="stern-grad"
   cx=".5" cy=".5" r="1">
   <stop offset="0" stop-color="rgba(255,255,255,1)" />
   <stop offset="1" stop-color="rgba(255,255,255,0)" />
  </radialGradient>
 </defs>
 <rect width="150" height="90" fill="rgb(0,50,200)" />
 
 <g transform="translate(-8,-18) scale(2)" >
 <path id="motionPath" fill="none" stroke="gold" stroke-width=".5"
    d="M 13.5, 44.8 
    C 17.4, 37.2, 26.2, 30.3, 33.1, 27.5
    C 41.0, 24.3, 50.2, 23.5, 61.4, 27.3 "/> 
    
 <polygon id="stern" fill="url(#stern-grad)" transform="translate(-8,-26) scale(.6)"
  points="12.3,40.8 13.7,32.1 15.2,40.8 22,37.7 16.5,42.9 
        22.83,47.241 15.369,45.294 13.692,52.308 12.291,45.294 
        6.092,47.241 11.12,43.085 6.092,37.742     ">        
        <animateMotion fill="freeze" 
         id="loops"
         begin="10s;loops.end"
         dur="10s" repeatCount="4">
   <mpath xlink:href="#motionPath"/>
  </animateMotion>
  <set begin="loops.begin"
             attributeType="CSS"
             attributeName="visibility"
             to="visible" />
  <set begin="loops.repeat(1)"
             attributeType="CSS"
             attributeName="visibility"
             to="hidden" />
  <set begin="loops.repeat(2)"
             attributeType="CSS"
             attributeName="visibility"
             to="hidden" />
  <set begin="loops.repeat(3)"
             attributeType="CSS"             
             attributeName="visibility"
             to="hidden" /> 
    </polygon>    
    </g>
</svg>

Eine zufällige und damit nicht vorhersehbare Animation schließt sich somit aus, aber eine Lösung ist gefunden, auch wenn das nur durch eine „höchst unsensible Hilfskrücke“ ermöglicht ist.
Für die Demonstration: JavaScript ► Spielereien ► Mausposition war ich auf der Suche.




Dokument geändert am: 02. Jul. 2019 14:31