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}
/>

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