diff --git a/README.md b/README.md index 1063e34..acd927d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,3 @@ - @@ -15,20 +14,21 @@ - Beautiful, high-performance Graphs/Charts for React Native. +Beautiful, high-performance Graphs/Charts for React Native. + ## About **react-native-graph** is a Line Graph implementation based on the high performance 2D graphics rendering engine "Skia". It's used in the [Pink Panda Wallet app](https://pinkpanda.io) to power thousands of token graphs every day. -* 🏎️ Faster and smoother than react-native-svg graphs -* ⚡️ Native path interpolation in Skia -* 🐎 Up to 120 FPS animations -* 📈 Cubic bezier rendering for smoother edges -* 👍 Smooth pan/scrubbing gesture -* 💰 Made for crypto apps and Wallets -* ❌ Does not block navigation, press or scroll animations +- 🏎️ Faster and smoother than react-native-svg graphs +- ⚡️ Native path interpolation in Skia +- 🐎 Up to 120 FPS animations +- 📈 Cubic bezier rendering for smoother edges +- 👍 Smooth pan/scrubbing gesture +- 💰 Made for crypto apps and Wallets +- ❌ Does not block navigation, press or scroll animations ## Installation @@ -41,34 +41,82 @@ yarn add react-native-graph ## Usage -```jsx -function App() { - const priceHistory = usePriceHistory('ethereum') +```tsx +import { LineGraph } from 'react-native-graph'; - return +function App() { + const priceHistory = usePriceHistory('ethereum'); + + return ( + + ); } ``` ## Configuration +`LineGraph` accepts the following props. It also accepts React Native [`ViewProps`](https://reactnative.dev/docs/view#props), which are forwarded to the root view. + +| Prop | Type | Default | Availability | Description | +| ------------------------- | ------------------------------------------ | -------------------------------------------------- | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------- | +| `animated` | `boolean` | `false` | Always | Uses the animated renderer when `true` and the lightweight static renderer when `false`. | +| `points` | `GraphPoint[]` | None. Required. | Always | The points to draw. Each point contains a numeric `value` and a `Date`. The graph scales to fit them unless `range` overrides an axis. | +| `color` | `string` | None. Required. | Always | The graph line color. | +| `range` | `GraphRange` | `undefined`. Both axes are inferred from `points`. | Always | Overrides all or part of the visible x-axis and y-axis ranges. | +| `gradientFillColors` | `Color[]` | `undefined`. No area fill is drawn. | `animated={true}` | Colors for the vertical gradient below the graph line. | +| `lineThickness` | `number` | `3` | Always | The graph line width in points. | +| `enableFadeInMask` | `boolean` | `false` | Always | Fades in the start of the graph line. | +| `enablePanGesture` | `boolean` | `false` | `animated={true}` | Lets the user press and scrub through graph points. | +| `panGestureDelay` | `number` | `300` | `animated={true}` | Time in milliseconds that a press must be held before scrubbing starts. Set it to `0` to start immediately. | +| `onGestureStart` | `() => void` | `undefined`. No callback runs. | `animated={true}` | Called when scrubbing starts. | +| `onPointSelected` | `(point: GraphPoint) => void` | `undefined`. No callback runs. | `animated={true}` | Called when scrubbing reaches a different point. | +| `onGestureEnd` | `() => void` | `undefined`. No callback runs. | `animated={true}` | Called when scrubbing ends. | +| `SelectionDot` | `ComponentType \| null` | Built-in `SelectionDot` | `animated={true}` | Renders the current scrub position. Pass `null` to hide it. | +| `selectionDotShadowColor` | `string` | `undefined` | `animated={true}` | Currently unused. This prop has no visual effect. | +| `horizontalPadding` | `number` | `10` when the indicator is enabled, otherwise `0` | `animated={true}` | Adds space to both horizontal edges of the drawing area. | +| `verticalPadding` | `number` | The value of `lineThickness` | `animated={true}` | Adds space to both vertical edges of the drawing area. | +| `enableIndicator` | `boolean` | `false` | `animated={true}` | Shows an indicator at the last graph point. | +| `indicatorPulsating` | `boolean` | `false` | `animated={true}` | Pulses the indicator while the graph is idle. Requires `enableIndicator`. | +| `TopAxisLabel` | `() => ReactElement \| null` | `undefined`. Nothing is rendered. | `animated={true}` | Renders a label above the graph. | +| `BottomAxisLabel` | `() => ReactElement \| null` | `undefined`. Nothing is rendered. | `animated={true}` | Renders a label below the graph. | + +### Data types + +```ts +interface GraphPoint { + value: number; + date: Date; +} + +interface GraphRange { + x?: { min: Date; max: Date }; + y?: { min: number; max: number }; +} +``` + +You can provide either axis in `range` and let the graph infer the other one from `points`. + +## Prop examples + ### `animated` Whether to animate between data changes. Defaults to `false` when omitted. -Animations are ran using the [Skia animation system](https://shopify.github.io/react-native-skia/docs/animations/animations) and are fully natively interpolated to ensure best possible performance. +Animations run using the [Skia animation system](https://shopify.github.io/react-native-skia/docs/animations/animations), with path interpolation handled on the UI thread. -If `animated` is `false`, a light-weight implementation of the graph renderer will be used, which is optimal for displaying a lot of graphs in large lists. +If `animated` is `false`, the graph uses a lightweight static renderer. This is useful when displaying many graphs in a list. Example: ```jsx - + ``` --- @@ -77,19 +125,19 @@ Example: -Whether to enable the pan gesture. +Whether to enable the pan gesture. Defaults to `false`. -> Requires `animated` to be `true`. +> Requires `animated` to be `true`. There are three events fired when the user interacts with the graph: -1. `onGestureStart`: Fired once the user presses and holds down on the graph. The pan gesture _activates_. -2. `onPointSelected`: Fired for each point the user pans through. You can use this event to update labels or highlight selection in the graph. -3. `onGestureEnd`: Fired once the user releases his finger and the pan gesture _deactivates_. +1. `onGestureStart`: Fires once the user presses and holds the graph. The pan gesture activates. +2. `onPointSelected`: Fires for each point the user pans through. Use it to update a label or highlight the selected value. +3. `onGestureEnd`: Fires once the user releases the graph. The pan gesture deactivates. The pan gesture can be configured using these props: -1. `panGestureDelay`: Set delay for the pan gesture to activate. Set to `0` to start immediately after touch. Defaults to `300`. +- `panGestureDelay` controls how long the user must hold before the gesture activates. It defaults to `300` milliseconds. Set it to `0` to start immediately. Example: @@ -111,11 +159,11 @@ Example: -Used to render labels above or below the Graph. +Renders labels above or below the graph. Both props default to `undefined`, so no labels are rendered. -> Requires `animated` to be `true`. +> Requires `animated` to be `true`. -Usually this is used to render the maximum and minimum values of the Graph. You can get the maximum and minimum values from your graph points array, and smoothly animate the labels on the X axis accordingly. +These labels usually show the maximum and minimum values. You can derive those values and their positions from the graph points. Example: @@ -129,18 +177,18 @@ Example: /> ``` -### `Range` +### `range` -Used to define a range for the graph canvas +Defines the visible range of the graph canvas. It defaults to `undefined`, which infers both axes from `points`. -This range has to be bigger than the span of the provided data points. This feature can be used, e.g. if the graph should show a fixed timeframe, whether there's data for that period or not. +Use a custom range to show a fixed time frame or value scale, even when the data does not cover the whole range. Points outside the x-axis range are not drawn.

-This example shows data in the timeframe between 01/01/2000 to 01/31/2000 and caps the value between 0 and 200: +This example shows January 2000 and sets the y-axis range to 0 through 200: ```jsx ``` @@ -170,11 +215,19 @@ This example shows data in the timeframe between 01/01/2000 to 01/31/2000 and ca -Used to render the selection dot. +Renders the selection dot. It defaults to the built-in `SelectionDot`. Pass `null` to hide it. + +> Requires `animated` and `enablePanGesture` to be `true`. -> Requires `animated` and `enablePanGesture` to be `true`. +A custom selection-dot component receives these props from `LineGraph`. They are all required and have no defaults when you render `SelectionDot` directly. -If `SelectionDot` is missing or `undefined`, a default one is provided with an outer ring and light shadow. +| Prop | Type | Default | Description | +| --------------- | ---------------------- | --------------- | ----------------------------------------------------------- | +| `isActive` | `SharedValue` | None. Required. | Whether the pan gesture is active. | +| `color` | `string` | None. Required. | The graph line color. | +| `lineThickness` | `number \| undefined` | None. Required. | The resolved graph line width when supplied by `LineGraph`. | +| `circleX` | `SharedValue` | None. Required. | The selected point's x-coordinate. | +| `circleY` | `SharedValue` | None. Required. | The selected point's y-coordinate. | Example: