Skip to content
Back to skills

Echarts

ASecurity

Creates interactive data visualizations with Apache ECharts, the open-source JavaScript charting library. Use when a user asks to build charts, dashboards, or data-driven graphics using ECharts in React, Vue, or vanilla JavaScript applications, render a chart to SVG on the server, or upgrade from ECharts 5 to 6.

  • 142 stars
  • 0 votes
  • 3 copies
  • 107 views
  • Added May 27, 2026
developmentjavascripttypescriptrustgojavabashreactvuenodeaws

Works with

  • terminal
  • cli

Security analysis

A96/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 2 files and shows the line behind each finding

Scanned October 4, 2026

npx -y skills add TerminalSkills/skills --skill echarts --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Echarts?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Echarts
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/terminalskills-echarts/badge)](https://www.skillsdirectory.com/skills/terminalskills-echarts)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: echarts
description: >-
  Creates interactive data visualizations with Apache ECharts, the open-source JavaScript charting library. Use when a user asks to build charts, dashboards, or data-driven graphics using ECharts in React, Vue, or vanilla JavaScript applications, render a chart to SVG on the server, or upgrade from ECharts 5 to 6.
license: Apache-2.0
compatibility: "ECharts 6.x (checked against 6.1.0) in modern browsers, or Node.js for server-side SVG. React: echarts-for-react 3.0.6. Vue: vue-echarts 8 (Vue 3.3+, ECharts 6 only)."
metadata:
  author: terminal-skills
  version: "1.1.0"
  category: data-ai
  tags: ["charts", "interactive", "canvas", "dashboard", "analytics"]
  repository: https://github.com/apache/echarts
---
# ECharts — Enterprise Data Visualization

## Overview

Apache ECharts is an open-source (Apache-2.0) JavaScript charting library. A chart is one plain `option` object passed to `chart.setOption()`: line, bar, pie, scatter, heatmap, tree, sankey, geographic and custom series, with tooltips, zooming, animation and themes built in. It draws on Canvas (the default) or SVG, and in Node.js it can produce an SVG string without a browser. ECharts 6 changed the default theme and added runtime theme switching plus chord, beeswarm, broken-axis and matrix-layout charts.

## Instructions

### Installation

```bash
npm install echarts                       # Vanilla JS
npm install echarts echarts-for-react     # React
npm install echarts vue-echarts           # Vue 3
```

### Vanilla JavaScript

```javascript
import * as echarts from "echarts/core";
import { BarChart, LineChart } from "echarts/charts";
import { DatasetComponent, GridComponent, LegendComponent, TooltipComponent } from "echarts/components";
import { CanvasRenderer } from "echarts/renderers";

// Tree-shakeable imports: register what the chart uses. A renderer is always required.
echarts.use([BarChart, LineChart, DatasetComponent, GridComponent, LegendComponent, TooltipComponent, CanvasRenderer]);

const el = document.getElementById("revenue-chart");   // the element needs a CSS width and height
const chart = echarts.init(el);
chart.setOption({
  tooltip: { trigger: "axis" },
  legend: {},
  dataset: {
    source: [
      ["month", "Revenue", "Costs"],
      ["Jan", 42000, 31000],
      ["Feb", 46500, 32500],
      ["Mar", 51200, 34100],
    ],
  },
  xAxis: { type: "category" },
  yAxis: {},
  series: [{ type: "bar" }, { type: "line" }],        // each series takes the next dataset column
});

// The chart does not follow its container: call resize() yourself
const observer = new ResizeObserver(() => chart.resize());
observer.observe(el);
// On teardown: observer.disconnect(); chart.dispose();
```

`import * as echarts from "echarts"` registers everything and needs no `use()` call: simpler, but a much larger bundle.

### React Integration

```tsx
// Using echarts-for-react wrapper
import { useEffect, useRef } from "react";
import ReactECharts from "echarts-for-react";

function SalesChart({ data }) {
  const option = {
    title: { text: "Monthly Sales", left: "center" },
    tooltip: {
      trigger: "axis",
      formatter: (params) => {
        return params.map(p => `${p.seriesName}: $${p.value.toLocaleString()}`).join("<br/>");
      },
    },
    legend: { bottom: 0, data: ["Revenue", "Costs", "Profit"] },
    xAxis: { type: "category", data: data.map(d => d.month) },
    yAxis: { type: "value", axisLabel: { formatter: "${value}" } },
    series: [
      { name: "Revenue", type: "bar", data: data.map(d => d.revenue), color: "#4f46e5" },
      { name: "Costs", type: "bar", data: data.map(d => d.costs), color: "#ef4444" },
      { name: "Profit", type: "line", data: data.map(d => d.profit), color: "#22c55e",
        smooth: true, areaStyle: { opacity: 0.1 } },
    ],
    toolbox: {
      feature: {
        saveAsImage: {},                  // Download as PNG
        dataZoom: {},                     // Zoom into data
        restore: {},                      // Reset view
      },
    },
    dataZoom: [{ type: "slider", start: 0, end: 100, bottom: 30 }],  // Range slider above the legend
    grid: { bottom: 90 },
  };

  return <ReactECharts option={option} style={{ height: 500 }} />;
}

// Donut chart; onEvents receives ECharts events such as a click on a slice
function CategoryBreakdown({ data, onSelect }) {
  const option = {
    tooltip: { trigger: "item", formatter: "{b}: {c} ({d}%)" },
    series: [{
      type: "pie",
      radius: ["40%", "70%"],             // Donut chart
      avoidLabelOverlap: true,
      itemStyle: { borderRadius: 8, borderColor: "#fff", borderWidth: 2 },
      label: { show: true, formatter: "{b}\n{d}%" },
      emphasis: { label: { fontSize: 16, fontWeight: "bold" } },
      data: data.map(d => ({ value: d.count, name: d.category })),
    }],
  };
  return <ReactECharts option={option} style={{ height: 400 }}
    onEvents={{ click: (e) => onSelect(e.name) }} />;
}

// Real-time streaming chart: update the instance directly instead of re-rendering React
function LiveMetrics({ readLatency }) {
  const chartRef = useRef(null);
  const points = useRef([]);
  const baseOption = {
    animation: false,
    xAxis: { type: "time" },
    yAxis: { type: "value", name: "ms" },
    series: [{ type: "line", showSymbol: false, data: [] }],
  };

  useEffect(() => {
    const interval = setInterval(() => {
      const chart = chartRef.current?.getEchartsInstance();
      if (!chart) return;
      // Append new data point, keep the last 60
      points.current = [...points.current, [Date.now(), readLatency()]].slice(-60);
      chart.setOption({ series: [{ data: points.current }] });
    }, 1000);
    return () => clearInterval(interval);
  }, [readLatency]);

  return <ReactECharts ref={chartRef} option={baseOption} style={{ height: 300 }} />;
}
```

### Vue Integration

```vue
<template>
  <VChart :option="option" autoresize style="height: 400px" />
</template>

<script setup lang="ts">
import { ref } from "vue";
import { use } from "echarts/core";
import { BarChart } from "echarts/charts";
import { GridComponent, TooltipComponent } from "echarts/components";
import { CanvasRenderer } from "echarts/renderers";
import VChart from "vue-echarts";

use([BarChart, GridComponent, TooltipComponent, CanvasRenderer]);

const option = ref({
  tooltip: {},
  xAxis: { type: "category", data: ["Mon", "Tue", "Wed", "Thu", "Fri"] },
  yAxis: {},
  series: [{ type: "bar", data: [412, 388, 455, 501, 476] }],
});
</script>
```

### Advanced Charts

```typescript
// Sankey diagram (flow visualization) — every name used in links must be listed in data
const sankeyOption = {
  series: [{
    type: "sankey",
    data: [
      { name: "Organic" }, { name: "Paid" }, { name: "Referral" }, { name: "Signup" },
      { name: "Activation" }, { name: "Churned" }, { name: "Paid User" },
    ],
    links: [
      { source: "Organic", target: "Signup", value: 5000 },
      { source: "Paid", target: "Signup", value: 3000 },
      { source: "Referral", target: "Signup", value: 2000 },
      { source: "Signup", target: "Activation", value: 6000 },
      { source: "Signup", target: "Churned", value: 4000 },
      { source: "Activation", target: "Paid User", value: 3500 },
    ],
  }],
};

// Heatmap (calendar-style, like GitHub contributions); dailyData = [{ date: "2026-03-14", commits: 7 }, ...]
const calendarHeatmap = {
  visualMap: { min: 0, max: 100, type: "piecewise", orient: "horizontal", left: "center" },
  calendar: { range: "2026", cellSize: ["auto", 15] },
  series: [{
    type: "heatmap",
    coordinateSystem: "calendar",
    data: dailyData.map(d => [d.date, d.commits]),
  }],
};
```

### Upgrading from ECharts 5 to 6

`npm install echarts@6` needs no code changes in most projects, but charts look different: a new color palette, and the legend now sits at the bottom by default.

```javascript
import * as echarts from "echarts";
import "echarts/theme/v5.js";                      // keep the .js: "echarts/theme/v5" fails to resolve in Node

const chart = echarts.init(el, "v5");             // version 5 colors and component positions
chart.setOption(option);
// New in 6: switch theme on a live chart (it has no effect before the first setOption)
chart.setTheme(window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "v5");
```

## Examples

### Example 1: Render a chart to SVG on the server

User: "Generate the weekly signups chart as an image for our email report, no browser."

```javascript
// render-signups.mjs — run with: node render-signups.mjs
import { writeFileSync } from "node:fs";
import * as echarts from "echarts";

const chart = echarts.init(null, null, { renderer: "svg", ssr: true, width: 800, height: 400 });
chart.setOption({
  animation: false,
  title: { text: "Signups, week of 21 September" },
  xAxis: { type: "category", data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"] },
  yAxis: { type: "value" },
  series: [{ type: "bar", data: [182, 205, 197, 241, 263, 118, 96], label: { show: true, position: "top" } }],
});
writeFileSync("signups.svg", chart.renderToSVGString());
chart.dispose();
```

Result: `signups.svg`, an 800×400 vector image of about 7 KB, written without a DOM. SSR mode needs `renderer: "svg"`, `ssr: true` and an explicit width and height. For PNG output, pass a `canvas` package (node-canvas) instance to `echarts.init` and call `canvas.toBuffer("image/png")`.

### Example 2: Plot 200,000 sensor readings without freezing the page

User: "Our temperature chart has 200k points and the page locks up when it loads."

```javascript
// readings: [[timestampMs, celsius], ...] with 200,000 rows
chart.setOption({
  animation: false,
  tooltip: { trigger: "axis" },
  xAxis: { type: "time" },
  yAxis: { type: "value", scale: true, name: "°C" },
  dataZoom: [{ type: "inside" }, { type: "slider" }],
  series: [{
    type: "line",
    showSymbol: false,       // no marker per point
    sampling: "lttb",        // downsample to what the pixels can show, keeping peaks
    data: readings,
  }],
});
```

Result: the line keeps its shape while far fewer segments are drawn (rendered to SVG at 1200 px wide, 200,000 points come to about 75 KB with `sampling: "lttb"`; without it the size depends on the data, from about 230 KB for a slow drift to over 2 MB for noisy readings), and zooming with the wheel or slider reveals detail again.

## Guidelines

1. **echarts-for-react for React** — Use the wrapper for lifecycle management; pass `option` as prop, and reach for `getEchartsInstance()` only for high-frequency updates
2. **Canvas for large data** — Canvas is the default renderer and the right one beyond roughly a thousand elements; use `sampling` on lines and `large: true` on bar and scatter series, and the `echarts-gl` extension (WebGL) for millions of points
3. **Toolbox for interaction** — Enable `saveAsImage`, `dataZoom`, `restore` in the toolbox; users expect to zoom and download
4. **Responsive resize** — Plain ECharts needs `chart.resize()` from a `ResizeObserver`; `echarts-for-react` resizes on its own (`autoResize`, on by default) and `vue-echarts` when the `autoresize` prop is set. The container must have a height
5. **Theme system** — Use ECharts themes for consistent styling across charts; create custom themes at https://echarts.apache.org/en/theme-builder.html and load them with `echarts.registerTheme(name, theme)`
6. **Updates in React** — A new `option` object is merged into the chart; set `notMerge={true}` when series are removed, or stale ones stay. `lazyUpdate={true}` postpones the redraw to the next frame
7. **Dataset for shared data** — Use ECharts `dataset` component when multiple series share the same data source
8. **Server-side rendering** — Use the built-in SVG SSR mode shown in Example 1 for reports and emails; `VChart` and `ReactECharts` render only in the browser
9. **Dispose charts** — Call `chart.dispose()` when the element is removed; undisposed instances keep memory and listeners
10. **Untrusted data** — A `tooltip.formatter` function returns raw HTML; escape user-supplied text with `echarts.format.encodeHTML()` before inserting it, or it is an XSS risk

Files in this skill

  • SKILL.md5.9 KB
  • _scores.json1.9 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…