Skip to content

Commit f3c6b9c

Browse files
authored
chore(πŸ“š): improve documentation for pictures (#3581)
1 parent bf60fec commit f3c6b9c

File tree

12 files changed

+299
-158
lines changed

12 files changed

+299
-158
lines changed

β€Žapps/docs/docs/pictures.mdβ€Ž

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
---
2+
id: pictures
3+
title: Pictures
4+
sidebar_label: Pictures
5+
slug: /shapes/pictures
6+
---
7+
8+
React Native Skia works in retained mode: every re-render, we create a display list with support for animation values.
9+
This is great to animate property values. However, if you want to execute a variable number of drawing commands, this is where you need to use pictures.
10+
11+
A Picture contains a list of drawing operations to be drawn on a canvas.
12+
The picture is immutable and cannot be edited or changed after it has been created. It can be used multiple times in any canvas.
13+
14+
| Name | Type | Description |
15+
| :------ | :---------- | :---------------- |
16+
| picture | `SkPicture` | Picture to render |
17+
18+
## Hello World
19+
20+
In this example, we animate a trail of circles. The number of circles in the trail changes over time, which is why we need to use pictures: we can't animated on the number of circle components.
21+
22+
```tsx twoslash
23+
import React, { useEffect } from "react";
24+
import { Canvas, Picture, Skia } from "@shopify/react-native-skia";
25+
import {
26+
useDerivedValue,
27+
useSharedValue,
28+
withRepeat,
29+
withTiming,
30+
} from "react-native-reanimated";
31+
32+
const size = 256;
33+
const n = 20;
34+
35+
const paint = Skia.Paint();
36+
37+
export const HelloWorld = () => {
38+
const progress = useSharedValue(0);
39+
40+
useEffect(() => {
41+
progress.value = withRepeat(withTiming(1, { duration: 3000 }), -1, true);
42+
}, [progress]);
43+
44+
const picture = useDerivedValue(() => {
45+
"worklet";
46+
const recorder = Skia.PictureRecorder();
47+
const canvas = recorder.beginRecording(Skia.XYWHRect(0, 0, size, size));
48+
const numberOfCircles = Math.floor(progress.value * n);
49+
for (let i = 0; i < numberOfCircles; i++) {
50+
const alpha = ((i + 1) / n) * 255;
51+
const r = ((i + 1) / n) * (size / 2);
52+
paint.setColor(Skia.Color(`rgba(0, 122, 255, ${alpha / 255})`));
53+
canvas.drawCircle(size / 2, size / 2, r, paint);
54+
}
55+
return recorder.finishRecordingAsPicture();
56+
});
57+
58+
return (
59+
<Canvas style={{ flex: 1 }}>
60+
<Picture picture={picture} />
61+
</Canvas>
62+
);
63+
};
64+
```
65+
66+
| progress=0.25 | progress=0.5 | progress=1 |
67+
| :-----------: | :----------: | :--------: |
68+
| <img src={require("/static/img/pictures/circle-trail-0.25.png").default} width="256" height="256" /> | <img src={require("/static/img/pictures/circle-trail-0.5.png").default} width="256" height="256" /> | <img src={require("/static/img/pictures/circle-trail-1.png").default} width="256" height="256" /> |
69+
70+
## Applying Effects
71+
72+
The `Picture` component doesn't follow the same painting rules as other components.
73+
However you can apply effects using the `layer` property.
74+
For instance, in the example below, we apply a blur image filter.
75+
76+
```tsx twoslash
77+
import React, { useMemo } from "react";
78+
import { Canvas, Skia, Group, Paint, Blur, BlendMode, Picture } from "@shopify/react-native-skia";
79+
80+
export const Demo = () => {
81+
const picture = useMemo(() => {
82+
const recorder = Skia.PictureRecorder();
83+
const size = 256;
84+
const canvas = recorder.beginRecording(Skia.XYWHRect(0, 0, size, size));
85+
const r = 0.33 * size;
86+
const paint = Skia.Paint();
87+
paint.setBlendMode(BlendMode.Multiply);
88+
89+
paint.setColor(Skia.Color("cyan"));
90+
canvas.drawCircle(r, r, r, paint);
91+
92+
paint.setColor(Skia.Color("magenta"));
93+
canvas.drawCircle(size - r, r, r, paint);
94+
95+
paint.setColor(Skia.Color("yellow"));
96+
canvas.drawCircle(size / 2, size - r, r, paint);
97+
98+
return recorder.finishRecordingAsPicture();
99+
}, []);
100+
return (
101+
<Canvas style={{ flex: 1 }}>
102+
<Group layer={<Paint><Blur blur={10} /></Paint>}>
103+
<Picture picture={picture} />
104+
</Group>
105+
</Canvas>
106+
);
107+
};
108+
```
109+
110+
<img src={require("/static/img/blurred-picture.png").default} width="256" height="256" />
111+
112+
## Serialization
113+
114+
You can serialize a picture to a byte array.
115+
Serialized pictures are only compatible with the version of Skia it was created with.
116+
You can use serialized pictures with the [Skia debugger](https://skia.org/docs/dev/tools/debugger/).
117+
118+
```tsx twoslash
119+
import React, { useMemo } from "react";
120+
import {
121+
Canvas,
122+
Picture,
123+
Skia,
124+
Group,
125+
} from "@shopify/react-native-skia";
126+
127+
export const PictureExample = () => {
128+
// Create picture
129+
const picture = useMemo(() => {
130+
const recorder = Skia.PictureRecorder();
131+
const canvas = recorder.beginRecording(Skia.XYWHRect(0, 0, 100, 100));
132+
133+
const paint = Skia.Paint();
134+
paint.setColor(Skia.Color("pink"));
135+
canvas.drawRect({ x: 0, y: 0, width: 100, height: 100 }, paint);
136+
137+
const circlePaint = Skia.Paint();
138+
circlePaint.setColor(Skia.Color("orange"));
139+
canvas.drawCircle(50, 50, 50, circlePaint);
140+
141+
return recorder.finishRecordingAsPicture();
142+
}, []);
143+
144+
// Serialize the picture
145+
const serialized = useMemo(() => picture.serialize(), [picture]);
146+
147+
// Create a copy from serialized data
148+
const copyOfPicture = useMemo(
149+
() => (serialized ? Skia.Picture.MakePicture(serialized) : null),
150+
[serialized]
151+
);
152+
153+
return (
154+
<Canvas style={{ flex: 1 }}>
155+
<Picture picture={picture} />
156+
<Group transform={[{ translateX: 200 }]}>
157+
{copyOfPicture && <Picture picture={copyOfPicture} />}
158+
</Group>
159+
</Canvas>
160+
);
161+
};
162+
```
163+
164+
## Instance Methods
165+
166+
| Name | Description |
167+
| :--------- | :---------------------------------------------------------------------------- |
168+
| makeShader | Returns a new shader that will draw with this picture. |
169+
| serialize | Returns a UInt8Array representing the drawing operations stored in the image. |

β€Žapps/docs/docs/shapes/pictures.mdβ€Ž

Lines changed: 0 additions & 157 deletions
This file was deleted.

β€Žapps/docs/sidebars.jsβ€Ž

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ const sidebars = {
4343
label: "Group",
4444
id: "group",
4545
},
46+
{
47+
type: "doc",
48+
label: "Pictures",
49+
id: "pictures",
50+
},
4651
{
4752
collapsed: true,
4853
type: "category",
@@ -54,7 +59,6 @@ const sidebars = {
5459
"shapes/atlas",
5560
"shapes/vertices",
5661
"shapes/patch",
57-
"shapes/pictures",
5862
],
5963
},
6064
{
9.03 KB
Loading
20.6 KB
Loading
24.9 KB
Loading
2.34 KB
Loading
24.9 KB
Loading
20.6 KB
Loading
20.6 KB
Loading

0 commit comments

Comments
Β (0)