Skip to content

Commit

Permalink
chore(🎮): add headless app example (#2945)
Browse files Browse the repository at this point in the history
  • Loading branch information
wcandillon authored Feb 5, 2025
1 parent 53e8fae commit 484b1b3
Show file tree
Hide file tree
Showing 7 changed files with 304 additions and 5 deletions.
3 changes: 2 additions & 1 deletion apps/docs/docs/getting-started/headless.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ You will notice in the example below that the import URL looks different than th

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

(async () => {
const width = 256;
const height = 256;
const size = 60;
const r = size * 0.33;
await LoadSkiaWeb();
// Once that CanvasKit is loaded, you can access Skia via getSkiaExports()
Expand Down
13 changes: 13 additions & 0 deletions apps/headless/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
## Commands

**Install Dependencies**

```console
yarn install
```

**Run**

```console
bun ./src/helloWorld.tsx
```
18 changes: 18 additions & 0 deletions apps/headless/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "headless-skia",
"version": "1.0.0",
"scripts": {
"test": "ts-node ./src/helloWorld.tsx",
"tsc": "tsc"
},
"dependencies": {
"@shopify/react-native-skia": "workspace:*",
"react": "^18.0.0",
"typescript": "^5.2.2"
},
"devDependencies": {
"eslint": "^9.19.0",
"eslint-config-react-native-wcandillon": "^3.10.2",
"ts-node": "^10.9.2"
}
}
34 changes: 34 additions & 0 deletions apps/headless/src/helloWorld.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import {
Circle,
drawOffscreen,
getSkiaExports,
Group,
makeOffscreenSurface,
} from "@shopify/react-native-skia/src/headless";
import { LoadSkiaWeb } from "@shopify/react-native-skia/src/web/LoadSkiaWeb";
import React from "react";

// https://shopify.github.io/react-native-skia/docs/getting-started/headless/
(async () => {
const width = 256;
const height = 256;
const size = 60;
const r = size * 0.33;
await LoadSkiaWeb();
// Once that CanvasKit is loaded, you can access Skia via getSkiaExports()
// Alternatively you can do const {Skia} = require("@shopify/react-native-skia")
const { Skia: _ } = getSkiaExports();
const surface = makeOffscreenSurface(width, height);
const image = drawOffscreen(
surface,
<Group blendMode="multiply">
<Circle cx={r} cy={r} r={r} color="cyan" />
<Circle cx={size - r} cy={r} r={r} color="magenta" />
<Circle cx={size / 2} cy={size - r} r={r} color="yellow" />
</Group>,
);
console.log(image.encodeToBase64());
// Cleaning up CanvasKit resources
image.dispose();
surface.dispose();
})();
13 changes: 13 additions & 0 deletions apps/headless/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"extends": "eslint-config-react-native-wcandillon/tsconfig.base",
"compilerOptions": {
"target": "es2018",
"module": "commonjs",
"lib": ["es2018", "dom"],
"jsx": "react",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"rootDir": "./src"
}
}
5 changes: 5 additions & 0 deletions packages/skia/src/sksg/Container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Rea from "../external/reanimated/ReanimatedProxy";
import type { Skia, SkCanvas } from "../skia/types";
import { HAS_REANIMATED_3 } from "../external/reanimated/renderHelpers";
import type { JsiRecorder } from "../skia/types/Recorder";
import type { ISkiaViewApi } from "../views/types";

import type { Node } from "./Node";
import type { Recording } from "./Recorder/Recorder";
Expand All @@ -11,6 +12,10 @@ import { replay } from "./Recorder/Player";
import { createDrawingContext } from "./Recorder/DrawingContext";
import { ReanimatedRecorder } from "./Recorder/ReanimatedRecorder";

declare global {
var SkiaViewApi: ISkiaViewApi;
}

const drawOnscreen = (Skia: Skia, nativeId: number, recording: Recording) => {
"worklet";

Expand Down
Loading

0 comments on commit 484b1b3

Please sign in to comment.