CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-vue-echarts

Vue.js component for Apache ECharts™ providing declarative data visualization with Vue 2.7+ and Vue 3.1+ support

Pending
Overview
Eval results
Files

main-component.mddocs/

Main Component

The core Vue component that renders ECharts instances with reactive props, comprehensive event handling, and automatic lifecycle management.

Capabilities

VChart Component

The main Vue component for rendering ECharts. Provides reactive chart updates, event handling, and full access to ECharts API methods.

/**
 * Vue component for rendering ECharts with reactive props
 * Automatically manages chart lifecycle and provides method access
 */
declare const VChart: DefineComponent<
  ChartProps & ChartEventProps,
  {
    root: Ref<HTMLElement | undefined>;
    chart: Ref<EChartsType | undefined>;
  },
  {},
  {},
  ChartMethods
>;

interface ChartProps {
  /** ECharts option configuration object */
  option?: Option;
  /** Chart theme (object or string name like 'dark') */
  theme?: Theme;
  /** ECharts initialization options */
  initOptions?: InitOptions;
  /** Chart update options */
  updateOptions?: UpdateOptions;
  /** Auto-resize configuration */
  autoresize?: AutoResize;
  /** Loading state */
  loading?: boolean;
  /** Loading animation options */
  loadingOptions?: LoadingOptions;
  /** Chart group name for linking charts */
  group?: string;
  /** Manual update mode - prevents automatic option watching */
  manualUpdate?: boolean;
}

Usage Examples:

<template>
  <v-chart 
    :option="chartOption"
    :theme="chartTheme"
    :autoresize="true"
    :loading="isLoading"
    @click="handleClick"
    class="chart"
  />
</template>

<script setup>
import VChart from "vue-echarts";
import { ref } from "vue";

const chartOption = ref({
  xAxis: { type: "category", data: ["A", "B", "C"] },
  yAxis: { type: "value" },
  series: [{ data: [120, 200, 150], type: "bar" }]
});

const chartTheme = ref("dark");
const isLoading = ref(false);

function handleClick(params) {
  console.log("Chart clicked:", params);
}
</script>

Component Events

Vue-ECharts supports all ECharts events through Vue event props. Event names are converted to Vue's on* format.

type ChartEventProps = {
  [key in keyof Emits as key extends string
    ? `on${Capitalize<key>}`
    : never]?: Emits[key];
};

interface Emits {
  // Mouse events
  click: (params: ECElementEvent) => void;
  dblclick: (params: ECElementEvent) => void;
  mousedown: (params: ECElementEvent) => void;
  mousemove: (params: ECElementEvent) => void;
  mouseup: (params: ECElementEvent) => void;
  mouseover: (params: ECElementEvent) => void;
  mouseout: (params: ECElementEvent) => void;
  contextmenu: (params: ECElementEvent) => void;
  globalout: (params: ECElementEvent) => void;
  
  // ZRender events (with zr: prefix)
  "zr:click": (params: ElementEvent) => void;
  "zr:mousewheel": (params: ElementEvent) => void;
  "zr:drag": (params: ElementEvent) => void;
  "zr:dragstart": (params: ElementEvent) => void;
  "zr:dragend": (params: ElementEvent) => void;
  "zr:dragenter": (params: ElementEvent) => void;
  "zr:dragleave": (params: ElementEvent) => void;
  "zr:dragover": (params: ElementEvent) => void;
  "zr:drop": (params: ElementEvent) => void;
  "zr:mousedown": (params: ElementEvent) => void;
  "zr:mouseup": (params: ElementEvent) => void;
  "zr:dblclick": (params: ElementEvent) => void;
  "zr:contextmenu": (params: ElementEvent) => void;
  
  // Chart-specific events
  highlight: (params: any) => void;
  downplay: (params: any) => void;
  selectchanged: (params: any) => void;
  legendselectchanged: (params: any) => void;
  legendselected: (params: any) => void;
  legendunselected: (params: any) => void;
  legendselectall: (params: any) => void;
  legendinverseselect: (params: any) => void;
  legendscroll: (params: any) => void;
  datazoom: (params: any) => void;
  datarangeselected: (params: any) => void;
  graphroam: (params: any) => void;
  georoam: (params: any) => void;
  treeroam: (params: any) => void;
  timelinechanged: (params: any) => void;
  timelineplaychanged: (params: any) => void;
  restore: (params: any) => void;
  dataviewchanged: (params: any) => void;
  magictypechanged: (params: any) => void;
  geoselectchanged: (params: any) => void;
  geoselected: (params: any) => void;
  geounselected: (params: any) => void;
  axisareaselected: (params: any) => void;
  brush: (params: any) => void;
  brushEnd: (params: any) => void;
  brushselected: (params: any) => void;
  globalcursortaken: (params: any) => void;
  
  // Lifecycle events
  rendered: (params: { elapsedTime: number }) => void;
  finished: () => void;
}

Usage Examples:

<template>
  <v-chart 
    @click="handleClick"
    @legend-select-changed="handleLegendChange"
    @zr:click="handleZrClick"
    @rendered="handleRendered"
  />
</template>

<script setup>
function handleClick(params) {
  console.log("Data item clicked:", params.data);
}

function handleLegendChange(params) {
  console.log("Legend selection changed:", params.selected);
}

function handleZrClick(params) {
  console.log("Canvas clicked:", params);
}

function handleRendered(params) {
  console.log("Chart rendered in:", params.elapsedTime, "ms");
}
</script>

Component Methods

All ECharts instance methods are exposed through the component for programmatic control.

interface ChartMethods {
  /** Get chart width in pixels */
  getWidth(): number;
  /** Get chart height in pixels */
  getHeight(): number;
  /** Get chart DOM element */
  getDom(): HTMLElement;
  /** Get current chart option */
  getOption(): Option;
  /** Resize chart to fit container */
  resize(): void;
  /** Dispatch action to chart */
  dispatchAction(payload: any): void;
  /** Convert logical coordinate to pixel coordinate */
  convertToPixel(finder: any, value: any): number[] | number;
  /** Convert pixel coordinate to logical coordinate */
  convertFromPixel(finder: any, value: any): number[] | number;
  /** Check if pixel coordinate is in specified area */
  containPixel(finder: any, value: number[]): boolean;
  /** Get chart as data URL */
  getDataURL(opts?: { type?: string; pixelRatio?: number; backgroundColor?: string; excludeComponents?: string[] }): string;
  /** Get connected charts as data URL */
  getConnectedDataURL(opts?: { type?: string; pixelRatio?: number; backgroundColor?: string; excludeComponents?: string[] }): string;
  /** Append data to series */
  appendData(opts: { seriesIndex: number; data: any[] }): void;
  /** Clear chart */
  clear(): void;
  /** Check if chart is disposed */
  isDisposed(): boolean;
  /** Dispose chart instance */
  dispose(): void;
  /** Set chart option */
  setOption(option: Option, updateOptions?: UpdateOptions): void;
  /** Show loading animation */
  showLoading(opts?: LoadingOptions): void;
  /** Hide loading animation */
  hideLoading(): void;
}

Usage Examples:

<template>
  <v-chart ref="chartRef" :option="option" />
  <button @click="exportChart">Export PNG</button>
  <button @click="refreshChart">Refresh</button>
</template>

<script setup>
import { ref } from "vue";

const chartRef = ref();

function exportChart() {
  const dataURL = chartRef.value.getDataURL({
    type: "png",
    pixelRatio: 2,
    backgroundColor: "#fff"
  });
  // Use dataURL for download or display
}

function refreshChart() {
  chartRef.value.clear();
  chartRef.value.setOption(newOption, { notMerge: true });
}
</script>

Native DOM Events

For native DOM events on the chart container, use the native: prefix:

<template>
  <v-chart 
    @native:click="handleNativeClick"
    @native:focus="handleFocus"
    @native:blur="handleBlur"
  />
</template>

<script setup>
function handleNativeClick(event) {
  console.log("Native DOM click:", event.target);
}

function handleFocus(event) {
  console.log("Chart container focused");
}

function handleBlur(event) {
  console.log("Chart container blurred");
}
</script>

Manual Update Mode

When manualUpdate is true, the chart won't automatically react to option changes. Use setOption method for manual updates.

<template>
  <v-chart 
    ref="chart"
    :option="option"
    :manual-update="true"
  />
  <button @click="updateChart">Update Chart</button>
</template>

<script setup>
import { ref } from "vue";

const chart = ref();
const option = ref({ /* initial option */ });

function updateChart() {
  const newOption = { /* updated option */ };
  chart.value.setOption(newOption, { notMerge: true });
}
</script>

Group Linking

Charts can be linked by setting the same group name, enabling coordinated interactions.

<template>
  <v-chart :option="chart1Option" group="dashboard" />
  <v-chart :option="chart2Option" group="dashboard" />
</template>

<script setup>
// Both charts will be linked for brush selection, data zoom, etc.
const chart1Option = ref({ /* ... */ });
const chart2Option = ref({ /* ... */ });
</script>

Loading State Management

Advanced loading state patterns:

<template>
  <div class="chart-container">
    <v-chart 
      ref="chartRef"
      :option="chartOption"
      :loading="isLoading"
      :loading-options="loadingConfig"
      @rendered="onChartRendered"
    />
    <div v-if="error" class="error-message">
      {{ error }}
    </div>
  </div>
</template>

<script setup>
import { ref } from "vue";
import VChart from "vue-echarts";

const chartRef = ref();
const chartOption = ref(null);
const isLoading = ref(true);
const error = ref(null);

const loadingConfig = {
  text: "Loading chart data...",
  color: "#409eff",
  textColor: "#000",
  maskColor: "rgba(255, 255, 255, 0.8)",
  showSpinner: true,
  spinnerRadius: 10
};

// Simulate data loading
async function loadChartData() {
  try {
    isLoading.value = true;
    error.value = null;
    
    const response = await fetch("/api/chart-data");
    const data = await response.json();
    
    chartOption.value = {
      xAxis: { type: "category", data: data.categories },
      yAxis: { type: "value" },
      series: [{ type: "bar", data: data.values }]
    };
  } catch (err) {
    error.value = "Failed to load chart data";
    console.error(err);
  } finally {
    isLoading.value = false;
  }
}

function onChartRendered() {
  console.log("Chart rendered successfully");
}

// Load data on mount
loadChartData();
</script>

Dynamic Chart Updates

Handling complex chart updates with animation:

<template>
  <div>
    <v-chart 
      ref="chart"
      :option="chartOption"
      :update-options="updateConfig"
    />
    <button @click="addDataPoint">Add Data</button>
    <button @click="changeChartType">Toggle Type</button>
  </div>
</template>

<script setup>
import { ref } from "vue";

const chart = ref();
const chartType = ref("bar");

const updateConfig = {
  notMerge: false,
  lazyUpdate: false,
  silent: false
};

const chartOption = ref({
  animation: true,
  animationDuration: 1000,
  xAxis: { 
    type: "category", 
    data: ["Jan", "Feb", "Mar", "Apr", "May"] 
  },
  yAxis: { type: "value" },
  series: [{
    type: chartType.value,
    data: [120, 200, 150, 80, 70],
    animationDelay: (idx) => idx * 100
  }]
});

function addDataPoint() {
  const currentData = chartOption.value.series[0].data;
  const months = chartOption.value.xAxis.data;
  
  // Add new month and random data
  const newMonth = `Month ${months.length + 1}`;
  const newValue = Math.floor(Math.random() * 300) + 50;
  
  chartOption.value = {
    ...chartOption.value,
    xAxis: {
      ...chartOption.value.xAxis,
      data: [...months, newMonth]
    },
    series: [{
      ...chartOption.value.series[0],
      data: [...currentData, newValue]
    }]
  };
}

function changeChartType() {
  chartType.value = chartType.value === "bar" ? "line" : "bar";
  
  chartOption.value = {
    ...chartOption.value,
    series: [{
      ...chartOption.value.series[0],
      type: chartType.value
    }]
  };
}
</script>

Install with Tessl CLI

npx tessl i tessl/npm-vue-echarts

docs

index.md

injection-system.md

main-component.md

tile.json