2017-12-31 121 views
1

Ich implementiere ein einfaches Spiel, wo der Spieler einen roten Kreis in der Mitte des Bildschirms steuern wird. Der Kreis ist als SVG-Element implementiert.Dynamisch animieren ein SVG-Element

Ich wäre in der Lage, den Kreis zwischen zwei beliebigen Positionen innerhalb der SVG-ViewBox mit den SVG-Animationen (SMIL) zu bewegen. Der Auslöser jeder Animation ist ein Linksklick irgendwo auf dem Bildschirm.

Ich habe written code, die, glaube ich, sowohl in Firefox als auch in Chrome funktionieren sollte. In Chrome funktioniert es nur für die erste Animation und für alle nachfolgenden Animationen "teleportiert" sich der Kreis einfach. In Firefox gibt es keine Animation (und keine Fehler in der Konsole) .

Gibt es einen Fehler in meinem Code oder gibt es einige allgemein bekannte Probleme mit SMIL zu unreif?

Kann ich SMIL in diesem Anwendungsfall verwenden oder sollte ich stattdessen Leinwand verwenden?

Dies ist der Code, den ich bisher habe:

<!DOCTYPE html> 
<html> 
    <body> 
    <svg id="canvas" width="800" height="800" onclick="Move()"> 
     <circle id="player1" cx="300" cy="300" r="40" stroke="blue" stroke-width="4" fill="red"> 
     </circle> 
    </svg> 
    <script> 

     function createAnimation(attribute, playerID, duration, from, to) { 
     var animation = document.createElementNS("http://www.w3.org/2000/svg", "animate") 
     animation.setAttribute("attributeType", "XML") 
     animation.setAttribute("attributeName", attribute) 
     animation.setAttribute("dur", duration) 
     animation.setAttribute("to", to) 
     animation.setAttribute("from", from) 
     animation.setAttribute("fill", "freeze") 
     animationID = playerID + "animation" + attribute 
     animation.setAttribute("id", animationID) 
     player = document.getElementById(playerID) 
     previous_animation = document.getElementById(animationID) 
     if (previous_animation != null) { 
      player.removeChild(previous_animation) 
     } 
     player.appendChild(animation) 
     } 

     function Move() { 
     console.log(event.clientX); 
     console.log(event.clientY); 
     createAnimation("cx", "player1", "2s", document.getElementById("player1").getAttribute("cx"), event.clientX); 
     createAnimation("cy", "player1", "2s", document.getElementById("player1").getAttribute("cy"), event.clientY); 
     } 

    </script> 
    </body> 

</html> 

Antwort

1

Es gibt eine Reihe von Fragen ...

  • Es gibt kein Ereignis (oder besser gesagt evt) Objekt in Firefox, wenn Sie einen Anruf an den Anrufer weitergeben. Dieser Fehler wird in der Firefox-Browserkonsole angezeigt.
  • Firefox noch implementiert SVG 1.1 Animation, die nicht die Attributwerte nicht aktualisiert, müssen Sie animVal rufen die Werte
  • Sobald Sie einmal animiert haben zu bekommen, ist die Zeitleiste jetzt im 2s so das nächste Mal, wenn Sie eine Animation animieren von 0-2s in einem Dokument bei 2s springt es genau dort hin. Ich setze die Zeitleiste jedes Mal auf 0 zurück, wenn in der Antwort unten ein Zug ist.

<!DOCTYPE html> 
 
<html> 
 
    <body> 
 
    <svg id="canvas" width="800" height="800" onclick="Move(evt)"> 
 
     <circle id="player1" cx="300" cy="300" r="40" stroke="blue" stroke-width="4" fill="red"> 
 
     </circle> 
 
    </svg> 
 
    <script> 
 
    
 
     function createAnimation(attribute, playerID, duration, from, to) { 
 
     var animation = document.createElementNS("http://www.w3.org/2000/svg", "animate") 
 
     animation.setAttribute("attributeType", "XML") 
 
     animation.setAttribute("attributeName", attribute) 
 
     animation.setAttribute("dur", duration) 
 
     animation.setAttribute("to", to) 
 
     animation.setAttribute("from", from) 
 
     animation.setAttribute("fill", "freeze") 
 
     animationID = playerID + "animation" + attribute 
 
     animation.setAttribute("id", animationID) 
 
     player = document.getElementById(playerID) 
 
     previous_animation = document.getElementById(animationID) 
 
     if (previous_animation != null) { 
 
      player.removeChild(previous_animation) 
 
     } 
 
     player.appendChild(animation) 
 
     } 
 

 
     function Move(evt) { 
 
     console.log(evt.clientX); 
 
     console.log(evt.clientY); 
 
     createAnimation("cx", "player1", "2s", document.getElementById("player1").cx.animVal.value, evt.clientX); 
 
     createAnimation("cy", "player1", "2s", document.getElementById("player1").cy.animVal.value, evt.clientY); 
 
     document.getElementById("canvas").setCurrentTime(0); 
 
     } 
 

 
    </script> 
 
    </body> 
 

 
</html>

+0

Prost! Das funktioniert perfekt! Wie würdest du mehrere Spieler zum Einsatz bringen? Wird die Uhr jedes Mal zurückgesetzt, wenn ein Spieler einen Zug ausführt oder ein Projektil verschießt, die Bewegung des anderen Spielers/anderer Projektile beeinflusst? Ersetzen von 'document.getElementById (" canvas "). SetCurrentTime (0);' in Ihrem Code mit 'document.getElementById (" player1 "). SetCurrentTime (0);' scheint nicht mehr zu funktionieren. Ist es möglich, den Timer nur für ein einzelnes SVG-Element zurückzusetzen? –

+0

Ich habe versucht, das Problem mit dem Gruppentag zu lösen '', hier ist mein Versuch: https://jsfiddle.net/q2js23t3/3/, aber es hat nicht funktioniert. –

+1

gibt es nur eine einzige Zeitleiste für das gesamte Dokument. Sie können stattdessen neue Animationen zur aktuellen Dokumentzeit starten. Wenn Sie immer noch stecken bleiben, stellen Sie eine neue Frage. –