Skip to content

Commit abbf10e

Browse files
committed
pass functions to webview
1 parent b59b993 commit abbf10e

File tree

6 files changed

+288
-111
lines changed

6 files changed

+288
-111
lines changed

README.md

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,64 @@ The `ref` exposes the following methods:
7676
- `setSize(width, height)`: Set the size of the chart.
7777
- `destroy()`: Destroy the chart instance.
7878
79-
### Plot dimensions
79+
### Dimensions
8080
81-
You can set the width and height either through the uPlot `options` or by passing a `style` prop to the `ChartUPlot` component. If you set both, the uPlot `options` will take precedence.
81+
You can set the width and height either through the uPlot `options` or by passing a `style` prop to the `ChartUPlot` component. If you set both, the uPlot `options` will take precedence. Any changes to the width and height in the `options` will not automatically update the chart size.
8282
83-
### Plot margins
83+
### Margins
8484
8585
Margin for the title and legend will be subtracted from the final width and height for the chart. You can control the margin via the `margin: { title?: number; legend?: number }` prop.
8686
87+
### Functions
88+
89+
The uPlot options can include custom functions for things like drawing and formatting tick labels. You'll need to duplicate each function: one as a normal javascript function and another as a string for the webview. Pass any functions to the `functions` prop of `ChartUPlot`, which will be injected into the webview and can be used in the uPlot options.
90+
91+
```javascript
92+
// for web version of uPlot
93+
function formatLabel(value) {
94+
return value.toFixed(2);
95+
}
96+
97+
// for iOS and Android version
98+
const formatLabelString = `
99+
function formatLabel(value) {
100+
return value.toFixed(2);
101+
}
102+
`;
103+
104+
const options = {
105+
width: 300,
106+
height: 300,
107+
scales: { x: { time: false } },
108+
series: [{ label: 'X' }, { label: 'Value', stroke: 'blue', width: 2 }],
109+
axes: [
110+
{
111+
scale: 'x',
112+
values: formatLabel,
113+
},
114+
{},
115+
],
116+
};
117+
118+
<ChartUPlot
119+
options={options}
120+
functions={[formatLabelString]}
121+
<!-- ... other props -->
122+
/>
123+
```
124+
125+
#### Important!
126+
127+
Any dependencies in each function must be:
128+
129+
- One of the other functions passed to the `functions` prop.
130+
- A global variable that is defined in the webview.
131+
- A function from the uPlot library that is available in the webview.
132+
133+
#### Why is it done this way?
134+
135+
There may be a better way to do this, so please open an issue if you have a suggestion. Passing javascript functions to the webview is tricky, so the current solution is to pass them as strings into WebView's `injectedJavaScript` prop. This means if you're also supporting web, you need to duplicate each function to support both web and iOS/Android. If you didn't do this and instead tried doing something like `function.toString()` in an iOS build, it does not return the javascript source code.
136+
87137
## Demo app
88138

89139
The `demo` folder contains an example Expo app that demonstrates how to use the library. You can run it by cloning the repository and running:

demo/app/(tabs)/index.tsx

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
11
import { useEffect, useRef, useState, useMemo } from 'react';
2-
import {
3-
Platform,
4-
StyleSheet,
5-
SafeAreaView,
6-
Text,
7-
Dimensions,
8-
} from 'react-native';
2+
import { StyleSheet, SafeAreaView, Text, Dimensions } from 'react-native';
93

104
import ChartUPlot from 'uplot-react-native';
115

@@ -21,6 +15,19 @@ var makeData = (points = 1000) => {
2115
return [xs, ys] as [number[], number[]];
2216
};
2317

18+
function format_value(self, ticks) {
19+
return ticks.map((val) => {
20+
return 2;
21+
});
22+
}
23+
var format_value_src = `
24+
function format_value(self, ticks) {
25+
return ticks.map((val) => {
26+
return 2;
27+
});
28+
};
29+
`;
30+
2431
var n = 500;
2532
var data1 = makeData(n);
2633
var data2 = makeData(n);
@@ -54,10 +61,27 @@ export default function HomeScreen() {
5461
width: width,
5562
height: height * 0.7,
5663
scales: { x: { time: false } },
57-
series: [{ label: 'Time' }, { label: 'Value', stroke: 'blue', width: 2 }],
58-
axes: [{ scale: 'x' }, {}],
64+
series: [
65+
{
66+
label: 'Time',
67+
},
68+
{ label: 'Value', stroke: 'blue', width: 2 },
69+
],
70+
axes: [
71+
{
72+
scale: 'x',
73+
ticks: {
74+
stroke: 'black',
75+
width: 2,
76+
},
77+
values: format_value,
78+
},
79+
{},
80+
],
5981
};
6082

83+
var functions = [format_value];
84+
6185
return (
6286
<SafeAreaView
6387
style={{
@@ -88,6 +112,7 @@ export default function HomeScreen() {
88112
height: height * 0.7,
89113
}}
90114
ref={chartRef1}
115+
functions={[format_value_src]}
91116
/>
92117
{/* <ChartUPlot
93118
data={data2}

demo/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
"react-native-screens": "~4.11.1",
3939
"react-native-web": "~0.20.0",
4040
"react-native-webview": "13.13.5",
41-
"uplot-react-native": "0.1.4"
41+
"uplot-react-native": "file:.."
4242
},
4343
"devDependencies": {
4444
"@babel/core": "^7.25.2",

0 commit comments

Comments
 (0)