Search code examples
javascripthtmlsvgsvg.js

SVG.js: why does rotate behave in a weird way


I'm trying to get a bus with its compass move along the line. However, I can't get the compass rotating properly, it rotates and also move in a very strange way.

Could you please help me find what has gone wrong?

Here is the link to Fiddle: https://jsfiddle.net/ugvapdrj (I've not fixed the CSS yet so it overflows to the right.)

Thanks!

Code:

<div id="drawing"></div>
let canvas = SVG('drawing').size(2000, 2000)
let compassSize = 42;
let lineColour = '#f00';


let Rsc2muVkt = canvas
  .path(
    'M736 96V72c0-13-11-24-24-24h-75c-18 0-35 7-48 18l-104 94c-23 21-54 32-85 32H0'
  )
  .stroke({
    color: lineColour
  })
  .fill('none');

// Buses
let bus = canvas.image(
  'https://s3-ap-southeast-1.amazonaws.com/viabus-develop-media-resource-ap-southeast/Vehicle+Images/entity/mu/veh_core_mu_06.png',
  compassSize
);
let busCompass = canvas.image(
  'https://s3-ap-southeast-1.amazonaws.com/viabus-develop-media-resource-ap-southeast/Network+Images/Azimuth/Public/veh_ring_white.png',
  compassSize
);

moveBus(bus, busCompass, Rsc2muVkt, 0);


for (let i = 0; i <= 100; i++) {
  setTimeout(() => {
    moveBus(bus, busCompass, Rsc2muVkt, i);
  }, 1000 + i * 200);
}

function moveBus(bus, busCompass, path, to) {
  const p = path.pointAt(to / 100 * path.length());
  const newPosition = {
    x: p.x,
    y: p.y
  };

  const oldX = bus.cx();
  const oldY = bus.cy();

  bus.center(newPosition.x, newPosition.y);
  busCompass.center(newPosition.x, newPosition.y);

  const newX = bus.cx();
  const newY = bus.cy();

  const dx = newX - oldX;
  const dy = newY - oldY;
  const rotatingAngle = Math.atan2(dy, dx) * 180 / Math.PI;

  busCompass.rotate(rotatingAngle + 90);
}

Solution

  • The compass is still rotated when you try to center it on the next frame of animation. This causes the busCompass.center(...) call to use the rotated coordinate system.

    You should first call busCompass.rotate(0); to reset the rotation, then busCompass.center(...) will work as expected and the final rotation will complete.