# SVG and animation (Chartist API)

> The small SVG toolkit behind the charts: elements, paths, SMIL animations, easings and line interpolation.

## Interpolation

```ts
namespace Interpolation
```

The line interpolations: functions that turn a series' points into the [`SvgPath`](https://chartist.dev/api/svg/#SvgPath) of its line, for the `lineSmooth` option of line charts. Each one is a factory: call it with its options, such as `Interpolation.cardinal({ tension: 0.2 })`, and pass the result. Write your own as a [`LineInterpolation`](https://chartist.dev/api/classes/#LineInterpolation).

- `CardinalInterpolationOptions` The options of [`Interpolation.cardinal`](https://chartist.dev/api/svg/#Interpolation.cardinal).
- `cardinal(options?: CardinalInterpolationOptions): (pathCoordinates: number[], valueData: SegmentData[]) => SvgPath` Smooths a line with a cardinal (Catmull-Rom) spline: round curves that go through every point. When values change quickly, the curve can swing past them; [`Interpolation.monotoneCubic`](https://chartist.dev/api/svg/#Interpolation.monotoneCubic) (the default for `lineSmooth: true`) doesn't. With two points or fewer, the line is straight, as with [`Interpolation.none`](https://chartist.dev/api/svg/#Interpolation.none).
- `MonotoneCubicInterpolationOptions` The options of [`Interpolation.monotoneCubic`](https://chartist.dev/api/svg/#Interpolation.monotoneCubic).
- `monotoneCubic(options?: MonotoneCubicInterpolationOptions): (pathCoordinates: number[], valueData: SegmentData[]) => SvgPath` Smooths a line with a monotone cubic spline: a smooth curve through every point that never swings above or below the values around it. It's what `lineSmooth: true` uses. The x values have to keep one direction, increasing or decreasing: where an x value repeats or turns back, the line breaks. With two points or fewer, the line is straight, as with [`Interpolation.none`](https://chartist.dev/api/svg/#Interpolation.none).
- `NoneInterpolationOptions` The options of [`Interpolation.none`](https://chartist.dev/api/svg/#Interpolation.none).
- `none(options?: NoneInterpolationOptions): (pathCoordinates: number[], valueData: SegmentData[]) => SvgPath` Draws a line as straight segments from point to point, without smoothing. It's what `lineSmooth: false` uses.
- `SimpleInteractionOptions` The options of [`Interpolation.simple`](https://chartist.dev/api/svg/#Interpolation.simple).
- `simple(options?: SimpleInteractionOptions): (pathCoordinates: number[], valueData: SegmentData[]) => SvgPath` Smooths a line with curves whose handles are horizontal: it goes through every point and never swings above or below them, but flows less than [`Interpolation.cardinal`](https://chartist.dev/api/svg/#Interpolation.cardinal). `divisor` sets how round it is.
- `StepInterpolationOptions` The options of [`Interpolation.step`](https://chartist.dev/api/svg/#Interpolation.step).
- `step(options?: StepInterpolationOptions): (pathCoordinates: number[], valueData: SegmentData[]) => SvgPath` Draws a line in steps: horizontal and vertical segments instead of diagonals or curves. Each step adds a corner to the path, and with `showPoint` a point is drawn there too.

## easings

```ts
const easings: { easeInSine: number[]; easeOutSine: number[]; easeInOutSine: number[]; easeInQuad: number[]; easeOutQuad: number[]; easeInOutQuad: number[]; easeInCubic: number[]; easeOutCubic: number[]; easeInOutCubic: number[]; easeInQuart: number[]; easeOutQuart: number[]; easeInOutQuart: number[]; easeInQuint: number[]; easeOutQuint: number[]; easeInOutQuint: number[]; easeInExpo: number[]; easeOutExpo: number[]; easeInOutExpo: number[]; easeInCirc: number[]; easeOutCirc: number[]; easeInOutCirc: number[]; easeInBack: number[]; easeOutBack: number[]; easeInOutBack: number[] }
```

The named easing curves for [`Svg.animate`](https://chartist.dev/api/svg/#Svg.animate), from `easeInSine` to `easeInOutBack`: each the four numbers of a cubic Bézier curve. Name one as an animation's `easing`, or pass four numbers of your own, such as `easing: [0.25, 0.1, 0.25, 1]`.

```ts
import { lineChart, findAll, Svg, type ChartPlugin } from 'chartist';

// Points drop in from the top and bounce a little at the end.
const dropIn: ChartPlugin = {
  name: 'drop-in',
  install(chart) {
    chart.on('mount', ({ scene, elementOf }) => {
      for (const point of findAll(scene, { role: 'point' })) {
        const element = elementOf(point);
        const { y } = point.ctx;
        if (element) {
          new Svg(element).animate({
            y1: { dur: 600, from: 0, to: y, easing: 'easeOutBack' },
            y2: { dur: 600, from: 0, to: y, easing: 'easeOutBack' }
          });
        }
      }
    });
  }
};

lineChart('#chart', { series: [[5, 2, 4, 3]] }, { plugins: [dropIn] });
```

## Svg

```ts
class Svg
```

Wraps an SVG element for chaining: set attributes and classes, add child elements, and animate attributes with SMIL. Wrap an element of a rendered chart (from `elementOf` in a `mount` listener), or create a new one by name.

Members:

- `Easing: { … }` The easing curves for [`Svg.animate`](https://chartist.dev/api/svg/#Svg.animate), as 1.x had them on the class.
- `attr: (attributes: string, ns?: string) => string | null` Set attributes on the current SVG element of the wrapper you're currently working on.
- `elem: (name: string, attributes?: Attributes, className?: string, insertFirst?: boolean) => Svg` Create a new SVG element whose wrapper object will be selected for further operations. This way you can also create nested groups easily.
- `parent: () => Svg | null` Wraps the element's parent.
- `root: () => Svg` This method returns a Svg wrapper around the root SVG element of the current tree.
- `querySelector: (selector: string) => Svg | null` Find the first child SVG element of the current element that matches a CSS selector. The returned object is a Svg wrapper.
- `querySelectorAll: (selector: string) => SvgList` Finds all descendants of the element that match a CSS selector.
- `getNode: <T extends Element = Element>() => T` Returns the underlying SVG node for the current element.
- `foreignObject: (content: string | Node, attributes?: Attributes, className?: string, insertFirst?: boolean) => Svg` This method creates a foreignObject (see https://developer.mozilla.org/en-US/docs/Web/SVG/Element/foreignObject) that allows to embed HTML content into a SVG graphic. With the help of foreignObjects you can enable the usage of regular HTML elements inside of SVG where they are subject for SVG positioning and transformation but the Browser will use the HTML rendering capabilities for the containing DOM.
- `text: (t: string) => Svg` This method adds a new text element to the current Svg wrapper.
- `empty: () => Svg` This method will clear all child nodes of the current wrapper object.
- `remove: () => Svg | null` Removes the element from its parent.
- `replace: (newElement: Svg) => Svg` This method will replace the element with a new element that can be created outside of the current DOM.
- `append: (element: Svg, insertFirst?: boolean) => Svg` This method will append an element to the current element as a child.
- `classes: () => string[]` Returns an array of class names that are attached to the current wrapper element. This method can not be chained further.
- `addClass: (names: string) => Svg` Adds one or a space separated list of classes to the current element and ensures the classes are only existing once.
- `removeClass: (names: string) => Svg` Removes one or a space separated list of classes from the current element.
- `removeAllClasses: () => Svg` Removes all classes from the current element.
- `height: () => number` Get element height using `clientHeight`
- `width: () => number` Get element width using `clientWidth`
- `animate: (animations: Record<string, AnimationDefinition | AnimationDefinition[]>, guided?: boolean, eventEmitter?: EventEmitter) => Svg` Animates attributes of the element with SMIL: adds an `<animate>` element per attribute. Each [`AnimationDefinition`](https://chartist.dev/api/svg/#AnimationDefinition) holds SMIL attributes (usually `begin`, `dur`, `from` and `to`, see https://www.w3.org/TR/SVG11/animate.html), plus an optional `easing`: a name from [`easings`](https://chartist.dev/api/svg/#easings) or four numbers of a cubic Bézier curve. An animations object could look like this: ```ts element.animate({   opacity: {     dur: 1000,     from: 0,     to: 1   },   x1: {     dur: '1000ms',     from: 100,     to: 200,     easing: 'easeOutQuart'   },   y1: {     dur: '2s',     from: 0,     to: 100   } }); ``` `dur` and `begin` given as numbers are milliseconds. **Guided mode** (the default) makes one-off animations behave: the attribute is set to `from` right away, even before a delayed start; the animation starts after `begin` ms (a timeout, not the document's timeline); and when it ends, the attribute keeps `to` and the `<animate>` element is removed. Pass `guided: false` to write the `<animate>` elements as given. An attribute with an array of definitions never runs guided.

```ts
import { barChart, findAll, Svg, type ChartPlugin } from 'chartist';

// Bars grow from the axis, animated from a plugin's mount listener.
const growBars: ChartPlugin = {
  name: 'grow-bars',
  install(chart) {
    chart.on('mount', ({ scene, elementOf }) => {
      for (const bar of findAll(scene, { role: 'bar' })) {
        const element = elementOf(bar);
        if (element) {
          new Svg(element).animate({
            y2: {
              begin: bar.ctx.valueIndex * 120,
              dur: 700,
              from: bar.attrs.y1,
              to: bar.attrs.y2,
              easing: 'easeOutQuint'
            }
          });
        }
      }
    });
  }
};

barChart('#chart', { series: [[5, 4, 3, 7]] }, { plugins: [growBars] });
```

## SvgList

```ts
class SvgList
```

A list of [`Svg`](https://chartist.dev/api/svg/#Svg) wrappers that calls an `Svg` method on all of them at once, such as `addClass` or `animate`. Each method returns the list, for chaining. [`Svg.querySelectorAll`](https://chartist.dev/api/svg/#Svg.querySelectorAll) returns one.

Members:

- `attr: (...args: [attributes: Attributes]) => SvgList` Sets attributes on every element, as [`Svg.attr`](https://chartist.dev/api/svg/#Svg.attr) does.
- `elem: (...args: [name: string, attributes?: Attributes, className?: string, insertFirst: boolean]) => SvgList` Adds a child element to every element, as [`Svg.elem`](https://chartist.dev/api/svg/#Svg.elem) does.
- `root: (...args: []) => SvgList` Calls [`Svg.root`](https://chartist.dev/api/svg/#Svg.root) on every element; returns the list, not the roots.
- `getNode: (...args: []) => SvgList` Calls [`Svg.getNode`](https://chartist.dev/api/svg/#Svg.getNode) on every element; returns the list, not the nodes.
- `foreignObject: (...args: [content: string | Node, attributes?: Attributes, className?: string, insertFirst: boolean]) => SvgList` Adds a `foreignObject` with the content to every element, as [`Svg.foreignObject`](https://chartist.dev/api/svg/#Svg.foreignObject) does.
- `text: (...args: [t: string]) => SvgList` Adds a text node to every element, as [`Svg.text`](https://chartist.dev/api/svg/#Svg.text) does.
- `empty: (...args: []) => SvgList` Removes the children of every element, as [`Svg.empty`](https://chartist.dev/api/svg/#Svg.empty) does.
- `remove: (...args: []) => SvgList` Removes every element from its parent, as [`Svg.remove`](https://chartist.dev/api/svg/#Svg.remove) does.
- `addClass: (...args: [names: string]) => SvgList` Adds classes to every element, as [`Svg.addClass`](https://chartist.dev/api/svg/#Svg.addClass) does.
- `removeClass: (...args: [names: string]) => SvgList` Removes classes from every element, as [`Svg.removeClass`](https://chartist.dev/api/svg/#Svg.removeClass) does.
- `removeAllClasses: (...args: []) => SvgList` Removes all classes from every element, as [`Svg.removeAllClasses`](https://chartist.dev/api/svg/#Svg.removeAllClasses) does.
- `animate: (...args: [animations: Record<string, AnimationDefinition | AnimationDefinition[]>, guided: boolean, eventEmitter?: EventEmitter]) => SvgList` Animates attributes of every element with SMIL, as [`Svg.animate`](https://chartist.dev/api/svg/#Svg.animate) does.

## SvgPath

```ts
class SvgPath
```

Builds and changes the `d` of an SVG `path`: move, line, curve and arc commands, with a cursor where new commands go. Lines, areas and slices are `SvgPath`s, and interpolations such as [`Interpolation.cardinal`](https://chartist.dev/api/svg/#Interpolation.cardinal) return one. Each command can carry the data of its point, which the chart reads back for its points.

Members:

- `join: (paths: SvgPath[], close?: boolean, options?: SvgPathOptions) => SvgPath` Joins paths into a new path, in the order given. The new path gets copies of the commands, and its cursor is at the end.
- `pathElements: PathCommand[]` The path's commands, in order: each with its letter, its coordinates and the data of its point.
- `position: (pos: number) => this` Gets or sets the current position (cursor) inside of the path. You can move around the cursor freely but limited to 0 or the count of existing elements. All modifications with element functions will insert new elements at the position of this cursor.
- `remove: (count: number) => SvgPath` Removes elements from the path starting at the current position.
- `move: (x: number, y: number, relative?: boolean, data?: SegmentData) => SvgPath` Use this function to add a new move SVG path element.
- `line: (x: number, y: number, relative?: boolean, data?: SegmentData) => SvgPath` Use this function to add a new line SVG path element.
- `curve: (x1: number, y1: number, x2: number, y2: number, x: number, y: number, relative?: boolean, data?: SegmentData) => SvgPath` Use this function to add a new curve SVG path element.
- `arc: (rx: number, ry: number, xAr: number, lAf: number, sf: number, x: number, y: number, relative?: boolean, data?: SegmentData) => SvgPath` Use this function to add a new non-bezier curve SVG path element.
- `parse: (path: string) => SvgPath` Parses the `d` of an SVG path and inserts its commands at the cursor. A closing `Z` at the end is dropped: the `close` of the path object decides that.
- `stringify: () => string` Writes the path as a string for the `d` attribute of a `path` element. Numbers are rounded to the `accuracy` option's decimals (to integers with `0`, not at all with `false`), and a closed path ends with `Z`.
- `scale: (x: number, y: number) => SvgPath` Scales all elements in the current SVG path object. There is an individual parameter for each coordinate. Scaling will also be done for control points of curves and the radii of arcs, affecting the given coordinate; an arc's rotation and flags stay as they are.
- `translate: (x: number, y: number) => SvgPath` Translates all elements in the current SVG path object. The translation is relative and there is an individual parameter for each coordinate. Translation will also be done for control points of curves, affecting the given coordinate; an arc's radii, rotation and flags stay as they are.
- `transform: (transformFnc: (cmd: PathCommand<T>, param: keyof T, cmdIndex: number, paramIndex: number, cmds: PathCommand<T>[]) => number | void) => SvgPath` This function will run over all existing path elements and then loop over their attributes. The callback function will be called for every path element attribute that exists in the current path. The method signature of the callback function looks like this: ```javascript function(pathElement, paramName, pathElementIndex, paramIndex, pathElements) ``` If something else than undefined is returned by the callback function, this value will be used to replace the old value. This allows you to build custom transformations of path objects that can't be achieved using the basic transformation functions scale and translate.
- `clone: (close?: boolean) => SvgPath` This function clones a whole path object with all its properties. This is a deep clone and path element objects will also be cloned.
- `splitByCommand: (command: string) => SvgPath[]` Splits the path into new paths, each starting at the given command, such as `'M'` to get the separate pieces of a line with holes. The letter matches absolute and relative commands. The pieces get copies of the commands and the path's options, with their cursor at the end; the last piece is closed if the path is.

```ts
import { SvgPath } from 'chartist';

const path = new SvgPath()
  .move(0, 100)
  .line(50, 20)
  .curve(70, 0, 90, 0, 100, 40);

path.stringify(); // 'M0,100L50,20C70,0,90,0,100,40'

// 10px to the right, at half the height
path.translate(10, 0).scale(1, 0.5);
```

## BasePathParams

```ts
interface BasePathParams
```

The end point every path command has.

Properties:

- `x: number` The x of the command's end point.
- `y: number` The y of the command's end point.

## MoveParams

```ts
type MoveParams = BasePathParams
```

The parameters of a move command (`M`): the point to move to.

Properties:

- `x: number` The x of the command's end point.
- `y: number` The y of the command's end point.

## LineParams

```ts
type LineParams = BasePathParams
```

The parameters of a line command (`L`): the point to draw to.

Properties:

- `x: number` The x of the command's end point.
- `y: number` The y of the command's end point.

## CurveParams

```ts
interface CurveParams extends BasePathParams
```

The parameters of a cubic Bézier curve command (`C`).

Properties:

- `x: number` The x of the command's end point.
- `y: number` The y of the command's end point.
- `x1: number` The x of the first control point.
- `y1: number` The y of the first control point.
- `x2: number` The x of the second control point.
- `y2: number` The y of the second control point.

## ArcParams

```ts
interface ArcParams extends BasePathParams
```

The parameters of an elliptical arc command (`A`), as in SVG.

Properties:

- `x: number` The x of the command's end point.
- `y: number` The y of the command's end point.
- `rx: number` The x radius of the ellipse.
- `ry: number` The y radius of the ellipse.
- `xAr: number` The rotation of the ellipse's x axis, in degrees.
- `lAf: number` The large arc flag: `1` takes the longer way around, `0` the shorter.
- `sf: number` The sweep flag: `1` draws the arc clockwise, `0` counterclockwise.

## PathParams

```ts
type PathParams = MoveParams | LineParams | CurveParams | ArcParams
```

The parameters of any path command.

## PathCommand

```ts
type PathCommand<T extends PathParams = PathParams> = { … } & T
```

A command of an [`SvgPath`](https://chartist.dev/api/svg/#SvgPath): its letter, its parameters and the data of its point.

Properties:

- `command: string` The command letter: `M`, `L`, `C` or `A`, or from a parsed path also `H`, `V`, `S`, `Q`, `T` or `Z` (lowercase when relative).
- `data?: SegmentData` The value of the chart point the command draws to, if any.

## SvgPathOptions

```ts
interface SvgPathOptions
```

The options of an [`SvgPath`](https://chartist.dev/api/svg/#SvgPath).

Properties:

- `accuracy?: number | false` The decimals numbers are rounded to when the path is stringified: `0` rounds to integers, `false` doesn't round.

## Attributes

```ts
type Attributes = Record<string, number | string | undefined | null>
```

SVG attributes by name, for [`Svg.attr`](https://chartist.dev/api/svg/#Svg.attr). `undefined` values are skipped; names with a prefix such as `ct:value` use its namespace.

## AnimationDefinition

```ts
interface AnimationDefinition
```

One SMIL animation of an attribute, for [`Svg.animate`](https://chartist.dev/api/svg/#Svg.animate): the attributes of its `<animate>` element, plus an `easing`.

Properties:

- `id?: string` The `id` of the `<animate>` element, to start other animations relative to it.
- `easing?: number[] | 'easeInSine' | 'easeOutSine' | 'easeInOutSine' | 'easeInQuad' | 'easeOutQuad' | 'easeInOutQuad' | 'easeInCubic' | 'easeOutCubic' | 'easeInOutCubic' | 'easeInQuart' | 'easeOutQuart' | 'easeInOutQuart' | 'easeInQuint' | 'easeOutQuint' | 'easeInOutQuint' | 'easeInExpo' | 'easeOutExpo' | 'easeInOutExpo' | 'easeInCirc' | 'easeOutCirc' | 'easeInOutCirc' | 'easeInBack' | 'easeOutBack' | 'easeInOutBack'` The easing: a name from [`easings`](https://chartist.dev/api/svg/#easings) or four numbers of a cubic Bézier curve. Sets `calcMode`, `keySplines` and `keyTimes` for you.
- `calcMode?: 'discrete' | 'linear' | 'paced' | 'spline'` How values are interpolated (SMIL `calcMode`); an `easing` sets `'spline'`.
- `restart?: 'always' | 'whenNotActive' | 'never'` Whether the animation can restart while it's running (SMIL `restart`).
- `repeatCount?: number | 'indefinite'` How many times the animation repeats, or `'indefinite'`.
- `repeatDur?: string` How long the animation repeats in total, or `'indefinite'`.
- `keySplines?: string` The Bézier control points of a `'spline'` animation (SMIL `keySplines`); an `easing` sets them.
- `keyTimes?: string` The times of the key values, from `0` to `1` (SMIL `keyTimes`); an `easing` sets them.
- `fill?: string` `'freeze'` keeps the last value after the animation, `'remove'` resets it. Guided mode sets `'freeze'`.
- `min?: string | number` The minimum active duration (SMIL `min`).
- `max?: string | number` The maximum active duration (SMIL `max`).
- `begin?: string | number` When the animation starts: ms as a number, or a SMIL time such as `'1s'`.
- `end?: string | number` When the animation ends (SMIL `end`).
- `dur: string | number` How long the animation runs: ms as a number, or a SMIL time such as `'2s'`.
- `from: string | number` The value the attribute starts at.
- `to: string | number` The value the attribute ends at.

## AnimationEvent

```ts
interface AnimationEvent
```

The payload of the `animationBegin` and `animationEnd` events that [`Svg.animate`](https://chartist.dev/api/svg/#Svg.animate) emits when it gets an event emitter.

Properties:

- `element: Svg` The animated element.
- `animate: Element` The `<animate>` element.
- `params: AnimationDefinition` The animation's definition, as given.
