diff --git a/.changeset/great-dogs-collect.md b/.changeset/great-dogs-collect.md new file mode 100644 index 00000000..29307ae7 --- /dev/null +++ b/.changeset/great-dogs-collect.md @@ -0,0 +1,5 @@ +--- +"victory-native": minor +--- + +Add option to have axis images instead of ticks diff --git a/.gitignore b/.gitignore index 14481b47..878bbee9 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,5 @@ yarn-error.* *.tsbuildinfo .expo/README.md .expo/devices.json + +.github/copilot-instructions.md \ No newline at end of file diff --git a/example/app/axis-images.tsx b/example/app/axis-images.tsx new file mode 100644 index 00000000..550ef432 --- /dev/null +++ b/example/app/axis-images.tsx @@ -0,0 +1,375 @@ +import React, { useCallback, useState } from "react"; +import { SafeAreaView, ScrollView, StyleSheet, View } from "react-native"; +import { + DashPathEffect, + useFont, + useImage, + Image, + Skia, + Paragraph, + TileMode, + Text as SkiaText, + type ImageProps, + type SkImage, +} from "@shopify/react-native-skia"; +import { CartesianChart, Line } from "victory-native"; +import { Text } from "example/components/Text"; +import inter from "../assets/inter-medium.ttf"; +import { appColors } from "../consts/colors"; + +const DATA = [ + { temperature: 10, day: 1 }, + { temperature: 20, day: 2 }, + { temperature: 30, day: 3 }, + { temperature: 20, day: 4 }, + { temperature: 60, day: 5 }, + { temperature: 15, day: 6 }, +]; + +export type TickImage = Partial> & { + image?: string; + skImage?: SkImage | null; + width?: number; + height?: number; +}; + +type AxisImageProps = TickImage & { + y: number; + x: number; +}; + +export const AxisImage: React.FC = ({ + image, + skImage, + y, + x, + ...rest +}) => { + const imageSKFromHook = useImage(image || ""); + const imageSK = skImage || imageSKFromHook; + + return ( + + ); +}; + +const ChartWithRemoteImages = () => { + const font = useFont(inter, 12); + const [data] = useState(DATA); + const images = [ + "https://picsum.photos/32/32", + "https://picsum.photos/32/32", + "https://picsum.photos/32/32", + ]; + + return ( + + , + }} + yAxis={[ + { + tickValues: [15, 50, 80], + renderYLabel: ({ x, y, index }) => { + return ( + + ); + }, + labelOffset: 12, + font, + linePathEffect: , + }, + ]} + > + {({ points }) => { + return ( + + ); + }} + + + ); +}; + +const ChartWithLocalImages = () => { + const font = useFont(inter, 12); + const [data] = useState(DATA); + + const warmImage = useImage(require("../assets/warm.png")); + const medImage = useImage(require("../assets/med.png")); + const coldImage = useImage(require("../assets/cold.png")); + const images = [coldImage, medImage, warmImage]; + + return ( + + , + renderXLabel: ({ x, y, content, canFitContent }) => { + if (!canFitContent) { + return null; + } + + return ( + + ); + }, + }} + yAxis={[ + { + tickValues: [15, 50, 80], + renderYLabel: ({ x, y, index }) => { + return ( + + ); + }, + labelOffset: 12, + font, + linePathEffect: , + }, + ]} + > + {({ points }) => { + return ( + + ); + }} + + + ); +}; + +// copied from https://shopify.github.io/react-native-skia/docs/text/paragraph/ +const source = Skia.RuntimeEffect.Make(` + uniform vec4 position; + uniform vec4 colors[4]; + + vec4 main(vec2 pos) { + vec2 uv = (pos - vec2(position.x, position.y))/vec2(position.z, position.w); + vec4 colorA = mix(colors[0], colors[1], uv.x); + vec4 colorB = mix(colors[2], colors[3], uv.x); + return mix(colorA, colorB, uv.y); + }`)!; + +const colors = [ + // #dafb61 + 0.85, 0.98, 0.38, 1.0, + // #61dafb + 0.38, 0.85, 0.98, 1.0, + // #fb61da + 0.98, 0.38, 0.85, 1.0, + // #61fbcf + 0.38, 0.98, 0.81, 1.0, +]; + +const ChartWithRenderCustomYLabel = () => { + const font = useFont(inter, 12); + const [data] = useState(DATA); + + const warmImage = useImage(require("../assets/warm.png")); + const medImage = useImage(require("../assets/med.png")); + const coldImage = useImage(require("../assets/cold.png")); + + const images = [coldImage, medImage, warmImage]; + const paragraphMaker = useCallback((t: string) => { + // Create a background paint. + const backgroundPaint = Skia.Paint(); + backgroundPaint.setShader(source.makeShader([0, 0, 256, 256, ...colors])); + + // Create a foreground paint. We use a radial gradient. + const foregroundPaint = Skia.Paint(); + foregroundPaint.setShader( + Skia.Shader.MakeRadialGradient( + { x: 0, y: 0 }, + 256, + [Skia.Color("magenta"), Skia.Color("yellow")], + null, + TileMode.Clamp, + ), + ); + + const para = Skia.ParagraphBuilder.Make() + .pushStyle( + { + fontFamilies: ["Roboto"], + fontSize: 12, + fontStyle: { weight: 500 }, + color: Skia.Color("black"), + }, + foregroundPaint, + backgroundPaint, + ) + .addText(`Label ${t}\nSkia`) + .pop() + .build(); + return para; + }, []); + + return ( + + , + renderXLabel: ({ x, y, content, canFitContent }) => { + if (!canFitContent) { + return null; + } + + return ( + + ); + }, + }} + yAxis={[ + { + tickValues: [15, 50, 80], + renderYLabel: ({ x, y, index }) => { + return ( + + ); + }, + labelOffset: 12, + font, + linePathEffect: , + }, + ]} + > + {({ points }) => { + return ( + + ); + }} + + + ); +}; + +export default function AxisIconsChartPage() { + return ( + <> + + + + + Chart with local images as tick values on the Y axis + + + + + + Chart using renderYLabel and renderXLabel for full customization + + + + + + Chart with remote images as tick values on the Y axis + + + + + + + ); +} + +const styles = StyleSheet.create({ + safeView: { + flex: 1, + backgroundColor: appColors.viewBackground.light, + $dark: { + backgroundColor: appColors.viewBackground.dark, + }, + }, + chartContainer: { + height: 400, + padding: 25, + borderBottomWidth: 1, + borderBottomColor: appColors.cardBorder.light, + $dark: { + borderBottomColor: appColors.cardBorder.dark, + }, + }, + title: { marginBottom: 10, fontSize: 16, fontWeight: "bold" }, +}); diff --git a/example/assets/cold.png b/example/assets/cold.png new file mode 100644 index 00000000..7ca5e2a1 Binary files /dev/null and b/example/assets/cold.png differ diff --git a/example/assets/med.png b/example/assets/med.png new file mode 100644 index 00000000..4c6198f7 Binary files /dev/null and b/example/assets/med.png differ diff --git a/example/assets/warm.png b/example/assets/warm.png new file mode 100644 index 00000000..f23b1f6a Binary files /dev/null and b/example/assets/warm.png differ diff --git a/example/consts/routes.ts b/example/consts/routes.ts index abbbb900..2fab77de 100644 --- a/example/consts/routes.ts +++ b/example/consts/routes.ts @@ -148,6 +148,11 @@ export const ChartRoutes: { description: "Show example of scrolling chart data.", path: "/scroll", }, + { + title: "Axis Images", + description: "Show example of using images as tick labels.", + path: "/axis-images", + }, ]; if (__DEV__) { diff --git a/lib/src/cartesian/components/XAxis.tsx b/lib/src/cartesian/components/XAxis.tsx index 6d834722..df468f03 100644 --- a/lib/src/cartesian/components/XAxis.tsx +++ b/lib/src/cartesian/components/XAxis.tsx @@ -42,6 +42,7 @@ export const XAxis = < chartBounds, enableRescaling, zoom, + renderXLabel, }: XAxisProps) => { const xScale = zoom ? zoom.rescaleX(xScaleProp) : xScaleProp; const [y1 = 0, y2 = 0] = yScale.domain(); @@ -52,7 +53,7 @@ export const XAxis = < ? xScale.ticks(tickCount) : xScaleProp.ticks(tickCount); - const xAxisNodes = xTicksNormalized.map((tick) => { + const xAxisNodes = xTicksNormalized.map((tick, index) => { const p1 = vec(xScale(tick), yScale(y2)); const p2 = vec(xScale(tick), yScale(y1)); @@ -137,23 +138,35 @@ export const XAxis = < ) : null} - {font && labelWidth && canFitLabelContent ? ( - - - - ) : null} + {renderXLabel ? ( + renderXLabel({ + x: labelX, + y: labelY, + content: contentX, + canFitContent: canFitLabelContent, + index: index, + }) + ) : ( + <> + {font && labelWidth && canFitLabelContent ? ( + + + + ) : null} + + )} <> ); diff --git a/lib/src/cartesian/components/YAxis.tsx b/lib/src/cartesian/components/YAxis.tsx index 478f6f02..244b684a 100644 --- a/lib/src/cartesian/components/YAxis.tsx +++ b/lib/src/cartesian/components/YAxis.tsx @@ -27,11 +27,13 @@ export const YAxis = < formatYLabel = (label: ValueOf) => String(label), linePathEffect, chartBounds, + renderYLabel, }: YAxisProps) => { const [x1 = 0, x2 = 0] = xScale.domain(); const [_ = 0, y2 = 0] = yScale.domain(); const fontSize = font?.getSize() ?? 0; - const yAxisNodes = yTicksNormalized.map((tick) => { + + const yAxisNodes = yTicksNormalized.map((tick, index) => { const contentY = formatYLabel(tick as never); const labelWidth = font @@ -71,8 +73,17 @@ export const YAxis = < ) : null} - {font - ? canFitLabelContent && ( + {renderYLabel ? ( + renderYLabel({ + x: labelX, + y: labelY, + content: contentY, + canFitContent: canFitLabelContent, + index: index, + }) + ) : ( + <> + {font && canFitLabelContent && ( - ) - : null} + )} + + )} ); }); diff --git a/lib/src/types.ts b/lib/src/types.ts index 9f2339df..cbbe6ee9 100644 --- a/lib/src/types.ts +++ b/lib/src/types.ts @@ -188,6 +188,7 @@ export type XAxisInputProps< yAxisSide?: YAxisSide; linePathEffect?: DashPathEffectComponent; enableRescaling?: boolean; + renderXLabel?: (opts: RenderAxisLabelProps) => React.ReactNode; }; export type XAxisPropsWithDefaults< @@ -196,7 +197,12 @@ export type XAxisPropsWithDefaults< > = Required< Omit< XAxisInputProps, - "font" | "tickValues" | "linePathEffect" | "enableRescaling" | "labelRotate" + | "font" + | "tickValues" + | "linePathEffect" + | "enableRescaling" + | "labelRotate" + | "renderXLabel" > > & Partial< @@ -207,6 +213,7 @@ export type XAxisPropsWithDefaults< | "linePathEffect" | "enableRescaling" | "labelRotate" + | "renderXLabel" > >; @@ -222,6 +229,14 @@ export type XAxisProps< zoom?: ZoomTransform; }; +type RenderAxisLabelProps = { + x: number; + y: number; + index: number; + content: string; + canFitContent: boolean; +}; + export type YAxisInputProps< RawData extends Record, YK extends keyof NumericalFields, @@ -229,6 +244,7 @@ export type YAxisInputProps< axisSide?: YAxisSide; font?: SkFont | null; formatYLabel?: (label: RawData[YK]) => string; + renderYLabel?: (opts: RenderAxisLabelProps) => React.ReactNode; labelColor?: string; labelOffset?: number; labelPosition?: AxisLabelPosition; @@ -248,13 +264,21 @@ export type YAxisPropsWithDefaults< > = Required< Omit< YAxisInputProps, - "font" | "tickValues" | "linePathEffect" | "enableRescaling" + | "font" + | "tickValues" + | "linePathEffect" + | "enableRescaling" + | "renderYLabel" > > & Partial< Pick< YAxisInputProps, - "font" | "tickValues" | "linePathEffect" | "enableRescaling" + | "font" + | "tickValues" + | "linePathEffect" + | "enableRescaling" + | "renderYLabel" > >; diff --git a/website/docs/cartesian/cartesian-chart.md b/website/docs/cartesian/cartesian-chart.md index 1353bfb2..52792c3a 100644 --- a/website/docs/cartesian/cartesian-chart.md +++ b/website/docs/cartesian/cartesian-chart.md @@ -132,42 +132,44 @@ The `axisOptions` is an optional prop allows you to configure the axes and grid The `xAxis` is an optional prop allows you to configure the X axis of the chart. If it is not present then the chart will not render any X axis. It is an object of the following properties: -| Property | Type | Description | -| :-------------------: | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| **`font`** |
SkFont | null
| Defines the font to be used for X axis labels. If not provided, then no labels will be rendered. This font object is typically returned from Skia’s `useFont` hook. | -| **`tickCount`** |
number
| Defines the number of ticks to be rendered on the X axis. If not provided, then the chart will attempt to choose a reasonable number of ticks based on the size of the chart.

Note: This is an approximation; the scale may return more or fewer values depending on the domain, padding, and axis labels. | -| **`tickValues`** |
[number]
| Defines the explicit set of numeric tick values to be rendered on the X axis. The tickValues prop is used to specify the values of each tick, so we only accept numeric values. Use the `formatXLabel` or `formatYLabel` options to customize how the ticks should be labeled.

Note: If `tickCount` value is also provided, it will be used to downsample the provided `tickValues` array to the specified length. | -| **`lineColor`** |
Color (RN Skia Color)
| Defines the color of the X axis lines. It will default to `hsla(0, 0%, 0%, 0.25)` if none is provided. | -| **`lineWidth`** |
number
| Defines the width of the X axis lines. It will default to `Stylesheet.hairlineWidth` if none is provided. A value of `0` will disable the line rendering. | -| **`labelColor`** |
string
| Defines the color of the X axis label. It will default to `#000000 (black)` if none is provided. | -| **`labelOffset`** |
number
| Defines the offset of the axis label. It will default to `2` if none is provided. | -| **`labelPosition`** |
AxisLabelPosition;
| Defines the position of the x-axis labels. It will default to `outset` if none is provided.

ⓘ **`AxisLabelPosition`** is an enum with the values: 'inset | 'outset'. | -| **`labelRotate`** |
number;
| Defines the angle of rotation for the X axis labels. It will default to 0. Note: The origin of rotation defaults to the center of the label. | -| **`axisSide`** |
XAxisSide
| Defines the side of the chart that the `X` axis is rendered on. It will default to `bottom` if none is provided.

ⓘ **`XAxisSide`** is an enum with the values: 'top' | 'bottom'.
| -| **`formatXLabel`** |
(label: T[XK]) => string
| Defines a function provide customization for formatting the X axis labels. It will default to just returning the value as a string if no function is provided. | -| **`linePathEffect`** |
`DashPathEffect`
| Currently accepts the `` from `react-native-skia` so one can add dashes to their axis lines. In the future this prop may accept other line path effects as well. | -| **`enableRescaling`** |
boolean
| When `true`, allows the axis ticks to be rescaled during pan/zoom transformations. When `false`, the ticks will remain fixed at their initial values regardless of zoom level. Defaults to `false`. | +| Property | Type | Description | +| :-------------------: | ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| **`font`** |
SkFont | null
| Defines the font to be used for X axis labels. If not provided, then no labels will be rendered. This font object is typically returned from Skia’s `useFont` hook. | +| **`tickCount`** |
number
| Defines the number of ticks to be rendered on the X axis. If not provided, then the chart will attempt to choose a reasonable number of ticks based on the size of the chart.

Note: This is an approximation; the scale may return more or fewer values depending on the domain, padding, and axis labels. | +| **`tickValues`** |
[number]
| Defines the explicit set of numeric tick values to be rendered on the X axis. The tickValues prop is used to specify the values of each tick, so we only accept numeric values. Use the `formatXLabel` or `formatYLabel` options to customize how the ticks should be labeled.

Note: If `tickCount` value is also provided, it will be used to downsample the provided `tickValues` array to the specified length. | +| **`lineColor`** |
Color (RN Skia Color)
| Defines the color of the X axis lines. It will default to `hsla(0, 0%, 0%, 0.25)` if none is provided. | +| **`lineWidth`** |
number
| Defines the width of the X axis lines. It will default to `Stylesheet.hairlineWidth` if none is provided. A value of `0` will disable the line rendering. | +| **`labelColor`** |
string
| Defines the color of the X axis label. It will default to `#000000 (black)` if none is provided. | +| **`labelOffset`** |
number
| Defines the offset of the axis label. It will default to `2` if none is provided. | +| **`labelPosition`** |
AxisLabelPosition;
| Defines the position of the x-axis labels. It will default to `outset` if none is provided.

ⓘ **`AxisLabelPosition`** is an enum with the values: 'inset | 'outset'. | +| **`labelRotate`** |
number;
| Defines the angle of rotation for the X axis labels. It will default to 0. Note: The origin of rotation defaults to the center of the label. | +| **`axisSide`** |
XAxisSide
| Defines the side of the chart that the `X` axis is rendered on. It will default to `bottom` if none is provided.

ⓘ **`XAxisSide`** is an enum with the values: 'top' | 'bottom'.
| +| **`formatXLabel`** |
(label: T[XK]) => string
| Defines a function provide customization for formatting the X axis labels. It will default to just returning the value as a string if no function is provided. | +| **`linePathEffect`** |
`DashPathEffect`
| Currently accepts the `` from `react-native-skia` so one can add dashes to their axis lines. In the future this prop may accept other line path effects as well. | +| **`enableRescaling`** |
boolean
| When `true`, allows the axis ticks to be rescaled during pan/zoom transformations. When `false`, the ticks will remain fixed at their initial values regardless of zoom level. Defaults to `false`. | +| **`renderXLabel?`** | `(opts: { x: number; y: number; content: string; canFitContent: boolean; index: number }) => React.ReactNode` | Optional render prop to customize axis labels. Can return any Skia component (Text, Image, Paragraph etc). Receives position coordinates, label content, fit status and index. See the example app for more details | ### `yAxis` The `yAxis` is an optional prop allows you to configure the **Y axes** of the chart. If it is not present then the chart will not render any Y-axis. To render multiple Y axes, pass in multiple Y axis objects to the array. It is an array of objects with the following properties: -| Property | Type | Description | -| :---------------------: | ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **`yKeys` (optional)** |
YK[]
| A `string[]` array of strings indicating the _keys_ of each `data[number]` object to be used on the dependent (y) axis for charting. Each yAxis object needs to specify which Y data keys it corresponds to. If only one object is passed, then this defaults to the existing yKeys and so remains optional, but you must specify it if you want to have multiple y axes, since the axis must know which data it corresponds to! | -| **`font`** |
SkFont | null
| Defines the font to be used for x axis labels. If not provided, then no labels will be rendered. This font object is typically returned from Skia’s `useFont` hook. | -| **`tickCount`** |
number
| Defines the number of ticks to be rendered on the Y axis. If not provided, then the chart will attempt to choose a reasonable number of ticks based on the size of the chart.

Note: This is an approximation; the scale may return more or fewer values depending on the domain, padding, and axis labels. | -| **`tickValues`** |
[number]
| Defines the explicit set of numeric tick values to be rendered on the Y axis. The tickValues prop is used to specify the values of each tick, so we only accept numeric values. Use the `formatXLabel` or `formatYLabel` options to customize how the ticks should be labeled.

Note: If `tickCount` value is also provided, it will be used to downsample the provided `tickValues` array to the specified length. | -| **`lineColor`** |
Color (RN Skia Color)
| Defines the color of the x axis lines. It will default to `hsla(0, 0%, 0%, 0.25)` if none is provided. | -| **`lineWidth`** |
number
| Defines the width of the Y axis lines. It will default to `Stylesheet.hairlineWidth` if none is provided. A value of `0` will disable the line rendering. | -| **`labelColor`** |
string
| Defines the color of the Y axis label. It will default to `#000000 (black)` if none is provided. | -| **`labelOffset`** |
number
| Defines the offset of the axis label. It will default to `4` if none is provided. | -| **`labelPosition`** |
AxisLabelPosition;
| Defines the position of the Y-axis labels. It will default to `outset` if none is provided.

ⓘ **`AxisLabelPosition`** is an enum with the values: 'inset | 'outset'. | -| **`axisSide`** |
YAxisSide
| Defines the side of the chart that the `Y` axis is rendered on. It will default to `left` if none is provided.

ⓘ **`YAxisSide`** is an enum with the values: 'left' | 'right'.
| -| **`formatYLabel`** |
(label: T[YK]) => string
| Defines a function provide customization for formatting the Y-axis labels. It will default to just returning the value as a string if no function is provided. | -| **`domain` (optional)** |
[number] | [number, number]
| Defines the domain for the Y-axis that can be specified to control the upper and lower bounds of the Y-axis. It defaults to the min and max of the range. | -| **`linePathEffect`** |
`DashPathEffect`
| Currently accepts the `` from `react-native-skia` so one can add dashes to their axis lines. In the future this prop may accept other line path effects as well. | -| **`enableRescaling`** |
boolean
| When `true`, allows the axis ticks to be rescaled during pan/zoom transformations. When `false`, the ticks will remain fixed at their initial values regardless of zoom level. Defaults to `false`. | +| Property | Type | Description | +| :---------------------: | ------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **`yKeys` (optional)** |
YK[]
| A `string[]` array of strings indicating the _keys_ of each `data[number]` object to be used on the dependent (y) axis for charting. Each yAxis object needs to specify which Y data keys it corresponds to. If only one object is passed, then this defaults to the existing yKeys and so remains optional, but you must specify it if you want to have multiple y axes, since the axis must know which data it corresponds to! | +| **`font`** |
SkFont | null
| Defines the font to be used for x axis labels. If not provided, then no labels will be rendered. This font object is typically returned from Skia’s `useFont` hook. | +| **`tickCount`** |
number
| Defines the number of ticks to be rendered on the Y axis. If not provided, then the chart will attempt to choose a reasonable number of ticks based on the size of the chart.

Note: This is an approximation; the scale may return more or fewer values depending on the domain, padding, and axis labels. | +| **`tickValues`** |
[number]
| Defines the explicit set of numeric tick values to be rendered on the Y axis. The tickValues prop is used to specify the values of each tick, so we only accept numeric values. Use the `formatXLabel` or `formatYLabel` options to customize how the ticks should be labeled.

Note: If `tickCount` value is also provided, it will be used to downsample the provided `tickValues` array to the specified length. | +| **`lineColor`** |
Color (RN Skia Color)
| Defines the color of the x axis lines. It will default to `hsla(0, 0%, 0%, 0.25)` if none is provided. | +| **`lineWidth`** |
number
| Defines the width of the Y axis lines. It will default to `Stylesheet.hairlineWidth` if none is provided. A value of `0` will disable the line rendering. | +| **`labelColor`** |
string
| Defines the color of the Y axis label. It will default to `#000000 (black)` if none is provided. | +| **`labelOffset`** |
number
| Defines the offset of the axis label. It will default to `4` if none is provided. | +| **`labelPosition`** |
AxisLabelPosition;
| Defines the position of the Y-axis labels. It will default to `outset` if none is provided.

ⓘ **`AxisLabelPosition`** is an enum with the values: 'inset | 'outset'. | +| **`axisSide`** |
YAxisSide
| Defines the side of the chart that the `Y` axis is rendered on. It will default to `left` if none is provided.

ⓘ **`YAxisSide`** is an enum with the values: 'left' | 'right'.
| +| **`formatYLabel`** |
(label: T[YK]) => string
| Defines a function provide customization for formatting the Y-axis labels. It will default to just returning the value as a string if no function is provided. | +| **`domain` (optional)** |
[number] | [number, number]
| Defines the domain for the Y-axis that can be specified to control the upper and lower bounds of the Y-axis. It defaults to the min and max of the range. | +| **`linePathEffect`** |
`DashPathEffect`
| Currently accepts the `` from `react-native-skia` so one can add dashes to their axis lines. In the future this prop may accept other line path effects as well. | +| **`enableRescaling`** |
boolean
| When `true`, allows the axis ticks to be rescaled during pan/zoom transformations. When `false`, the ticks will remain fixed at their initial values regardless of zoom level. Defaults to `false`. | +| **`renderYLabel?`** | `(opts: { x: number; y: number; content: string; canFitContent: boolean; index: number }) => React.ReactNode` | Optional render prop to customize axis labels. Can return any Skia component (Text, Image, Paragraph etc). Receives position coordinates, label content, fit status and index. See the example app for more details. | ### `frame`