1
votes

I'm trying to create a simple test with an svg, allowing me to change a quality setting (FPS), and a speed of rotation on an svg.

I noticed that the transform, rotate functionality works with degrees. To my knowledge it is not possible to increase precision by using decimals as degrees.

So are we stuck using the rotation degrees, which gives us a maximum of 360 pieces to divide a circle into, or is there a way to increase the precision somehow ?

The reason I ask is because I created a pen https://codepen.io/KaGys/pen/yKVjrr?editors=1111 in which I added several quality settings. A higher quality setting results in a higher number of frames per second. This means that if 1 degree is the smallest unit I can rotate at, I would need to start delaying the animation to go slower than 1 degree per frame, which at my highest quality setting (fastest frames per second) is still a pretty fast rotation. I hope the question is clear, if not, please let me know and I'll try to clarify.

    var ultra = 1000 / 120;
    var high = 1000 / 60;
    var medium = 1000 / 30;
    var low = 1000 / 10;

    var quality = ultra;

    var speed = 1; // degrees per frame on ultra quality (converts to lower quality settings to maintain consistency)
    // I tried doing this on per second basis, which works but the problem is that degrees can not be decimals which causes inconsistent behavior
    speed = (speed * quality) / ultra; // Recalculate the speed for consistency across quality settings

  var rotateSettings = {
    path: document.getElementById("pathGroup"),
    active: false,
    speed: speed,
    quality: quality
  };

  function rotate() {
    if (this.active) {
      setTimeout(rotate.bind(this), this.quality);
      var currentRotation = Number(
        /\d+/.exec(this.path.getAttributeNS(null, "transform"))
      );
  currentRotation = currentRotation%360;
      console.log(this.speed);
      this.path.setAttributeNS(
        null,
        "transform",
        `rotate(${currentRotation + this.speed}, 60, 60)`
      );
    }
  }

  document.getElementById("btnRotate").addEventListener("click", e => {
    if (!rotateSettings.active) {
      rotateSettings.active = true;
      document.getElementById("btnRotate").style.background = "green";
      document.getElementById("btnRotate").style.color = "white";
      rotate.bind(rotateSettings)();
    } else {
      rotateSettings.active = false;
      document.getElementById("btnRotate").style.background = "white";
      document.getElementById("btnRotate").style.color = "green";
    }
  });
1
your knowledge is incorrect, you could easily correct your misconception by trying a rotate with a floating point number. - Robert Longson
Hi Robert, Could you please check codepen.io/KaGys/pen/yKVjrr?editors=1111 . If you change the speed there (var speed = 1; ) to for example speed 0.5 or 1.5. 0.5 won't work. If rotation degrees accept floating points, where am I going wrong here ? (use rotate button to test, the console will log your speed setting in the loop so you can see the loop still works) Thanks in advance ! - Kasper Gyselinck
The logic you've written to decompose the transform an get the value out is incorrect. You'll find the SVG DOM easier than doing it yourself. - Robert Longson
Your response was very helpful at finding the mistake and it clears up my misconception about rotation and floating points. Thanks Robert. In case anyone wonders, the mistake is here: /\d+/.exec(this.path.getAttributeNS(null, "transform")) The regular expression only extracts numbers. It was corrected by changing the regular expression to: /\d*\.?\d+/ I'm not sure what you mean by using the SVG DOM though. - Kasper Gyselinck

1 Answers

2
votes

You can read the transform angle via the SVG DOM

var currentRotation = this.path.transform.animVal[0].angle;