Using amCharts 5 with SvelteKit
Use amCharts 5 in Svelte and SvelteKit with our @amcharts/amcharts5-svelte package. It creates and disposes the chart with the element, and works with server rendering.
Create a project, if you do not have one, and install amCharts with the package:
npx sv create my-appcd my-appnpm install @amcharts/amcharts5 @amcharts/amcharts5-svelteIt needs Svelte 4 or later and amCharts 5.21.4 or later.
SvelteKit’s dev server leaves amCharts to Node, which cannot load its files on its own. Add it to the server build in vite.config.ts. The production build does not need it:
import adapter from "@sveltejs/adapter-node";import { sveltekit } from "@sveltejs/kit/vite";import { defineConfig } from "vite";
export default defineConfig({ plugins: [sveltekit({ adapter: adapter() })], ssr: { noExternal: ["@amcharts/amcharts5"] }});Using the package
Section titled “Using the package”In Svelte 5.29 or later, use attachments. attachAmChart() gives your function a new root in the element; build the chart in it as in any amCharts example. attachAmChartConfig() builds a chart from a JSON config in the library’s <am5-chart> element. Both elements need a height.
<script lang="ts"> import { attachAmChart, attachAmChartConfig } from "@amcharts/amcharts5-svelte"; import type { Root } from "@amcharts/amcharts5"; import * as am5xy from "@amcharts/amcharts5/xy"; import am5themes_Animated from "@amcharts/amcharts5/themes/Animated";
let { data, config } = $props();
// The series, to give it new data later let series = $state.raw<am5xy.ColumnSeries>();
function buildChart(root: Root) { root.setThemes([am5themes_Animated.new(root)]);
const chart = root.container.children.push(am5xy.XYChart.new(root, {}));
const xAxis = chart.xAxes.push(am5xy.CategoryAxis.new(root, { categoryField: "category", renderer: am5xy.AxisRendererX.new(root, {}) }));
const yAxis = chart.yAxes.push(am5xy.ValueAxis.new(root, { renderer: am5xy.AxisRendererY.new(root, {}) }));
series = chart.series.push(am5xy.ColumnSeries.new(root, { xAxis: xAxis, yAxis: yAxis, categoryXField: "category", valueYField: "value" })); }
// The data goes to the chart once it is made, and again when it changes, // without making the chart again $effect(() => { if (series) { const rows = $state.snapshot(data); series.get("xAxis").data.setAll(rows); series.data.setAll(rows); } });</script>
<div {@attach attachAmChart(buildChart)} style="height: 500px"></div>
<am5-chart {@attach attachAmChartConfig({ config, themes: [am5themes_Animated] })} style="height: 500px"></am5-chart>- The chart is made when the element is there, and disposed when it goes. Like any attachment, it is made again when state read in its expression changes.
attachAmChart(buildChart, { renderer: "svg" })draws the chart as SVG.- A theme with settings is a pair:
themes: [am5themes_Animated, [am5themes_Adaptive, { baseColor: "#4150a0" }]]. attachAmChart(buildChart, { onError })gets errors from your function. Without it, they are reported as uncaught errors.- Give amCharts plain data:
$state.snapshot()turns Svelte state into it. - The
<am5-chart>element dispatchesready(event.detailhasrootandchart) anderror: listen withonreadyandonerror.
A map’s config names its geodata ("geoJSON": "am5geodata_worldLow"), and a config may name a locale ("locale": "am5locales_de_DE"), instead of carrying them. With npm imports they are not globals: import the files the config names and give them in resources, under the same names:
<script> import am5geodata_worldLow from "@amcharts/amcharts5-geodata/worldLow";</script>
<am5-chart {@attach attachAmChartConfig({ config: mapConfig, resources: { am5geodata_worldLow } })} style="height: 400px"></am5-chart>Svelte 4 and older Svelte 5
Section titled “Svelte 4 and older Svelte 5”Use the actions instead. With deps, the chart is made again when a value in it changes, compared by content:
<div use:amChart={{ setup: buildChart, deps: [data] }} style="height: 500px"></div>
<am5-chart use:amChartConfig={{ config }} on:ready={(event) => console.log(event.detail.chart)}></am5-chart>License
Section titled “License”With a commercial license, call am5.addLicense() once in src/hooks.client.ts, which runs when the app starts in the browser.
An example app is on GitHub.
Example
Section titled “Example”Without the package
Section titled “Without the package”To manage the chart yourself, create the root in onMount and dispose it in the function it returns. onMount runs in the browser only:
<script> import { onMount } from "svelte"; import * as am5 from "@amcharts/amcharts5"; import * as am5xy from "@amcharts/amcharts5/xy";
let chartdiv;
onMount(() => { const root = am5.Root.new(chartdiv);
const chart = root.container.children.push(am5xy.XYChart.new(root, {})); // ... axes, series and data
return () => { root.dispose(); }; });</script>
<div bind:this={chartdiv} style="height: 500px"></div>