Core JavaScript

SVG - Shooting a Complex Arrow Animation

This JavaScript Reference section displays the code for an example program that shows how to animate the shooting of a complex arrow using scalable vector graphics (SVG).

ShootingComplexArrow.html

<!DOCTYPE html>
<html>
<head>
  <title>XoaX.net's Javascript Shooting a Complex Arrow Animation</title>
  <script type="text/javascript" src="ShootingComplexArrow.js"></script>
  <button onclick="Restart()">Shoot</button>
</head>
<body>
</body>
</html>

ShootingComplexArrow.js

const kiTotalTime = 150;
var iTime = 0;
var qPosition = { mdX:50.0, mdY:400.0};
var qInitVelocity = { mdX:3.3, mdY:10};
var qCurrVelocity = { mdX:0.0, mdY:0.0};
var gqRotationSvg = null;
var gqTranslationSvg = null;
var gbRunning = false;


function UpdateVelocityAndPosition() {
	// Change the velocity and rotation
	qCurrVelocity.mdX = qInitVelocity.mdX;
	qCurrVelocity.mdY = (20*(iTime/kiTotalTime) - qInitVelocity.mdY);
	var dAngle = ((Math.atan2(qCurrVelocity.mdY, qCurrVelocity.mdX)*180)/Math.PI);
    gqRotationSvg.setAttribute('transform', 'rotate('+dAngle+')');
    // Change the position and translation
	qPosition.mdX += qCurrVelocity.mdX;
	qPosition.mdY += qCurrVelocity.mdY;
	gqTranslationSvg.setAttribute('transform', 'translate('+qPosition.mdX+', '+qPosition.mdY+')');
}

function AnimationLoop() {
  UpdateVelocityAndPosition();
  ++iTime;
  // Stop when the arrow hits the ground
  if (qPosition.mdY < 400){
    setTimeout(AnimationLoop, 25);
  } else {
	gbRunning = false;
  }
}

function Restart() {
  if (!gbRunning) {
    qPosition.mdX = 50.0;
    qPosition.mdY = 400.0;
    iTime = 0;
    gbRunning = true;
    AnimationLoop();
  }
}

function Initialize() {
  qpBody = document.getElementsByTagName("body")[0];

  // Create a 600 by 400 pixel region for drawing
  qMainDiv = document.createElement('div');
  qpBody.appendChild(qMainDiv);
  qMainDiv.style.width = '600px';
  qMainDiv.style.height = '400px';
  qMainDiv.style.background = 'linear-gradient(cyan, tan)';

  // The Main Svg Element
  var qMainSvg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
  qMainSvg.style.width="600px";
  qMainSvg.style.height="400px";
  qMainDiv.appendChild(qMainSvg);

  // Add a Translation Element
  gqTranslationSvg = document.createElementNS("http://www.w3.org/2000/svg", "g");
  qMainSvg.appendChild(gqTranslationSvg);
  gqTranslationSvg.setAttribute('transform', 'translate('+qPosition.mdX+', '+qPosition.mdY+')');

  // Add a Rotation Element
  gqRotationSvg = document.createElementNS("http://www.w3.org/2000/svg", "g");
  gqTranslationSvg.appendChild(gqRotationSvg);
  var dAngle = -((Math.atan2(qInitVelocity.mdY, qInitVelocity.mdX)*180)/Math.PI);
  gqRotationSvg.setAttribute('transform', 'rotate('+dAngle+')');

  // The arrowhead marker
  var gqMarkerSvg = document.createElementNS("http://www.w3.org/2000/svg", "marker");
  qMainSvg.appendChild(gqMarkerSvg);
  gqMarkerSvg.setAttribute('id', 'idArrowhead');
  gqMarkerSvg.setAttribute('markerWidth', 5);
  gqMarkerSvg.setAttribute('markerHeight', 3);
  gqMarkerSvg.setAttribute('refX', 2);
  gqMarkerSvg.setAttribute('refY', 1);
  gqMarkerSvg.setAttribute('orient', 'auto');
  gqMarkerSvg.setAttribute('markerUnits', 'strokeWidth');

  // The marker path
  var gqMarkerPathSvg = document.createElementNS("http://www.w3.org/2000/svg", "path");
  gqMarkerSvg.appendChild(gqMarkerPathSvg);
  gqMarkerPathSvg.setAttribute('d', "M0,0 L0,2 L4,1 Z");
  gqMarkerPathSvg.setAttribute('fill', 'rgb(55, 55, 55)');

  // The arrowhead marker
  var gqTailMarkerSvg = document.createElementNS("http://www.w3.org/2000/svg", "marker");
  qMainSvg.appendChild(gqTailMarkerSvg);
  gqTailMarkerSvg.setAttribute('id', 'idArrowtail');
  gqTailMarkerSvg.setAttribute('markerWidth', 5);
  gqTailMarkerSvg.setAttribute('markerHeight', 3);
  gqTailMarkerSvg.setAttribute('refX', 2);
  gqTailMarkerSvg.setAttribute('refY', 1);
  gqTailMarkerSvg.setAttribute('orient', 'auto');
  gqTailMarkerSvg.setAttribute('markerUnits', 'strokeWidth');

  // The marker path
  var gqMarkerTailPathSvg = document.createElementNS("http://www.w3.org/2000/svg", "path");
  gqTailMarkerSvg.appendChild(gqMarkerTailPathSvg);
  gqMarkerTailPathSvg.setAttribute('d', "M0,0 L1,1 L0,2 L3,2, L4,1 L3,0 Z");
  gqMarkerTailPathSvg.setAttribute('fill', 'rgb(55, 55, 55)');

  // The SVG arrow element with markers for the ends
  var gqComplexArrowSvg = document.createElementNS("http://www.w3.org/2000/svg", "line");
  gqRotationSvg.appendChild(gqComplexArrowSvg);
  gqComplexArrowSvg.setAttribute('x1', -25);
  gqComplexArrowSvg.setAttribute('y1', 0);
  gqComplexArrowSvg.setAttribute('x2', 25);
  gqComplexArrowSvg.setAttribute('y2', 0);
  gqComplexArrowSvg.setAttribute('stroke', 'rgb(55, 55, 55)');
  gqComplexArrowSvg.setAttribute('stroke-width', 3);
  gqComplexArrowSvg.setAttribute('marker-end', 'url(#idArrowhead)');
  gqComplexArrowSvg.setAttribute('marker-start', 'url(#idArrowtail)');
}

window.onload = Initialize;
 

Output

 
 

© 2007–2024 XoaX.net LLC. All rights reserved.