|
| 1 | +import type { SkiaContext } from "@shopify/react-native-skia"; |
| 2 | +import { |
| 3 | + BlendMode, |
| 4 | + BlurStyle, |
| 5 | + mix, |
| 6 | + polar2Canvas, |
| 7 | + Skia, |
| 8 | +} from "@shopify/react-native-skia"; |
| 9 | +import { Dimensions, PixelRatio } from "react-native"; |
| 10 | +import { useSharedValue } from "react-native-reanimated"; |
| 11 | +import { useCanvasEffect } from "react-native-wgpu"; |
| 12 | + |
| 13 | +export const useSkiaContext = () => { |
| 14 | + const context = useSharedValue<SkiaContext | null>(null); |
| 15 | + const ref = useCanvasEffect(() => { |
| 16 | + const nativeSurface = ref.current!.getNativeSurface(); |
| 17 | + context.value = Skia.Context( |
| 18 | + nativeSurface.surface, |
| 19 | + nativeSurface.width * pd, |
| 20 | + nativeSurface.height * pd |
| 21 | + ); |
| 22 | + }); |
| 23 | + return { |
| 24 | + context, |
| 25 | + ref, |
| 26 | + }; |
| 27 | +}; |
| 28 | + |
| 29 | +const pd = PixelRatio.get(); |
| 30 | +const { width, height } = Dimensions.get("window"); |
| 31 | +const center = { x: width / 2, y: height / 2 }; |
| 32 | +const R = width / 4; |
| 33 | + |
| 34 | +const c1 = "#61bea2"; |
| 35 | +const c2 = "#529ca0"; |
| 36 | +const root = Skia.Paint(); |
| 37 | +root.setBlendMode(BlendMode.Screen); |
| 38 | +root.setMaskFilter(Skia.MaskFilter.MakeBlur(BlurStyle.Solid, 10, true)); |
| 39 | +const p1 = root.copy(); |
| 40 | +p1.setColor(Skia.Color(c1)); |
| 41 | +const p2 = root.copy(); |
| 42 | +p2.setColor(Skia.Color(c2)); |
| 43 | + |
| 44 | +export const drawBreatheDemo = (ctx: SkiaContext, progress: number) => { |
| 45 | + "worklet"; |
| 46 | + const surface = ctx.getSurface(); |
| 47 | + const canvas = surface.getCanvas(); |
| 48 | + canvas.clear(Skia.Color("rgb(36, 43, 56)")); |
| 49 | + canvas.save(); |
| 50 | + canvas.scale(pd, pd); |
| 51 | + canvas.rotate(progress * -180, center.x, center.y); |
| 52 | + // const offscreen = Skia.Surface.MakeOffscreen(256, 256)!; |
| 53 | + // const offscreenCanvas = offscreen.getCanvas(); |
| 54 | + // offscreenCanvas.clear(Skia.Color("green")); |
| 55 | + // canvas.drawImage(offscreen.makeImageSnapshot(), 0, 0); |
| 56 | + new Array(6).fill(0).map((_, index) => { |
| 57 | + canvas.save(); |
| 58 | + const theta = (index * (2 * Math.PI)) / 6; |
| 59 | + const { x, y } = polar2Canvas( |
| 60 | + { theta, radius: progress * R }, |
| 61 | + { x: 0, y: 0 } |
| 62 | + ); |
| 63 | + const scale = mix(progress, 0.3, 1); |
| 64 | + |
| 65 | + canvas.translate(center.x, center.y); |
| 66 | + canvas.translate(x, y); |
| 67 | + canvas.scale(scale, scale); |
| 68 | + canvas.translate(-center.x, -center.y); |
| 69 | + |
| 70 | + const paint = index % 2 ? p1 : p2; |
| 71 | + canvas.drawCircle(center.x, center.y, R, paint); |
| 72 | + canvas.restore(); |
| 73 | + }); |
| 74 | + |
| 75 | + canvas.restore(); |
| 76 | +}; |
0 commit comments