Skip to content

Commit 484b1b3

Browse files
authoredFeb 5, 2025
chore(🎮): add headless app example (#2945)
1 parent 53e8fae commit 484b1b3

File tree

7 files changed

+304
-5
lines changed

7 files changed

+304
-5
lines changed
 

‎apps/docs/docs/getting-started/headless.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,12 @@ You will notice in the example below that the import URL looks different than th
1515

1616
```tsx
1717
import { LoadSkiaWeb } from "@shopify/react-native-skia/lib/commonjs/web/LoadSkiaWeb";
18-
import { Fill, makeOffscreenSurface, drawOffscreen, getSkiaExports } from "@shopify/react-native-skia/lib/commonjs/headless";
18+
import { Circle, drawOffscreen, getSkiaExports, Group, makeOffscreenSurface } from "@shopify/react-native-skia/lib/commonjs/headless";
1919

2020
(async () => {
2121
const width = 256;
2222
const height = 256;
23+
const size = 60;
2324
const r = size * 0.33;
2425
await LoadSkiaWeb();
2526
// Once that CanvasKit is loaded, you can access Skia via getSkiaExports()

‎apps/headless/README.md

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
## Commands
2+
3+
**Install Dependencies**
4+
5+
```console
6+
yarn install
7+
```
8+
9+
**Run**
10+
11+
```console
12+
bun ./src/helloWorld.tsx
13+
```

‎apps/headless/package.json

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"name": "headless-skia",
3+
"version": "1.0.0",
4+
"scripts": {
5+
"test": "ts-node ./src/helloWorld.tsx",
6+
"tsc": "tsc"
7+
},
8+
"dependencies": {
9+
"@shopify/react-native-skia": "workspace:*",
10+
"react": "^18.0.0",
11+
"typescript": "^5.2.2"
12+
},
13+
"devDependencies": {
14+
"eslint": "^9.19.0",
15+
"eslint-config-react-native-wcandillon": "^3.10.2",
16+
"ts-node": "^10.9.2"
17+
}
18+
}

‎apps/headless/src/helloWorld.tsx

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import {
2+
Circle,
3+
drawOffscreen,
4+
getSkiaExports,
5+
Group,
6+
makeOffscreenSurface,
7+
} from "@shopify/react-native-skia/src/headless";
8+
import { LoadSkiaWeb } from "@shopify/react-native-skia/src/web/LoadSkiaWeb";
9+
import React from "react";
10+
11+
// https://shopify.github.io/react-native-skia/docs/getting-started/headless/
12+
(async () => {
13+
const width = 256;
14+
const height = 256;
15+
const size = 60;
16+
const r = size * 0.33;
17+
await LoadSkiaWeb();
18+
// Once that CanvasKit is loaded, you can access Skia via getSkiaExports()
19+
// Alternatively you can do const {Skia} = require("@shopify/react-native-skia")
20+
const { Skia: _ } = getSkiaExports();
21+
const surface = makeOffscreenSurface(width, height);
22+
const image = drawOffscreen(
23+
surface,
24+
<Group blendMode="multiply">
25+
<Circle cx={r} cy={r} r={r} color="cyan" />
26+
<Circle cx={size - r} cy={r} r={r} color="magenta" />
27+
<Circle cx={size / 2} cy={size - r} r={r} color="yellow" />
28+
</Group>,
29+
);
30+
console.log(image.encodeToBase64());
31+
// Cleaning up CanvasKit resources
32+
image.dispose();
33+
surface.dispose();
34+
})();

‎apps/headless/tsconfig.json

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"extends": "eslint-config-react-native-wcandillon/tsconfig.base",
3+
"compilerOptions": {
4+
"target": "es2018",
5+
"module": "commonjs",
6+
"lib": ["es2018", "dom"],
7+
"jsx": "react",
8+
"strict": true,
9+
"esModuleInterop": true,
10+
"skipLibCheck": true,
11+
"rootDir": "./src"
12+
}
13+
}

‎packages/skia/src/sksg/Container.ts

+5
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import Rea from "../external/reanimated/ReanimatedProxy";
22
import type { Skia, SkCanvas } from "../skia/types";
33
import { HAS_REANIMATED_3 } from "../external/reanimated/renderHelpers";
44
import type { JsiRecorder } from "../skia/types/Recorder";
5+
import type { ISkiaViewApi } from "../views/types";
56

67
import type { Node } from "./Node";
78
import type { Recording } from "./Recorder/Recorder";
@@ -11,6 +12,10 @@ import { replay } from "./Recorder/Player";
1112
import { createDrawingContext } from "./Recorder/DrawingContext";
1213
import { ReanimatedRecorder } from "./Recorder/ReanimatedRecorder";
1314

15+
declare global {
16+
var SkiaViewApi: ISkiaViewApi;
17+
}
18+
1419
const drawOnscreen = (Skia: Skia, nativeId: number, recording: Recording) => {
1520
"worklet";
1621

0 commit comments

Comments
 (0)
Failed to load comments.