Archived

Documentation for Layer Cake v10, before Svelte 5 runes. Current docs at layercake.graphics

Menu

AxisRadial.svelte component

Generates SVG axis lines and labels around a circle, for radar charts. The keys of the x accessor become the labels.

Param Default Required Description
lineLengthFactor number 1.1
no
How far to extend the lines from the circle's center. A value of 1 puts them at the circle's circumference.
labelPlacementFactor number 1.25
no
How far to place the labels from the circle's center. A value of 1 puts them at the circle's circumference.

Used in these examples:

<!--
  @component
  Generates SVG axis lines and labels around a circle, for radar charts. The keys of the x accessor become the labels.
 -->
<script>
  import { getLayerCakeContext } from 'layercake';

  const k = getLayerCakeContext();

  /**
   * @typedef {Object} Props
   * @property {number} [lineLengthFactor=1.1] - How far to extend the lines from the circle's center. A value of `1` puts them at the circle's circumference.
   * @property {number} [labelPlacementFactor=1.25] - How far to place the labels from the circle's center. A value of `1` puts them at the circle's circumference.
   */

  /** @type {Props} */
  let { lineLengthFactor = 1.1, labelPlacementFactor = 1.25 } = $props();

  // The largest x value, scaled, is the outer circle's radius
  let outerRadius = $derived(k.xScale(Math.max(...k.extents.x)));

  let lineLength = $derived(outerRadius * lineLengthFactor);
  let labelPlacement = $derived(outerRadius * labelPlacementFactor);

  let angleSlice = $derived((Math.PI * 2) / k.config.x.length);

  /** @param {number} total
   *  @param {number} i */
  function anchor(total, i) {
    if (i === 0 || i === total / 2) {
      return 'middle';
    } else if (i < total / 2) {
      return 'start';
    }
    return 'end';
  }
</script>

<g transform="translate({k.width / 2}, {k.height / 2})">
  <circle
    cx="0"
    cy="0"
    r={outerRadius}
    stroke="#ccc"
    stroke-width="1"
    fill="#CDCDCD"
    fill-opacity="0.1"
  ></circle>
  <circle cx="0" cy="0" r={outerRadius / 2} stroke="#ccc" stroke-width="1" fill="none"></circle>

  {#each k.config.x as label, i}
    {@const thisAngleSlice = angleSlice * i - Math.PI / 2}
    <line
      x1="0"
      y1="0"
      x2={lineLength * Math.cos(thisAngleSlice)}
      y2={lineLength * Math.sin(thisAngleSlice)}
      stroke="#ccc"
      stroke-width="1"
      fill="none"
    >
    </line>
    <text
      text-anchor={anchor(k.config.x.length, i)}
      dy="0.35em"
      font-size="12px"
      transform="translate({labelPlacement * Math.cos(thisAngleSlice)}, {labelPlacement *
        Math.sin(thisAngleSlice)})">{label}</text
    >
  {/each}
</g>