Skia Candlestick Chart for React Native Apps – kline-chart

Description:

react-native-kline-chart is a Skia-powered candlestick chart library that renders K-line data at 60fps in React Native applications.

It draws all candle geometry directly onto a Skia canvas via PictureRecorder and runs every gesture handler as a Reanimated worklet on the UI thread.

Features

  • Renders all candlestick bodies and wicks directly on a Skia canvas at 60 frames per second.
  • Runs pan, pinch-to-zoom, and long-press crosshair gestures entirely as UI thread worklets.
  • Viewport clipping limits drawing to the visible candle range, with full performance at 10,000+ entries.
  • Built-in moving average overlay with configurable period counts and per-line color assignments.
  • Long-press crosshair displays a synchronized info panel with open, high, low, close, and percentage change values.
  • Dashed last-price reference line marks the most recent closing value in real time.
  • High and low price markers appear at their exact positions on the chart canvas.
  • Configurable candle width, spacing, and zoom bounds for the pinch interaction.
  • Fully customizable color tokens for candle bodies, wicks, grid lines, axis labels, and background.
  • TypeScript type exports for candle data structures and chart prop interfaces.

Preview

skia-candlestick-chart-kline

Use Cases

  • Crypto trading apps get a jank-free candlestick view for high-frequency tick data feeds.
  • Stock analysis dashboards display months of daily OHLC bars in a single scrollable, zoomable chart.
  • Forex monitoring tools surface trend direction through the configurable moving average overlay.
  • Portfolio review screens support long-press crosshair inspection of exact historical price values.

How to Use It

1. Install react-native-kline-chart with NPM

npm install react-native-kline-chart

2. Install Peer Dependencies

npm install @shopify/react-native-skia react-native-reanimated react-native-gesture-handler

3. Open babel.config.js and add the plugin entry. After editing the config, run npx pod-install on iOS and rebuild the project.

// babel.config.js
module.exports = {
  plugins: ['react-native-reanimated/plugin'], // Required — Reanimated worklet compilation
};

4. Wrap the chart in GestureHandlerRootView at the root level.

import { KlineChart } from 'react-native-kline-chart';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
// Minimal OHLC dataset — each entry requires a millisecond timestamp
const priceData = [
  { time: 1715000000000, open: 62400, high: 63100, low: 62200, close: 62950 },
  { time: 1715003600000, open: 62950, high: 64000, low: 62800, close: 63750 },
  { time: 1715007200000, open: 63750, high: 63900, low: 62500, close: 62700 },
];
export default function App() {
  return (
    // GestureHandlerRootView must sit at the root for gesture recognition to work
    <GestureHandlerRootView style={{ flex: 1 }}>
      <KlineChart
        data={priceData}     // Array of Candle objects
        width={390}          // Canvas width in pixels
        height={500}         // Canvas height in pixels
        showMA               // Render moving average lines
        showCrosshair        // Enable long-press crosshair
      />
    </GestureHandlerRootView>
  );
}

5. This example reads the active candle from the crosshair and displays an OHLC header panel above the chart. The onCrosshairChange callback fires on every long-press move and returns null when the user lifts their finger.

import React, { useState, useCallback } from 'react';
import { View, Text, StyleSheet, useWindowDimensions } from 'react-native';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { KlineChart } from 'react-native-kline-chart';
import type { Candle } from 'react-native-kline-chart';
const priceData: Candle[] = [
  { time: 1715000000000, open: 62400, high: 63100, low: 62200, close: 62950 },
  { time: 1715003600000, open: 62950, high: 64000, low: 62800, close: 63750 },
  // ...additional candles
];
export default function TradingScreen() {
  const { width } = useWindowDimensions(); // Use device width for a responsive canvas
  const [selectedCandle, setSelectedCandle] = useState<Candle | null>(null);
  // Fires with the hovered Candle during long-press; null on finger lift
  const handleCrosshairChange = useCallback((candle: Candle | null) => {
    setSelectedCandle(candle);
  }, []);
  return (
    <GestureHandlerRootView style={styles.root}>
      {/* Render an OHLC header bar only while the crosshair is active */}
      {selectedCandle && (
        <View style={styles.infoBar}>
          <Text style={styles.label}>O: {selectedCandle.open}</Text>
          <Text style={styles.label}>H: {selectedCandle.high}</Text>
          <Text style={styles.label}>L: {selectedCandle.low}</Text>
          <Text style={styles.label}>C: {selectedCandle.close}</Text>
        </View>
      )}
      <KlineChart
        data={priceData}
        width={width}
        height={460}
        showMA                                          // Enable the MA overlay
        maPeriods={[5, 10, 30]}                         // Three MA periods
        maColors={['#F7931A', '#4A90D9', '#A855F7']}   // One color per period, in order
        showCrosshair
        onCrosshairChange={handleCrosshairChange}       // Fires on every crosshair move
        bullishColor="#26A69A"                          // Teal for bullish candles
        bearishColor="#EF5350"                          // Red for bearish candles
        backgroundColor="#131722"                       // Dark chart background
        gridColor="rgba(255, 255, 255, 0.08)"          // Subtle grid lines
        textColor="rgba(255, 255, 255, 0.4)"           // Dimmed axis labels
        crosshairColor="rgba(255, 255, 255, 0.25)"     // Crosshair line opacity
        rightPaddingCandles={15}                        // Right-side padding in candle widths
      />
    </GestureHandlerRootView>
  );
}
const styles = StyleSheet.create({
  root: { flex: 1, backgroundColor: '#131722' },
  infoBar: { flexDirection: 'row', gap: 16, paddingHorizontal: 16, paddingVertical: 10 },
  label: { color: '#D1D4DC', fontSize: 13, fontVariant: ['tabular-nums'] },
});

6. All component props.

  • data (Candle[]): The array of candle objects to render. Each entry requires time, open, high, low, and close. This prop is required.
  • width (number): The canvas width in pixels. This prop is required.
  • height (number): The canvas height in pixels. This prop is required.
  • candleWidth (number): The pixel width of each candle body. Defaults to 8.
  • candleSpacing (number): The pixel gap between adjacent candles. Defaults to 3.
  • minCandleWidth (number): The minimum candle width reachable by pinch-to-zoom. Defaults to 2.
  • maxCandleWidth (number): The maximum candle width reachable by pinch-to-zoom. Defaults to 24.
  • bullishColor (string): The fill color for bullish candles where close is greater than or equal to open. Defaults to '#2DC08E'.
  • bearishColor (string): The fill color for bearish candles. Defaults to '#F6465D'.
  • showMA (boolean): Renders moving average lines on the chart when set to true. Defaults to true.
  • maPeriods (number[]): An array of period values for the MA calculation. Defaults to [5, 10].
  • maColors (string[]): An array of hex or rgba color strings applied to MA lines in index order. Defaults to ['#F7931A', '#5B8DEF', '#C084FC'].
  • showCrosshair (boolean): Activates the long-press crosshair interaction. Defaults to true.
  • backgroundColor (string): The chart canvas background color. Defaults to '#0B0E11'.
  • gridColor (string): The color applied to horizontal and vertical grid lines. Defaults to 'rgba(255,255,255,0.2)'.
  • textColor (string): The color of axis tick labels. Defaults to 'rgba(255,255,255,0.35)'.
  • crosshairColor (string): The color of the crosshair line. Defaults to 'rgba(255,255,255,0.3)'.
  • rightPaddingCandles (number): The right-side canvas padding expressed in candle widths. Defaults to 20.
  • onCrosshairChange ((candle: Candle | null) => void): A callback that fires whenever the crosshair moves. Receives the hovered Candle object, or null when the user lifts their finger.

Alternatives

  • react-native-gifted-charts: A feature-rich React Native chart library covering bar, line, pie, and candlestick chart types.
  • react-native-wagmi-charts: A gesture-driven charting library built for crypto and DeFi apps, with candlestick and line chart support.

Add Comment