Vue (ECharts) having difficulty creating pie charts

I have the following ECharts code that can be replaced using this link:

import * as echarts from 'echarts';

type EChartsOption = echarts.EChartsOption;

var chartDom = document.getElementById('main')!;
var myChart = echarts.init(chartDom);
var option: EChartsOption;

const values = [0, 0, 0, 0, 1];
const names = ['A', 'B', 'C', 'D', 'E'];

const initialValues = values.map((v, i) => ({ name: names[i], value: v }));

option = {
  tooltip: {
    trigger: 'item',
    formatter: '{a} <br/>{b} : {c} ({d}%)'
  },
  legend: {
    bottom: 10,
    left: 'center',
    data: names
  },
  series: [
    {
      type: 'pie',
      radius: '65%',
      center: ['50%', '50%'],
      selectedMode: 'single',
      data: initialValues,
      emphasis: {
        itemStyle: {
          shadowBlur: 10,
          shadowOffsetX: 0,
          shadowColor: 'rgba(0, 0, 0, 0.5)'
        }
      }
    }
  ]
};

option && myChart.setOption(option);

An issue arises when there is only one value.

const values = [0, 0, 0, 0, 1];

Upon selecting item E for label removal, 1/4 of all items are displayed, even though they are zero.

https://i.sstatic.net/eyIpv.png

My concern is how to prevent any of these items from being displayed and show 0% for item E.

Something along the lines of this image

https://i.sstatic.net/tLF9x.png

Answer №1

The data presented in the pie chart are actually ratios rather than absolute values, as the chart is designed to display proportions. When all values are 0, the chart accurately represents that they contribute equally to the whole. If a value is "empty" or nonexistent, it should be represented by null. In cases where all values are null, it is appropriate not to display the pie chart since there is no data available.

It's worth noting that the community has already addressed this issue:

Solution

In order to represent an "empty pie chart" when all values are null (indicating no data), a circle can be drawn using the following configuration:

graphic: { 
  elements: [
    {
      type: 'circle',
      left: 'center', // Positioned at horizontal center relative to its parent.
      top: 'middle',  // Positioned at vertical center relative to its parent.
      shape: {
        r: 100,
      },
      style: {
        fill: '#f7f7f7',
        stroke: '#ddd',
        lineWidth: 1
      }
    }
  ]
}

If all values are null, a gray circle will be displayed. Unfortunately, the radius (r) cannot be specified as a percentage, so a fixed width is necessary for the circle. In this case, the radius has been set to 100 for a consistent appearance.

Example

// JavaScript code snippets demonstrating the implementation

/**
 ** Initialize
 */
const chartDom = document.getElementById('chart')
const chart = echarts.init(chartDom)

/**
 ** Data
 */
let values = [null, null, null, null, null]
const names = ['A', 'B', 'C', 'D', 'E']

// Toggle to show/hide null values on the chart
document.getElementById('showNullChart').addEventListener('click', (e) => {
  const showNull = e.target.checked

  if (showNull) {
    values.fill(null)
  } else {
    values = [10, 20, 30, 40, 50]
  }
  
  updateChart()
})

/**
 ** Chart
 */
function updateChart () {
  /**
   ** Option
   */
  const option = {
    tooltip: {
      trigger: 'item',
      formatter: '{a} <br/>{b} : {c} ({d}%)'
    },
    legend: {
      bottom: 10,
      left: 'center',
      data: names
    },
    series: [
      {
        type: 'pie',
        radius: '100',
        center: ['50%', '50%'],
        selectedMode: 'single',
        data: values.map((v, i) => ({ name: names[i], value: v })),
        emphasis: {
          itemStyle: {
            shadowBlur: 10,
            shadowOffsetX: 0,
            shadowColor: 'rgba(0, 0, 0, 0.5)'
          }
        },
      }
    ],
    // Additional graphic element
    graphic: { 
      elements: [
        {
          type: 'circle',
          left: 'center', // Positioned at horizontal center relative to its parent.
          top: 'middle',  // Positioned at vertical center relative to its parent.
          shape: {
            r: 100,
          },
          style: {
            fill: '#f7f7f7',
            stroke: '#ddd',
            lineWidth: 1
          }
        }
      ]
    }
  }

  /**
   ** Render Chart
   */
  chart.setOption(option)
}
// Initial rendering of the chart
updateChart() 
<script src="https://cdnjs.cloudflare.com/ajax/libs/echarts/5.4.2/echarts.min.js" integrity="sha512-VdqgeoWrVJcsDXFlQEKqE5MyhaIgB9yXUVaiUa8DR2J4Lr1uWcFm+ZH/YnzV5WqgKf4GPyHQ64vVLgzqGIchyw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

<input type="checkbox" id="showNullChart" checked> Null (Empty Chart)

<div id="chart" style="width: 300px; height: 300px;"></div>

Extra

I neglected to mention the variable named initialValues in the formula, which should be included in the data parameter to convert every 0 value to null. This adjustment allows the chart to treat 0 values as empty as well.

const initialValues = values.map((v, i) => ({ name: names[i], value: v === 0 ? null : v }));

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Using TypeScript to work with JSON fields that include the '@' symbol

While working on an Angular project with TypeScript, I am facing a challenge of displaying certain JSON fields obtained from a POST request to the user. One of the fields begins with the '@' symbol, which is a reserved word in Angular causing th ...

Is there a way in Vue to send view data to a template component without using bindings?

Is there a way to pass data in the template part to a component without using binding like :amount=amount? I have tried amount="amount" and amount=amount but it did not work. The reason I want to avoid v-bind is because I only want the value in ...

Lethargic responsiveness of a reactive entity sourced from a library

Currently, I am in the process of developing a compact chess platform using fastAPI and Vue 3 which incorporates the composition API. To handle the chess logic, I am utilizing the chessjs library to create a chess object that comes with a range of convenie ...

Guide on sending an array of objects to Material Vue Autocomplete

Context Currently, I am dealing with a situation where I am passing an array of objects to a material autocomplete feature. The documentation for this can be found here. However, upon selecting an item from the list for the first time, it throws an error ...

Tips for preventing the vue/require-prop-type-constructor alert in VueJS

A boolean variable isTabsEnabled is being used to control a Tabview and toggle the display of tabs. This property is passed as a child to the screens where it is utilized, within this parent file. export{ props:{ isTabsEnabled: true } } When usin ...

Perform different actions based on the state of a Vue JS checkbox: "Do This" when checked and

Attempting to create a checkbox that triggers one function when initially checked, and another when it is unchecked. I have tried the following approach. There is also a variable that has been read out and reflects the current status: <input type=" ...

What is the best way to retrieve the input field's name using an Angular2 FormControl object?

My Angular 2 application features the ReactiveForms module for managing a form with its own custom validator. This validator takes in a FormControl object as an input parameter. I've noticed that multiple input fields could benefit from using this sam ...

The partial template is not functioning as anticipated

Introducing an interface designed to accept two templates, with the resulting function being a partial of one of them (similar to React-Redux): export type IState<TState, TOwnProps> = { connect: (mapStateToProps: MapStateToProps<TState, Parti ...

Challenge faced: Angular array variable not refreshing

I am currently working on a map application where users can input coordinates (latitude and longitude). I want to add a marker to the map when the "Add Waypoint" button is clicked, but nothing happens. Strangely, entering the values manually into the .ts f ...

Pass the type of object property as an argument in the function

I've been having trouble trying to figure this out and haven't been able to find a solution in the TS docs or examples I came across. Essentially, I'm working with a configuration specifying operations on object properties and looking to en ...

Endless cycle in Vue-Router when redirecting routes

I need advice on how to properly redirect non-authenticated users to the login page when using JWT tokens for authentication. My current approach involves using the router.beforeEach() method in my route configuration, but I'm encountering an issue wi ...

Importing a JavaScript file into TypeScript in NodeJS - A step-by-step guide

I'm currently diving into TypeScript as a newcomer. I am exploring the NodeJS Loopback 4 framework, which is based on Typescript language. My query revolves around how to import functions and classes exported in a JS file into my TS file. Despite tryi ...

The functionality of mdTooltip and mdDialog is currently not working as expected when used within an

Recently, I delved into the world of Angular and started working on a project that utilizes the Angular Material library. During my journey, I stumbled upon some peculiar behavior while using mdTooltip and mdDialog requests within an md-grid-list. This rai ...

What is the best approach for managing _app.js props when transitioning from a page router to an app router?

Recently, in the latest version of next.js 13.4, the app router has been upgraded to stable. This update prompted me to transition my existing page router to utilize the app router. In _app.jsx file, it is expected to receive Component and pageProps as pr ...

Attempting to dispatch data from Vue.js event bus

I am attempting to increase the count of quotes by one and also add the text from a textarea to an array. While the text is successfully added to the array, the number of quotes always remains zero. I have tried combining the two actions in one method as w ...

Arranging an array of integers followed by sorting by the decimal part of each value in a particular sequence using JavaScript

Below is an example of sorting an array: let arr = ['100.12', '100.8', '100.11', '100.9']; When sorted traditionally, the output is: '100.11', '100.12', '100.8', '100.9' Ho ...

Encountering an issue when attempting to save an excel file in Angular 8, receiving an error message that states "

When working with angular 8, I encountered an issue while trying to save an excel file. The error message displayed was as follows: ERROR TypeError: Failed to execute 'createObjectURL' on 'URL': Overload resolution failed. at Functi ...

Guide to updating the placeholder text in the element ui vue 3 table

Before sending a request to the server, I want to update the "no data" label. see image here I'm looking to display "Downloading company data..." as the new text. This question is straightforward and I'm unsure what else to include in order to ...

Having trouble implementing types with typescript in Vue-toastification for vuejs 3

Having trouble incorporating vue-toast-notification into my vue 3 project. The issue seems to be with vue Augmenting Types. I've tried other solutions without success, encountering the following error: TS2339: Property '$toast' does not exis ...

Retrieving data from an API using VUEJS3 and Typescript

I am facing an issue with displaying data in my template. When I try to do so, the screen remains blank. I am using Vue.js 3 with TypeScript and I am fairly new to this technology. <template> <div> <img :src="datas[0].imag ...