Vue Dashboard Development: ECharts Composition API Wrapper

ECharts Configuration Hook Implementation

Core Configuration Functions

The implementation begins with utility functions that define default chart styling:

const createDefaultLegend = () => ({
  bottom: 0,
  left: 0,
  orient: "vertical",
  itemWidth: 8,
  itemHeight: 8,
  textStyle: {
    color: "white",
  },
});

const createDefaultSeries = () => ({
  type: "pie",
  radius: ["50%", "70%"],
  width: 140,
  height: 140,
  label: {
    show: false,
    position: "bottom",
  },
  labelLine: {
    show: false,
  },
  data: [
    { value: 1048, name: "Large Catering >500m²" },
    { value: 735, name: "Medium Catering 150-500m²" },
    { value: 580, name: "Small Catering ≤150m²" },
  ],
});

Chart Hook Definition

The main composition function accepts configuration parameters and returns a complete ECharts options object:

export const useEChartsConfig = (configProps) => {
  let chartOptions = {
    tooltip: {
      trigger: "item",
      position: ["50%", "50%"],
      borderColor: "#9DC3EF",
      borderWidth: 1,
      backgroundColor: "rgba(16,21,35,0.8)",
      textStyle: {
        color: "white",
      },
    },
    color: ["#83BAFA", "#3768D8", "#15DED7", "#F1E49D", "#668DE3"],
    legend: createDefaultLegend(),
    series: [createDefaultSeries()],
    grid: {
      bottom: "20%",
      height: 90,
    },
  };

  // Series customization
  if (configProps.customizeSeries) {
    if (configProps.isMultiple) {
      chartOptions.series = configProps.customizeSeries();
    } else {
      chartOptions.series[0] = {
        ...createDefaultSeries(),
        ...configProps.customizeSeries(),
      };
    }
  }

  // Axis customizations
  if (configProps.customizeXAxis) {
    chartOptions.xAxis = configProps.customizeXAxis();
  }

  if (configProps.customizeYAxis) {
    chartOptions.yAxis = configProps.customizeYAxis();
  }

  // Data override
  if (configProps.customizeData) {
    chartOptions.series[0].data = configProps.customizeData();
  }

  // Legend customization
  if (configProps.customizeLegend) {
    chartOptions.legend = {
      ...createDefaultLegend(),
      ...configProps.customizeLegend(),
    };
  }

  // Responsive sizing
  if (chartOptions.series) {
    chartOptions.series.forEach((element) => {
      if (element.width && element.height) {
        const clonedElement = cloneDeep(element);
        const { width, height } = calculateResponsiveSize(
          clonedElement.width,
          clonedElement.height
        );
        element.width = width;
        element.height = height;
      }
    });
  }

  return chartOptions;
};

Responsive Sizing Utility

A helper function adjusts chart dimensions based on viewport size:

const calculateResponsiveSize = (baseWidth, baseHeight) => ({
  width: (window.innerWidth / 1920) * baseWidth,
  height: (window.innerHeight / 1080) * baseHeight,
});

Usage Examples

Social Catering Visualization

const socialCateringConfig = useEChartsConfig({
  customizeData: () => [
    { value: 1048, name: "Large Catering >500m²" },
    { value: 735, name: "Medium Catering 150-500m²" },
    { value: 580, name: "Small Catering ≤150m²" },
  ],
});

Institutional Cafeterai Display

const cafeteriaConfig = useEChartsConfig({
  customizeData: () => [
    { value: 1048, name: "School Cafeterias" },
    { value: 1048, name: "Medical Facility Cafeterias" },
    { value: 1048, name: "Other Cafeterias" },
    { value: 1048, name: "Senior Care Cafeterias" },
  ],
});

Certified Business Metrics

const businessMetricsConfig = useEChartsConfig({
  customizeData: () => [
    { value: 1048, name: "Large Catering >500m²" },
    { value: 735, name: "Medium Catering 150-500m²" },
    { value: 580, name: "Small Catering ≤150m²" },
    { value: 1048, name: "School Cafeterias" },
    { value: 1048, name: "Medical Facility Cafeterias" },
    { value: 1048, name: "Other Cafeterias" },
    { value: 1048, name: "Senior Care Cafeterias" },
  ],
  customizeSeries: () => ({
    width: 157,
    height: 157,
  }),
  customizeLegend: () => ({
    right: 0,
    left: null,
    itemGap: 25,
    top: "center",
  }),
});

This approach provides a flexible foundation for creating consistent, responsive dashboard visualizations while allowing individual customization of chart components.

Tags: vue echarts javascript composition-api data-visualization

Posted on Sat, 13 Jun 2026 18:24:09 +0000 by tommychi