svg with svg.js

by jpeter06

HTML

<script src="https://cdn.jsdelivr.net/npm/@svgdotjs/[email protected]/dist/svg.min.js"></script>
<svg id="svg" viewBox="-10 -10 173 61">
  <defs>
  <path id = "arrowDef"
        d = "M -2.0286728,-0.44913063 0.01728976,-2.4950973 2.0632567,-0.44913063 H 1.2448717 V 2.0060262 h -2.4551595 v -2.45515683 z"
        stroke-width = "0px" />
  </defs>
  <path class="infinity path" d="M153,20.89c0-45.88-74.95,0-74.95,0S.5,66.76.5,20.89s77.54,0,77.54,0S153,66.76,153,20.89Z" fill="none" stroke-width="12px" stroke="#fa0" vector-effect="non-scaling-stroke" marker="url(#diamond)"/>
  <g class="arrow" >
    <use xlink:href = "#arrowDef"  />
  </g>
  <text  x="38" class="small">click anywhere to start/stop</text>
  <marker id="diamond" markerWidth="12" markerHeight="12" refX="6" refY="6"
          markerUnits="userSpaceOnUse" orient="auto-start-reverse">
    <circle cx="6" cy="6" r="3"
            fill="transparent" stroke="black" stroke-width="1"/>
    <rect x="4" y="5" width="4" height="2" fill="green" stroke="context-stroke" stroke-width="2"/>
  </marker>
</svg>

CSS

body {
  height: 100vh;
  overflow: hidden;
  display: grid;
  place-items: center;
  margin: 0;
}
svg {
  overflow: visible;
  width: 100%;
  height: 100vh;
}

rect {
  transform-origin: center;
  transform-box: fill-box;
}

.path{
  marker: url(#diamond);
}
.arrow{
  transform-origin: center;
  transform-box: fill-box;
  stroke-width:0px;
  stroke:red;
  fill:blue;
}

.small { font: italic 6px sans-serif;  }

JavaScript

// Query DOM Elements
const svg = document.getElementById("svg");

//SVG.js
var draw = SVG().addTo('#svg');
//var group = draw.group();
//group.add(draw.use('arrowDef'));
//group.transform({ rotate: 125,  translateX: 20,  translateY: 30});
//END SVG.js

//draw.use('arrowDef').move(10, 10);
const w = 10;
const h = 5;
const step = 10;
const path = document.querySelector('.infinity');
const arrow = document.querySelector('.arrow');
const arrowList = [];
const totalLength = path.getTotalLength();

for(let i=0; i*step < totalLength; i++){
		var group = draw.group();
		group.add(draw.use('arrowDef'));
    arrowList.push(group);
}

let pos = 0;
let anim = false;
//animate();
// Create an object that gsap can animate
function generateMatrix(){
	var matrix = svg.createSVGMatrix();
}

function animateAll(){
  if(anim){
    pos++;
    const length = pos%totalLength;
    for(let i=0; i*step < totalLength; i++){
        animateArrow(arrowList[i], pos + i*step);
    }
  }
  requestAnimationFrame(animateAll);
}

function animateArrow(g,pos){
    const length = pos%totalLength;
    const point = path.getPointAtLength(length);
    const p1 = path.getPointAtLength(length + 5);
    const p2 = path.getPointAtLength(length - 5);

    var deg = Math.atan2(p1.y - p2.y, p1.x - p2.x) * (180 / Math.PI) + 90;
    g.transform({ rotate: deg,  translateX: point.x,  translateY: point.y});
   // g.setAttribute('transform', "translate(" + point.x + ',' + point.y +                ') rotate(' + deg + ')');
}


requestAnimationFrame(animateAll);

document.body.addEventListener('click', ()=>{
	anim = ! anim;
}, true); 

//OLD 1 arrow
/*
function animate(){
  if(anim){
    pos++;
    const length = pos%totalLength;
    const point = path.getPointAtLength(length);
    const p1 = path.getPointAtLength(length + 5);
    const p2 = path.getPointAtLength(length - 5);

    var deg = Math.atan2(p1.y - p2.y, p1.x - p2.x) * (180 / Math.PI) + 90;
    arrow.setAttribute('transform', "translate(" + point.x + ','...