Skip to content

Commit

Permalink
[experiment]: renderXLabel and renderYLabel
Browse files Browse the repository at this point in the history
  • Loading branch information
zibs committed Jan 9, 2025
1 parent e846c4b commit 7a90e4b
Show file tree
Hide file tree
Showing 4 changed files with 230 additions and 26 deletions.
157 changes: 155 additions & 2 deletions example/app/axis-images.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import React, { useState } from "react";
import React, { useCallback, useState } from "react";
import { SafeAreaView, ScrollView, StyleSheet, View } from "react-native";
import { DashPathEffect, useFont, useImage } from "@shopify/react-native-skia";
import {
DashPathEffect,
useFont,
useImage,
Image,
Skia,
Paragraph,
TileMode,
} from "@shopify/react-native-skia";
import { CartesianChart, Line } from "victory-native";
import { Text } from "example/components/Text";
import inter from "../assets/inter-medium.ttf";
Expand Down Expand Up @@ -113,6 +121,145 @@ const ChartWithLocalImages = () => {
);
};

// 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 (
<View style={{ flex: 1 }}>
<CartesianChart
xKey="day"
padding={20}
yKeys={["temperature"]}
domainPadding={{ left: 12, right: 50, top: 0 }}
data={data}
domain={{ y: [0, 100], x: [0, 7] }}
xAxis={{
font,
labelOffset: 14,
linePathEffect: <DashPathEffect intervals={[4, 4]} />,
renderXLabel: ({ x, y, content, canFitContent }) => {
if (!canFitContent) {
return null;
}

return (
<Paragraph
paragraph={paragraphMaker(content)}
x={x}
y={y}
width={42}
/>

// <SkiaText
// key={`y-${y}-${x}`}
// color={"green"}
// text={`Hi ${content}`}
// font={font}
// y={y}
// x={x}
// />
);
},
}}
yAxis={[
{
tickValues: [15, 50, 80],
renderYLabel: ({ x, y, index }) => {
return (
<Image
image={images[index]!}
fit="contain"
y={y}
x={x}
width={32}
height={32}
/>
);
},
labelOffset: 12,
font,
linePathEffect: <DashPathEffect intervals={[4, 4]} />,
},
]}
>
{({ points }) => {
return (
<Line
strokeWidth={3}
color={"#f7ce64"}
curveType="natural"
points={points.temperature}
/>
);
}}
</CartesianChart>
</View>
);
};

export default function AxisIconsChartPage() {
return (
<>
Expand All @@ -124,6 +271,12 @@ export default function AxisIconsChartPage() {
</Text>
<ChartWithLocalImages />
</View>
<View style={styles.chartContainer}>
<Text style={styles.title}>
Chart using renderYLabel and renderXLabel for full customization
</Text>
<ChartWithRenderCustomYLabel />
</View>
<View style={styles.chartContainer}>
<Text style={styles.title}>
Chart with remote images as tick values on the Y axis
Expand Down
38 changes: 27 additions & 11 deletions lib/src/cartesian/components/XAxis.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export const XAxis = <
enableRescaling,
zoom,
tickImages,
renderXLabel,
}: XAxisProps<RawData, XK>) => {
const xScale = zoom ? zoom.rescaleX(xScaleProp) : xScaleProp;
const [y1 = 0, y2 = 0] = yScale.domain();
Expand Down Expand Up @@ -93,18 +94,33 @@ export const XAxis = <
</Line>
</Group>
) : null}
{tickImages && tickImages[index] && canFitLabelContent && (
<AxisImage {...tickImages[index]} y={labelY} x={labelX} />
{renderXLabel ? (
renderXLabel({
x: labelX,
y: labelY,
content: contentX,
canFitContent: canFitLabelContent,
index: index,
})
) : (
<>
{tickImages && tickImages[index] && canFitLabelContent && (
<AxisImage {...tickImages[index]} y={labelY} x={labelX} />
)}
{font &&
labelWidth &&
canFitLabelContent &&
!tickImages?.[index] ? (
<Text
color={labelColor}
text={contentX}
font={font}
y={labelY}
x={labelX}
/>
) : null}
</>
)}
{font && labelWidth && canFitLabelContent && !tickImages?.[index] ? (
<Text
color={labelColor}
text={contentX}
font={font}
y={labelY}
x={labelX}
/>
) : null}
<></>
</React.Fragment>
);
Expand Down
35 changes: 24 additions & 11 deletions lib/src/cartesian/components/YAxis.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export const YAxis = <
linePathEffect,
chartBounds,
tickImages,
renderYLabel,
}: YAxisProps<RawData, YK> & { tickImages?: TickImage[] }) => {
const [x1 = 0, x2 = 0] = xScale.domain();
const [_ = 0, y2 = 0] = yScale.domain();
Expand Down Expand Up @@ -74,17 +75,29 @@ export const YAxis = <
</Line>
</Group>
) : null}
{tickImages && tickImages[index] && canFitLabelContent && (
<AxisImage {...tickImages[index]} y={labelY} x={labelX} />
)}
{font && canFitLabelContent && !tickImages?.[index] && (
<Text
color={labelColor}
text={contentY}
font={font}
y={labelY}
x={labelX}
/>
{renderYLabel ? (
renderYLabel({
x: labelX,
y: labelY,
content: contentY,
canFitContent: canFitLabelContent,
index: index,
})
) : (
<>
{tickImages && tickImages[index] && canFitLabelContent && (
<AxisImage {...tickImages[index]} y={labelY} x={labelX} />
)}
{font && canFitLabelContent && !tickImages?.[index] && (
<Text
color={labelColor}
text={contentY}
font={font}
y={labelY}
x={labelX}
/>
)}
</>
)}
</React.Fragment>
);
Expand Down
26 changes: 24 additions & 2 deletions lib/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ export type XAxisInputProps<
linePathEffect?: DashPathEffectComponent;
enableRescaling?: boolean;
tickImages?: TickImage[];
renderXLabel?: (opts: RenderAxisLabelProps) => React.ReactNode;
};

export type XAxisPropsWithDefaults<
Expand All @@ -197,7 +198,12 @@ export type XAxisPropsWithDefaults<
> = Required<
Omit<
XAxisInputProps<RawData, XK>,
"font" | "tickValues" | "linePathEffect" | "enableRescaling" | "tickImages"
| "font"
| "tickValues"
| "linePathEffect"
| "enableRescaling"
| "tickImages"
| "renderXLabel"
>
> &
Partial<
Expand All @@ -208,6 +214,7 @@ export type XAxisPropsWithDefaults<
| "linePathEffect"
| "enableRescaling"
| "tickImages"
| "renderXLabel"
>
>;

Expand All @@ -223,13 +230,22 @@ export type XAxisProps<
zoom?: ZoomTransform;
};

type RenderAxisLabelProps = {
x: number;
y: number;
index: number;
content: string;
canFitContent: boolean;
};

export type YAxisInputProps<
RawData extends Record<string, unknown>,
YK extends keyof NumericalFields<RawData>,
> = {
axisSide?: YAxisSide;
font?: SkFont | null;
formatYLabel?: (label: RawData[YK]) => string;
renderYLabel?: (opts: RenderAxisLabelProps) => React.ReactNode;
labelColor?: string;
labelOffset?: number;
labelPosition?: AxisLabelPosition;
Expand All @@ -250,7 +266,12 @@ export type YAxisPropsWithDefaults<
> = Required<
Omit<
YAxisInputProps<RawData, YK>,
"font" | "tickValues" | "linePathEffect" | "enableRescaling" | "tickImages"
| "font"
| "tickValues"
| "linePathEffect"
| "enableRescaling"
| "tickImages"
| "renderYLabel"
>
> &
Partial<
Expand All @@ -261,6 +282,7 @@ export type YAxisPropsWithDefaults<
| "linePathEffect"
| "enableRescaling"
| "tickImages"
| "renderYLabel"
>
>;

Expand Down

0 comments on commit 7a90e4b

Please sign in to comment.