Claude Code Plugins

Community-maintained marketplace

Feedback

Create powerful interactive charts with Apache ECharts - balanced ease-of-use and customization

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name echarts
version 1.0.0
description Create powerful interactive charts with Apache ECharts - balanced ease-of-use and customization
author workspace-hub
category data-visualization
tags charts, echarts, apache, interactive, typescript, mobile
platforms web, javascript, typescript

Apache ECharts Visualization Skill

Create stunning, interactive charts with Apache ECharts - the perfect balance of ease-of-use and extensive customization.

When to Use This Skill

Use ECharts when you need:

  • Balance of ease and power - Easy to start, powerful when needed
  • Broad chart variety - 20+ chart types including geo maps
  • TypeScript support - Full type definitions
  • Mobile responsiveness - Built-in responsive design
  • Large datasets - Efficient rendering of 100k+ points
  • Chinese/International - Excellent i18n support

Avoid when:

  • Ultimate customization needed (use D3.js)
  • Only need simple charts (use Chart.js)
  • 3D scientific visualizations (use Plotly)

Core Capabilities

1. Basic Line Chart

<!DOCTYPE html>
<html>
<head>
  <script src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script>
</head>
<body>
  <div id="main" style="width: 600px; height: 400px;"></div>
  <script>
    var myChart = echarts.init(document.getElementById('main'));

    var option = {
      title: {
        text: 'Monthly Sales'
      },
      tooltip: {
        trigger: 'axis'
      },
      legend: {
        data: ['Sales']
      },
      xAxis: {
        type: 'category',
        data: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun']
      },
      yAxis: {
        type: 'value'
      },
      series: [{
        name: 'Sales',
        type: 'line',
        data: [120, 200, 150, 80, 70, 110],
        smooth: true
      }]
    };

    myChart.setOption(option);
  </script>
</body>
</html>

2. Bar Chart with Multiple Series

var option = {
  title: {
    text: 'Quarterly Revenue Comparison'
  },
  tooltip: {
    trigger: 'axis',
    axisPointer: {
      type: 'shadow'
    }
  },
  legend: {
    data: ['2023', '2024']
  },
  grid: {
    left: '3%',
    right: '4%',
    bottom: '3%',
    containLabel: true
  },
  xAxis: {
    type: 'category',
    data: ['Q1', 'Q2', 'Q3', 'Q4']
  },
  yAxis: {
    type: 'value',
    name: 'Revenue (k$)'
  },
  series: [
    {
      name: '2023',
      type: 'bar',
      data: [120, 200, 150, 80],
      itemStyle: {
        color: '#5470C6'
      }
    },
    {
      name: '2024',
      type: 'bar',
      data: [180, 250, 200, 120],
      itemStyle: {
        color: '#91CC75'
      }
    }
  ]
};

myChart.setOption(option);

3. Pie Chart with Rich Formatting

var option = {
  title: {
    text: 'Traffic Sources',
    left: 'center'
  },
  tooltip: {
    trigger: 'item',
    formatter: '{a} <br/>{b}: {c} ({d}%)'
  },
  legend: {
    orient: 'vertical',
    left: 'left'
  },
  series: [
    {
      name: 'Access From',
      type: 'pie',
      radius: '50%',
      data: [
        { value: 1048, name: 'Search Engine' },
        { value: 735, name: 'Direct' },
        { value: 580, name: 'Email' },
        { value: 484, name: 'Affiliate' },
        { value: 300, name: 'Video Ads' }
      ],
      emphasis: {
        itemStyle: {
          shadowBlur: 10,
          shadowOffsetX: 0,
          shadowColor: 'rgba(0, 0, 0, 0.5)'
        }
      }
    }
  ]
};

myChart.setOption(option);

Complete Examples

Example 1: Loading Data from CSV

// Fetch CSV data
fetch('../data/sales.csv')
  .then(response => response.text())
  .then(csvText => {
    // Parse CSV
    const lines = csvText.trim().split('\n');
    const headers = lines[0].split(',');

    const categories = [];
    const values = [];

    for (let i = 1; i < lines.length; i++) {
      const row = lines[i].split(',');
      categories.push(row[0]);
      values.push(parseFloat(row[1]));
    }

    // Create chart
    var myChart = echarts.init(document.getElementById('main'));
    var option = {
      title: { text: 'Sales Data from CSV' },
      tooltip: { trigger: 'axis' },
      xAxis: {
        type: 'category',
        data: categories
      },
      yAxis: { type: 'value' },
      series: [{
        name: 'Sales',
        type: 'line',
        data: values,
        smooth: true,
        areaStyle: {}
      }]
    };

    myChart.setOption(option);
  });

Example 2: Multi-Axis Chart

var option = {
  title: {
    text: 'Temperature and Precipitation'
  },
  tooltip: {
    trigger: 'axis',
    axisPointer: {
      type: 'cross'
    }
  },
  legend: {
    data: ['Temperature', 'Precipitation']
  },
  xAxis: {
    type: 'category',
    data: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun']
  },
  yAxis: [
    {
      type: 'value',
      name: 'Temperature (°C)',
      position: 'left',
      axisLabel: {
        formatter: '{value} °C'
      }
    },
    {
      type: 'value',
      name: 'Precipitation (mm)',
      position: 'right',
      axisLabel: {
        formatter: '{value} mm'
      }
    }
  ],
  series: [
    {
      name: 'Temperature',
      type: 'line',
      yAxisIndex: 0,
      data: [2, 5, 9, 15, 20, 25],
      smooth: true
    },
    {
      name: 'Precipitation',
      type: 'bar',
      yAxisIndex: 1,
      data: [50, 45, 40, 35, 30, 25]
    }
  ]
};

myChart.setOption(option);

Example 3: Heatmap Calendar

// Generate data for a year
function getVirtulData(year) {
  const date = +echarts.time.parse(year + '-01-01');
  const end = +echarts.time.parse(+year + 1 + '-01-01');
  const dayTime = 3600 * 24 * 1000;
  const data = [];
  for (let time = date; time < end; time += dayTime) {
    data.push([
      echarts.time.format(time, '{yyyy}-{MM}-{dd}', false),
      Math.floor(Math.random() * 10000)
    ]);
  }
  return data;
}

var option = {
  title: {
    text: 'Activity Heatmap Calendar'
  },
  tooltip: {
    position: 'top',
    formatter: function (p) {
      return p.data[0] + ': ' + p.data[1];
    }
  },
  visualMap: {
    min: 0,
    max: 10000,
    calculable: true,
    orient: 'horizontal',
    left: 'center',
    top: 'top'
  },
  calendar: {
    range: '2024',
    cellSize: ['auto', 13]
  },
  series: {
    type: 'heatmap',
    coordinateSystem: 'calendar',
    data: getVirtulData('2024')
  }
};

myChart.setOption(option);

Example 4: Gauge Chart

var option = {
  title: {
    text: 'Performance Score'
  },
  tooltip: {
    formatter: '{a} <br/>{b} : {c}%'
  },
  series: [
    {
      name: 'Score',
      type: 'gauge',
      progress: {
        show: true
      },
      detail: {
        valueAnimation: true,
        formatter: '{value}%'
      },
      data: [
        {
          value: 85,
          name: 'Overall Score'
        }
      ]
    }
  ]
};

myChart.setOption(option);

// Animate the value
setInterval(() => {
  const newValue = Math.random() * 100;
  option.series[0].data[0].value = newValue.toFixed(2);
  myChart.setOption(option);
}, 2000);

Example 5: Geographic Map (China)

// Load map data
fetch('https://cdn.jsdelivr.net/npm/echarts/map/json/china.json')
  .then(response => response.json())
  .then(chinaJson => {
    echarts.registerMap('china', chinaJson);

    var option = {
      title: {
        text: 'Sales by Province',
        left: 'center'
      },
      tooltip: {
        trigger: 'item',
        formatter: '{b}<br/>{c} (units)'
      },
      visualMap: {
        min: 0,
        max: 1000,
        text: ['High', 'Low'],
        calculable: true
      },
      series: [
        {
          name: 'Sales',
          type: 'map',
          map: 'china',
          roam: true,
          emphasis: {
            label: {
              show: true
            }
          },
          data: [
            { name: 'Beijing', value: 500 },
            { name: 'Shanghai', value: 800 },
            { name: 'Guangdong', value: 900 },
            { name: 'Zhejiang', value: 700 }
          ]
        }
      ]
    };

    myChart.setOption(option);
  });

Example 6: Dynamic Real-Time Data

var data = [];
var now = new Date();

function randomData() {
  now = new Date(+now + 1000);
  return {
    name: now.toString(),
    value: [
      [now.getFullYear(), now.getMonth() + 1, now.getDate()].join('/') + ' ' +
      [now.getHours(), now.getMinutes(), now.getSeconds()].join(':'),
      Math.round(Math.random() * 100)
    ]
  };
}

// Initialize with 100 points
for (var i = 0; i < 100; i++) {
  data.push(randomData());
}

var option = {
  title: {
    text: 'Real-Time Data Stream'
  },
  tooltip: {
    trigger: 'axis',
    formatter: function (params) {
      params = params[0];
      return params.value[0] + ' : ' + params.value[1];
    },
    axisPointer: {
      animation: false
    }
  },
  xAxis: {
    type: 'time',
    splitLine: {
      show: false
    }
  },
  yAxis: {
    type: 'value',
    boundaryGap: [0, '100%'],
    splitLine: {
      show: false
    }
  },
  series: [
    {
      name: 'Value',
      type: 'line',
      showSymbol: false,
      data: data,
      smooth: true
    }
  ]
};

myChart.setOption(option);

// Update every second
setInterval(() => {
  data.shift();
  data.push(randomData());

  myChart.setOption({
    series: [{
      data: data
    }]
  });
}, 1000);

Best Practices

1. Use Responsive Design

// Make chart responsive
window.addEventListener('resize', function() {
  myChart.resize();
});

// Or set explicit size
myChart.resize({
  width: 800,
  height: 600
});

2. Use Loading and Empty States

// Show loading
myChart.showLoading();

// Fetch data
fetch('../data/data.json')
  .then(response => response.json())
  .then(data => {
    myChart.hideLoading();
    myChart.setOption(option);
  });

// Handle no data
if (data.length === 0) {
  myChart.setOption({
    title: {
      text: 'No Data Available',
      left: 'center',
      top: 'center'
    }
  });
}

3. Use Themes

// Use built-in themes
var myChart = echarts.init(document.getElementById('main'), 'dark');

// Or custom theme
var customTheme = {
  color: ['#c23531', '#2f4554', '#61a0a8'],
  backgroundColor: '#f4f4f4'
};

var myChart = echarts.init(document.getElementById('main'), customTheme);

4. Optimize for Large Datasets

option = {
  series: [{
    type: 'line',
    // Enable sampling for large datasets
    sampling: 'lttb',
    // Use progressive rendering
    progressive: 1000,
    progressiveThreshold: 3000,
    data: largeDataArray
  }]
};

Available Chart Types

Basic Charts

  • Line, Bar, Pie, Scatter, Candlestick

Advanced Charts

  • Radar, Heatmap, Tree, Treemap, Sunburst, Parallel, Sankey, Funnel, Gauge

Maps

  • GeoMap, BMap (Baidu Maps), Google Maps

3D Charts (with GL extension)

  • 3D Bar, 3D Line, 3D Scatter, 3D Surface, Globe

Graph Charts

  • Graph, Force-directed Graph

TypeScript Support

import * as echarts from 'echarts';

type EChartsOption = echarts.EChartsOption;

const option: EChartsOption = {
  title: {
    text: 'TypeScript Example'
  },
  xAxis: {
    type: 'category',
    data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
  },
  yAxis: {
    type: 'value'
  },
  series: [
    {
      data: [120, 200, 150, 80, 70, 110, 130],
      type: 'line'
    }
  ]
};

const chartDom = document.getElementById('main')!;
const myChart = echarts.init(chartDom);
myChart.setOption(option);

Installation

CDN

<script src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script>

NPM

npm install echarts
import * as echarts from 'echarts';

// Or import specific modules
import * as echarts from 'echarts/core';
import { LineChart } from 'echarts/charts';
import { GridComponent } from 'echarts/components';
import { CanvasRenderer } from 'echarts/renderers';

echarts.use([LineChart, GridComponent, CanvasRenderer]);

Advanced Features

Animation Configuration

option = {
  animation: true,
  animationDuration: 1000,
  animationEasing: 'cubicOut',
  animationDelay: function (idx) {
    return idx * 50;
  }
};

DataZoom (Zoom/Pan)

option = {
  dataZoom: [
    {
      type: 'inside', // Mouse wheel zoom
      start: 0,
      end: 100
    },
    {
      type: 'slider', // Slider zoom
      start: 0,
      end: 100
    }
  ],
  // ... rest of option
};

Brush Selection

option = {
  brush: {
    toolbox: ['rect', 'polygon', 'lineX', 'lineY', 'keep', 'clear'],
    xAxisIndex: 0
  },
  // ... rest of option
};

myChart.on('brushSelected', function (params) {
  var brushComponent = params.batch[0];
  var selected = brushComponent.selected[0].dataIndex;
  console.log('Selected data indices:', selected);
});

Event Handling

// Click event
myChart.on('click', function (params) {
  console.log('Clicked:', params);
  alert('You clicked on ' + params.name);
});

// Hover event
myChart.on('mouseover', function (params) {
  console.log('Hovered:', params);
});

// Custom events
myChart.dispatchAction({
  type: 'highlight',
  seriesIndex: 0,
  dataIndex: 1
});

Integration Examples

With React

import { useEffect, useRef } from 'react';
import * as echarts from 'echarts';

function EChartsComponent({ option }) {
  const chartRef = useRef(null);
  const chartInstance = useRef(null);

  useEffect(() => {
    if (!chartInstance.current) {
      chartInstance.current = echarts.init(chartRef.current);
    }

    chartInstance.current.setOption(option);

    const handleResize = () => chartInstance.current.resize();
    window.addEventListener('resize', handleResize);

    return () => {
      window.removeEventListener('resize', handleResize);
      chartInstance.current?.dispose();
    };
  }, [option]);

  return <div ref={chartRef} style={{ width: '100%', height: '400px' }} />;
}

With Vue

<template>
  <div ref="chart" style="width: 600px; height: 400px;"></div>
</template>

<script>
import * as echarts from 'echarts';

export default {
  props: ['option'],
  mounted() {
    this.chart = echarts.init(this.$refs.chart);
    this.chart.setOption(this.option);

    window.addEventListener('resize', this.handleResize);
  },
  beforeUnmount() {
    window.removeEventListener('resize', this.handleResize);
    this.chart.dispose();
  },
  methods: {
    handleResize() {
      this.chart.resize();
    }
  },
  watch: {
    option: {
      deep: true,
      handler(newOption) {
        this.chart.setOption(newOption);
      }
    }
  }
};
</script>

Resources

Performance Tips

  1. Use progressive rendering for >10k points
  2. Enable sampling for time series data
  3. Lazy load chart instances
  4. Dispose charts when unmounting
  5. Use Canvas renderer for large datasets

Use this skill for the best balance of ease-of-use and powerful customization!