Skip to content

Pie Chart ​

Pie charts are perfect for showing proportions and part-to-whole relationships. Supports both pie and donut (ring) styles.

Basic Usage ​

html
<PieChart
  [data]="pieData"
  [legend]="legendConfig"
  [animation]="animationConfig"
  [drawHole]="true"
  [holeRadius]="45"
  [drawCenterText]="true"
  [centerText]="'Total'"
  [usePercentValues]="true">
</PieChart>
tsx
<pieChart
  data={pieData}
  legend={legendConfig}
  animation={animationConfig}
  drawHole={true}
  holeRadius={45}
  drawCenterText={true}
  centerText="Total"
  usePercentValues={true}
/>
vue
<PieChart
  :data="pieData"
  :legend="legendConfig"
  :animation="animationConfig"
  :drawHole="true"
  :holeRadius="45"
  :drawCenterText="true"
  centerText="Total"
  :usePercentValues="true"
/>
svelte
<pieChart
  data={pieData}
  legend={legendConfig}
  animation={animationConfig}
  drawHole={true}
  holeRadius={45}
  drawCenterText={true}
  centerText="Total"
  usePercentValues={true}
/>
jsx
<pieChart
  data={pieData()}
  legend={legendConfig}
  animation={animationConfig}
  drawHole={true}
  holeRadius={45}
  drawCenterText={true}
  centerText="Total"
  usePercentValues={true}
/>

Dark Background Text Visibility ​

typescript
const pieData: PieChartData = {
  dataSets: [
    {
      label: 'Market Share',
      values: [35, 25, 20, 12, 8],
      config: {
        drawValues: true,
        valueTextColor: '#FFFFFF',
      },
    },
  ],
};

const legend: LegendConfig = { textColor: '#F3F4F6' };
const chartDescription: ChartDescription = { text: '', textColor: '#9CA3AF' };
const noDataTextColor = '#9CA3AF';

Data Format ​

typescript
import type { PieChartData, PieDataSet, PieDataEntry } from '@nstudio/ncharts';

const pieData: PieChartData = {
  dataSets: [
    {
      label: 'Market Share',
      values: [
        { value: 35, label: 'Product A' },
        { value: 25, label: 'Product B' },
        { value: 20, label: 'Product C' },
        { value: 12, label: 'Product D' },
        { value: 8, label: 'Others' },
      ],
      config: {
        colors: ['#F59E0B', '#EF4444', '#8B5CF6', '#3B82F6', '#6B7280'],
        sliceSpace: 3,
        selectionShift: 8,
      },
    },
  ],
};

PieDataEntry ​

PropertyTypeDescription
valuenumberSlice value (required)
labelstringSlice label text

Simplified Values

You can also pass just numbers if you don't need labels:

typescript
values: [35, 25, 20, 12, 8]

DataSet Configuration ​

Slice Styling ​

PropertyTypeDefaultDescription
colorsChartColor[]-Colors for each slice
sliceSpacenumber0Space between slices in dp
selectionShiftnumber0How far slice moves out when selected

Value Positioning ​

PropertyTypeDefaultDescription
xValuePositionValuePosition'INSIDE_SLICE'Label position
yValuePositionValuePosition'INSIDE_SLICE'Value position
typescript
type ValuePosition = 'INSIDE_SLICE' | 'OUTSIDE_SLICE';

Value Lines (for outside positioning) ​

PropertyTypeDescription
valueLinePart1LengthnumberLength of line segment 1
valueLinePart2LengthnumberLength of line segment 2
valueLineColorChartColorLine color
valueLineWidthnumberLine width
valueLinePart1OffsetPercentagenumberOffset from center
valueLineVariableLengthbooleanAuto-adjust line length

Chart Properties ​

Donut Configuration ​

PropertyTypeDefaultDescription
drawHolebooleanfalseEnable donut mode
holeRadiusnumber50Hole radius as % of chart
holeColorChartColor-Hole background color
transparentCircleRadiusnumber-Transparent circle around hole
transparentCircleColorChartColor-Transparent circle color

Center Text ​

PropertyTypeDescription
drawCenterTextbooleanShow text in center
centerTextstringCenter text content
centerTextColorChartColorText color
centerTextSizenumberText size in dp

Slice Labels ​

PropertyTypeDescription
drawSliceTextbooleanShow labels on slices
entryLabelColorChartColorLabel text color
entryLabelTextSizenumberLabel text size
usePercentValuesbooleanShow values as percentages

Interaction ​

PropertyTypeDescription
rotationEnabledbooleanAllow rotation gesture
rotationAnglenumberInitial rotation angle
maxAnglenumberMax angle for display (default 360)
highlightPerTapEnabledbooleanEnable tap selection

Complete Example ​

typescript
import type { 
  PieChartData, 
  ChartAnimation, 
  LegendConfig 
} from '@nstudio/ncharts';

// Market share data
const marketData: PieChartData = {
  dataSets: [
    {
      label: 'Market Share',
      values: [
        { value: 35, label: 'iOS Apps' },
        { value: 28, label: 'Android Apps' },
        { value: 18, label: 'Web Apps' },
        { value: 12, label: 'Desktop' },
        { value: 7, label: 'Other' },
      ],
      config: {
        colors: ['#3B82F6', '#10B981', '#F59E0B', '#8B5CF6', '#6B7280'],
        sliceSpace: 3,
        selectionShift: 10,
        drawValues: true,
        valueTextSize: 12,
        valueTextColor: '#FFFFFF',
        xValuePosition: 'INSIDE_SLICE',
        yValuePosition: 'INSIDE_SLICE',
      },
    },
  ],
};

// Animation
const animation: ChartAnimation = {
  durationX: 1400,
  durationY: 1400,
  easingX: 'EaseOutBounce',
};

// Legend
const legend: LegendConfig = {
  enabled: true,
  horizontalAlignment: 'CENTER',
  verticalAlignment: 'BOTTOM',
  orientation: 'HORIZONTAL',
  form: 'CIRCLE',
  textSize: 10,
};

Template ​

Standard Pie Chart ​

html
<PieChart
  #pieChart
  [data]="marketData"
  [animation]="animation"
  [legend]="legend"
  [drawHole]="false"
  [drawSliceText]="true"
  [usePercentValues]="true"
  [rotationEnabled]="true"
  [rotationAngle]="0"
  [highlightPerTapEnabled]="true"
  (select)="onSelect($event)"
  (deselect)="onDeselect()"
  class="h-80 w-full">
</PieChart>

Donut Chart ​

html
<PieChart
  [data]="marketData"
  [animation]="animation"
  [legend]="legend"
  [drawHole]="true"
  [holeRadius]="50"
  [transparentCircleRadius]="55"
  [holeColor]="'#FFFFFF'"
  [drawCenterText]="true"
  [centerText]="'Revenue\n$2.4M'"
  [centerTextColor]="'#374151'"
  [centerTextSize]="16"
  [usePercentValues]="true"
  class="h-80 w-full">
</PieChart>
tsx
import * as React from "react";
import { useState, useRef } from "react";
import type { PieChartData, ChartAnimation, LegendConfig, PieChart } from "@nstudio/ncharts";

export const PieChartDemo = () => {
  const pieChartRef = useRef<PieChart | null>(null);
  const [isDonut, setIsDonut] = useState(true);
  const [selectedData, setSelectedData] = useState(null);

  const marketData: PieChartData = {
    dataSets: [
      {
        label: 'Market Share',
        values: [
          { value: 35, label: 'Product A' },
          { value: 25, label: 'Product B' },
          { value: 20, label: 'Product C' },
          { value: 12, label: 'Product D' },
          { value: 8, label: 'Others' },
        ],
        config: {
          colors: ['#F59E0B', '#EF4444', '#8B5CF6', '#3B82F6', '#6B7280'],
          sliceSpace: 3,
          selectionShift: 8,
          drawValues: true,
          valueTextSize: 12,
          valueTextColor: '#FFFFFF',
        },
      },
    ],
  };

  return (
    <pieChart
      ref={pieChartRef}
      data={marketData}
      animation={{ durationX: 1400, durationY: 1400, easingX: 'EaseOutBounce' }}
      legend={{ enabled: true, horizontalAlignment: 'CENTER', verticalAlignment: 'BOTTOM' }}
      drawHole={isDonut}
      holeRadius={45}
      drawCenterText={isDonut}
      centerText="Total"
      usePercentValues={true}
      rotationEnabled={true}
      highlightPerTapEnabled={true}
      onSelect={(event) => setSelectedData(event.data)}
      onDeselect={() => setSelectedData(null)}
      className="h-80 w-full"
    />
  );
};
vue
<script lang="ts" setup>
import { ref, computed } from 'vue';
import type { PieChartData, ChartSelectEvent } from '@nstudio/ncharts';

const selectedValue = ref('');
const isDonut = ref(false);

const chartData: PieChartData = {
  dataSets: [
    {
      label: 'Sales by Product',
      values: [
        { value: 35, label: 'Product A' },
        { value: 25, label: 'Product B' },
        { value: 20, label: 'Product C' },
        { value: 12, label: 'Product D' },
        { value: 8, label: 'Other' },
      ],
      config: {
        colors: ['#3B82F6', '#10B981', '#F59E0B', '#EF4444', '#8B5CF6'],
        sliceSpace: 2,
        selectionShift: 8,
        drawValues: true,
        valueTextSize: 12,
        valueTextColor: '#FFFFFF',
      },
    },
  ],
};

function handleValueSelected(event: ChartSelectEvent) {
  if (event.data) {
    selectedValue.value = `Value: ${event.data.y?.toFixed(0)}%`;
  }
}
</script>

<template>
  <PieChart
    :data="chartData"
    :animation="{ durationX: 1400, durationY: 1400, easingX: 'EaseOutBounce' }"
    :legend="{ enabled: true }"
    :drawHole="isDonut"
    :holeRadius="50"
    :drawCenterText="isDonut"
    centerText="Total"
    :usePercentValues="true"
    :rotationEnabled="true"
    :highlightPerTapEnabled="true"
    @select="handleValueSelected"
    class="h-80 w-full"
  />
</template>
svelte
<script lang="ts">
  import type { PieChartData, ChartSelectData } from '@nstudio/ncharts';

  let selectedData: ChartSelectData | null = null;
  let isDonut = true;

  const marketData: PieChartData = {
    dataSets: [
      {
        label: 'Market Share',
        values: [
          { value: 35, label: 'Product A' },
          { value: 25, label: 'Product B' },
          { value: 20, label: 'Product C' },
          { value: 12, label: 'Product D' },
          { value: 8, label: 'Others' },
        ],
        config: {
          colors: ['#F59E0B', '#EF4444', '#8B5CF6', '#3B82F6', '#6B7280'],
          sliceSpace: 3,
          selectionShift: 8,
          drawValues: true,
          valueTextSize: 12,
          valueTextColor: '#FFFFFF',
        },
      },
    ],
  };

  const legendConfig = { enabled: true, horizontalAlignment: 'CENTER', verticalAlignment: 'BOTTOM' };
  const animationConfig = { durationX: 1400, durationY: 1400, easingX: 'EaseOutBounce' };

  function handleSelect(event: CustomEvent) {
    selectedData = event.detail.data;
  }
</script>

<pieChart
  data={marketData}
  animation={animationConfig}
  legend={legendConfig}
  drawHole={isDonut}
  holeRadius={45}
  drawCenterText={isDonut}
  centerText="Total"
  usePercentValues={true}
  rotationEnabled={true}
  highlightPerTapEnabled={true}
  on:select={handleSelect}
  on:deselect={() => selectedData = null}
  class="h-80 w-full"
/>
jsx
import { createSignal } from 'solid-js';

export const PieChartDemo = () => {
  let pieChartRef;
  const [isDonut, setIsDonut] = createSignal(true);
  const [selectedData, setSelectedData] = createSignal(null);

  const marketData = () => ({
    dataSets: [
      {
        label: 'Market Share',
        values: [
          { value: 35, label: 'Product A' },
          { value: 25, label: 'Product B' },
          { value: 20, label: 'Product C' },
          { value: 12, label: 'Product D' },
          { value: 8, label: 'Others' },
        ],
        config: {
          colors: ['#F59E0B', '#EF4444', '#8B5CF6', '#3B82F6', '#6B7280'],
          sliceSpace: 3,
          selectionShift: 8,
          drawValues: true,
          valueTextSize: 12,
          valueTextColor: '#FFFFFF',
        },
      },
    ],
  });

  const legendConfig = { enabled: true, horizontalAlignment: 'CENTER', verticalAlignment: 'BOTTOM' };
  const animationConfig = { durationX: 1400, durationY: 1400, easingX: 'EaseOutBounce' };

  return (
    <pieChart
      ref={pieChartRef}
      data={marketData()}
      animation={animationConfig}
      legend={legendConfig}
      drawHole={isDonut()}
      holeRadius={45}
      drawCenterText={isDonut()}
      centerText="Total"
      usePercentValues={true}
      rotationEnabled={true}
      highlightPerTapEnabled={true}
      onSelect={(event) => setSelectedData(event.data)}
      onDeselect={() => setSelectedData(null)}
      class="h-80 w-full"
    />
  );
};

Half Pie (Semi-circle) ​

html
<PieChart
  [data]="marketData"
  [maxAngle]="180"
  [rotationAngle]="180"
  [drawHole]="true"
  [holeRadius]="40"
  class="h-48 w-full">
</PieChart>
tsx
<pieChart
  data={marketData}
  maxAngle={180}
  rotationAngle={180}
  drawHole={true}
  holeRadius={40}
  className="h-48 w-full"
/>
vue
<PieChart
  :data="marketData"
  :maxAngle="180"
  :rotationAngle="180"
  :drawHole="true"
  :holeRadius="40"
  class="h-48 w-full"
/>
svelte
<pieChart
  data={marketData}
  maxAngle={180}
  rotationAngle={180}
  drawHole={true}
  holeRadius={40}
  class="h-48 w-full"
/>
jsx
<pieChart
  data={marketData()}
  maxAngle={180}
  rotationAngle={180}
  drawHole={true}
  holeRadius={40}
  class="h-48 w-full"
/>

Outside Labels Example ​

For charts with many small slices, place labels outside:

typescript
config: {
  colors: ['#3B82F6', '#10B981', '#F59E0B', '#8B5CF6', '#6B7280'],
  sliceSpace: 2,
  xValuePosition: 'OUTSIDE_SLICE',
  yValuePosition: 'OUTSIDE_SLICE',
  valueLinePart1Length: 0.4,
  valueLinePart2Length: 0.5,
  valueLineColor: '#9CA3AF',
  valueLineWidth: 1,
  valueLineVariableLength: true,
  drawValues: true,
  valueTextSize: 10,
  valueTextColor: '#374151',
}

Methods ​

MethodParametersDescription
animate()ChartAnimationTrigger chart animation
highlightValues()Highlight[]Programmatically highlight slices
clearHighlights()-Clear all highlights
spin()duration, degreesSpin the chart

Events ​

EventPayloadDescription
selectChartSelectEventFired when slice is tapped
deselect-Fired when selection is cleared

Programmatic Control ​

typescript
@ViewChild('pieChart') chartRef!: ElementRef;

// Spin animation
spinChart(): void {
  const chart = this.chartRef.nativeElement;
  this.rotationAngle += 90;
}

// Animate in
animateChart(): void {
  const chart = this.chartRef.nativeElement;
  chart.animate({ 
    durationX: 1400, 
    durationY: 1400, 
    easingX: 'EaseInOutCubic' 
  });
}

See Also ​