Skip to content

Commit

Permalink
Merge pull request #1088 from Shopify/useSize
Browse files Browse the repository at this point in the history
Deprecate useCanvas()
  • Loading branch information
chrfalch authored Nov 14, 2022
2 parents 9c24a44 + a4a0ce3 commit 3524887
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 33 deletions.
30 changes: 6 additions & 24 deletions docs/docs/animations/values.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,16 +89,9 @@ const Demo = () => {
};
```

## Canvas
## Canvas Size

The `useCanvas` hook returns a `size` value that updates every time the canvas size updates.
On the first frame, the size is zero.

:::caution

`useCanvas` can only be used inside the Canvas element because it relies on context.

:::
The `onSize` property will update the provided Skia Value with the current canvas size when the Canvas is resized.

```tsx twoslash
import React from "react";
Expand All @@ -108,22 +101,19 @@ import {
Group,
Rect,
rect,
useCanvas,
useValue,
useComputedValue,
} from "@shopify/react-native-skia";

const MyComp = () => {
// 💚 useCanvas() can safely be used here
const { size } = useCanvas();
// 💚 canvas is a regular skia value that can be used for animations
const Example = () => {
const size = useValue({ width: 0, height: 0 });
const rct = useComputedValue(() => {
return rect(0, 0, size.current.width, size.current.height / 2);
}, [size]);
return (
<Canvas style={{ flex: 1 }} onSize={size}>
<Group>
<Fill color="magenta" />
<Rect color="cyan" rect={rct} />
{/* ❌ this won't update since canvas is a skia value */}
<Rect
x={0}
y={0}
Expand All @@ -132,14 +122,6 @@ const MyComp = () => {
color="red"
/>
</Group>
);
};

const Example = () => {
// ❌ Using useCanvas() here would crash
return (
<Canvas style={{ flex: 1 }}>
<MyComp />
</Canvas>
);
};
Expand Down
1 change: 1 addition & 0 deletions docs/docs/canvas/canvas.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Behind the scenes, it is using its own React renderer.
| ref? | `Ref<SkiaView>` | Reference to the `SkiaView` object |
| mode? | `default` or `continuous` | By default, the canvas is only updated when the drawing tree or animation values change. With `mode="continuous"`, the canvas will redraw on every frame |
| onTouch? | `TouchHandler` | Touch handler for the Canvas (see [touch handler](/docs/animations/touch-events#usetouchhandler)) |
| onSize? | `SkiaMutableValue<Size>` | Skia value to which the canvas size will be assigned (see [canvas size](/docs/animations/values#canvas-size)) |
| onLayout? | `NativeEvent<LayoutEvent>` | Invoked on mount and on layout changes (see [onLayout](https://reactnative.dev/docs/view#onlayout)) |

## Getting the Canvas size
Expand Down
15 changes: 10 additions & 5 deletions example/src/Examples/API/UseCanvas.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
import type { SkiaValue, SkSize } from "@shopify/react-native-skia";
import {
useValue,
Canvas,
Fill,
Group,
Rect,
rect,
useCanvas,
useComputedValue,
} from "@shopify/react-native-skia";
import React, { useEffect, useRef } from "react";
import { View, Animated } from "react-native";

const MyComp = () => {
const { size } = useCanvas();
interface MyCompProps {
size: SkiaValue<SkSize>;
}

const MyComp = ({ size }: MyCompProps) => {
const rct = useComputedValue(() => {
return rect(0, 0, size.current.width, size.current.height / 2);
}, [size]);
Expand All @@ -24,6 +28,7 @@ const MyComp = () => {
};

export const UseCanvas = () => {
const size = useValue({ width: 0, height: 0 });
const height = useRef(new Animated.Value(0));
useEffect(() => {
Animated.loop(
Expand All @@ -36,8 +41,8 @@ export const UseCanvas = () => {
}, []);
return (
<View style={{ flex: 1 }}>
<Canvas style={{ flex: 1 }}>
<MyComp />
<Canvas style={{ flex: 1 }} onSize={size}>
<MyComp size={size} />
</Canvas>
<Animated.View style={{ height: height.current }} />
</View>
Expand Down
9 changes: 7 additions & 2 deletions package/src/renderer/Canvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ import { SkiaView, useDrawCallback } from "../views";
import type { TouchHandler } from "../views";
import { useValue } from "../values/hooks/useValue";
import { Skia } from "../skia/Skia";
import type { SkiaValue } from "../values";
import type { SkiaValue, SkiaMutableValue } from "../values";
import type { SkSize } from "../skia/types";

import { debug as hostDebug, skHostConfig } from "./HostConfig";
// import { debugTree } from "./nodes";
Expand Down Expand Up @@ -49,10 +50,11 @@ export interface CanvasProps extends ComponentProps<typeof SkiaView> {
ref?: RefObject<SkiaView>;
children: ReactNode;
onTouch?: TouchHandler;
onSize?: SkiaMutableValue<SkSize>;
}

export const Canvas = forwardRef<SkiaView, CanvasProps>(
({ children, style, debug, mode, onTouch }, forwardedRef) => {
({ children, style, debug, mode, onTouch, onSize }, forwardedRef) => {
const size = useValue({ width: 0, height: 0 });
const canvasCtx = useMemo(() => ({ Skia, size }), [size]);
const innerRef = useCanvasRef();
Expand Down Expand Up @@ -114,6 +116,9 @@ export const Canvas = forwardRef<SkiaView, CanvasProps>(
height !== canvasCtx.size.current.height
) {
canvasCtx.size.current = { width, height };
if (onSize) {
onSize.current = { width, height };
}
}
paint.reset();
const ctx = {
Expand Down
4 changes: 2 additions & 2 deletions package/src/renderer/components/Mask.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { ReactNode } from "react";
import React, { useMemo } from "react";

import { BlendMode } from "../../skia/types";
import { useCanvas } from "../useCanvas";
import { useSkiaPrivate } from "../useCanvas";

import { Group } from "./Group";

Expand All @@ -14,7 +14,7 @@ interface MaskProps {
}

export const Mask = ({ children, mask, mode, clip }: MaskProps) => {
const { Skia } = useCanvas();
const Skia = useSkiaPrivate();
const maskPaint = useMemo(() => {
const paint = Skia.Paint();
paint.setBlendMode(BlendMode.Src);
Expand Down
14 changes: 14 additions & 0 deletions package/src/renderer/useCanvas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,22 @@ export const CanvasProvider = CanvasContext.Provider;

export const useCanvas = () => {
const ctx = useContext(CanvasContext);
console.warn(
// eslint-disable-next-line max-len
"useCanvas is deprecated. use the onSize property instead: https://shopify.github.io/react-native-skia/docs/canvas/overview"
);
if (!ctx) {
throw new Error("Canvas context is not available");
}
return ctx;
};

// This private function will be removed once we remove the useCanvas hook and
// implement the Mask component as a node (will be faster too)
export const useSkiaPrivate = () => {
const ctx = useContext(CanvasContext);
if (!ctx) {
throw new Error("Canvas context is not available");
}
return ctx.Skia;
};
4 changes: 4 additions & 0 deletions package/src/skia/types/Size.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface SkSize {
width: number;
height: number;
}
1 change: 1 addition & 0 deletions package/src/skia/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ export * from "./RSXform";
export * from "./JsiInstance";
export * from "./Skia";
export * from "./TextBlob";
export * from "./Size";

0 comments on commit 3524887

Please sign in to comment.