• Open in:

Compass Chart

This multi-arrow RadarChart uses built-in animation routines to dynamically change start and end angles of the whole chart to imitate rotating of a compass dial.

Related tutorials

Demo source

<!-- Styles -->
<style>
#chartdiv {
  width: 100%;
  height: 500px;
}
</style>

<!-- Resources -->
<script src="https://cdn.amcharts.com/lib/5/index.js"></script>
<script src="https://cdn.amcharts.com/lib/5/xy.js"></script>
<script src="https://cdn.amcharts.com/lib/5/radar.js"></script>
<script src="https://cdn.amcharts.com/lib/5/themes/Animated.js"></script>

<!-- Chart code -->
<script>
am5.ready(function() {

// Create root element
// https://www.amcharts.com/docs/v5/getting-started/#Root_element
var root = am5.Root.new("chartdiv");

// Set themes
// https://www.amcharts.com/docs/v5/concepts/themes/
root.setThemes([
  am5themes_Animated.new(root)
]);

// Create chart
// https://www.amcharts.com/docs/v5/charts/radar-chart/
var chart = root.container.children.push(
  am5radar.RadarChart.new(root, {
    panX: false,
    panY: false,
    startAngle: -90,
    endAngle: 270
  })
);

// Create axis and its renderer
// https://www.amcharts.com/docs/v5/charts/radar-chart/gauge-charts/#Axes
var axisRenderer = am5radar.AxisRendererCircular.new(root, {
  strokeOpacity: 1,
  strokeWidth: 5,
  minGridDistance: 10
});
axisRenderer.ticks.template.setAll({
  forceHidden: true
});
axisRenderer.grid.template.setAll({
  forceHidden: true
});

axisRenderer.labels.template.setAll({ forceHidden: true });

var xAxis = chart.xAxes.push(
  am5xy.ValueAxis.new(root, {
    maxDeviation: 0,
    min: 0,
    max: 360,
    strictMinMax: true,
    renderer: axisRenderer
  })
);

// Add clock hand
// https://www.amcharts.com/docs/v5/charts/radar-chart/gauge-charts/#Clock_hands
// north
var axisDataItemN = xAxis.makeDataItem({ value: 0 });

var clockHandN = am5radar.ClockHand.new(root, {
  pinRadius: 0,
  radius: am5.percent(90),
  bottomWidth: 40
});

clockHandN.hand.set("fill", am5.color(0xff0000));
// do not change angle at all
clockHandN.adapters.add("rotation", function () {
  return -90;
});

axisDataItemN.set(
  "bullet",
  am5xy.AxisBullet.new(root, {
    sprite: clockHandN
  })
);

xAxis.createAxisRange(axisDataItemN);

//south
var axisDataItemS = xAxis.makeDataItem({ value: 180 });

var clockHandS = am5radar.ClockHand.new(root, {
  pinRadius: 0,
  radius: am5.percent(90),
  bottomWidth: 40
});

// do not change angle at all
clockHandS.adapters.add("rotation", function () {
  return 90;
});

axisDataItemS.set(
  "bullet",
  am5xy.AxisBullet.new(root, {
    sprite: clockHandS
  })
);

xAxis.createAxisRange(axisDataItemS);

function createLabel(text, value, tickOpacity) {
  var axisDataItem = xAxis.makeDataItem({ value: value });
  xAxis.createAxisRange(axisDataItem);
  var label = axisDataItem.get("label");
  label.setAll({
    text: text,
    forceHidden: false,
    inside: true,
    radius: 20
  });

  var tick = axisDataItem
    .get("tick")
    .setAll({
      forceHidden: false,
      strokeOpacity: tickOpacity,
      length: 12 * tickOpacity,
      visible: true,
      inside: true
    });
}

createLabel("N", 0, 1);
createLabel("NE", 45, 1);
createLabel("E", 90, 1);
createLabel("SE", 135, 1);
createLabel("S", 180, 1);
createLabel("SW", 225, 1);
createLabel("W", 270, 1);
createLabel("NW", 315, 1);

for (var i = 0; i < 360; i = i + 5) {
  createLabel("", i, 0.5);
}

setInterval(function () {
  var newAngle = Math.random() * 360;
  chart.animate({
    key: "startAngle",
    to: newAngle,
    duration: 1000,
    easing: am5.ease.out(am5.ease.cubic)
  });
  chart.animate({
    key: "endAngle",
    to: newAngle + 360,
    duration: 1000,
    easing: am5.ease.out(am5.ease.cubic)
  });
  axisDataItemN.animate({
    key: "value",
    to: am5.math.normalizeAngle(-90 - newAngle),
    duration: 1000,
    easing: am5.ease.out(am5.ease.cubic)
  });
  axisDataItemS.animate({
    key: "value",
    to: am5.math.normalizeAngle(90 - newAngle),
    duration: 1000,
    easing: am5.ease.out(am5.ease.cubic)
  });
}, 2000);

// Make stuff animate on load
chart.appear(1000, 100);

}); // end am5.ready()
</script>

<!-- HTML -->
<div id="chartdiv"></div>