Replies: 1 comment
-
Finding area of the path might be challenging import {
Canvas,
Group,
Image,
Path,
Skia,
rect,
useCanvasRef,
useImage,
} from '@shopify/react-native-skia';
import {
MutableRefObject,
useRef,
useState,
} from 'react';
import {Button} from 'react-native';
let imgPath = require('./i.png');
let path = Skia.Path.Make();
path
.moveTo(40, 40)
.lineTo(200, 400)
// .lineTo(0, 400)
.close();
type hiddenCavasRef = MutableRefObject<{
getCoveredArea?: () => number;
}>;
export function F() {
const img = useImage(imgPath);
const hiddenCavasRef = useRef(
{},
) as hiddenCavasRef;
return (
<>
<Canvas
collapsable
style={{width: 300, height: 300}}>
<Group>
<Image
image={img}
rect={rect(0, 0, 300, 300)}
fit={'cover'}
/>
<Path
path={path}
style={'stroke'}
strokeWidth={50}
color={'black'}
strokeCap={'round'}
strokeJoin={'round'}
blendMode={'xor'}
/>
</Group>
</Canvas>
<HiddenCanvasToGetAvgColor
hiddenCavasRef={hiddenCavasRef}
/>
<Button
title="get covered area fraction"
onPress={() => {
console.error(
hiddenCavasRef.current.getCoveredArea?.(),
);
}}
/>
</>
);
}
const HiddenCanvasToGetAvgColor = ({
hiddenCavasRef,
}: {
hiddenCavasRef: hiddenCavasRef;
}) => {
const ref = useCanvasRef();
const getAvgColor = () => {
let img = ref.current?.makeImageSnapshot();
let pixels = img?.readPixels();
if (pixels) {
const rPixels = pixels.filter(
(_, i) => i % 4 === 0,
);
const avgColor =
//@ts-ignore
rPixels.reduce(
//@ts-ignore
(acc, cur) => acc + cur,
0,
) /
rPixels.length /
255;
return avgColor;
}
return 0;
};
hiddenCavasRef.current.getCoveredArea =
getAvgColor;
return (
<Canvas
ref={ref}
style={{
width: 10,
height: 10,
backgroundColor: 'black',
position: 'absolute',
opacity: 0,
}}>
<Path
transform={[{scale: 1 / 30}]}
path={path}
style={'stroke'}
strokeWidth={50}
color={'white'}
strokeCap={'round'}
strokeJoin={'round'}
/>
</Canvas>
);
}; So, here's what I did: I made a hidden canvas where I drew the same path used for the scratch effect, then filled it with white color. After that, I make a sanpshot of that canvas and by using the readPixel API, I deduced out the average color of the snapshot of that canvas. Since only the painted area is white, the average color tells me the percentage of the covered area. And for the optimisation purpose I used only red channel, since the color is either white or none (0, 0, 0, 0) Also one suggestion use forwardRef to access the child's function. And you can write proper types for the reduce function. Please let me know if it helps. |
Beta Was this translation helpful? Give feedback.
-
Simply a scratchboard component.
I need a way to get how much percentage of the image is scratched to be able to mark it as scratched or not...
Beta Was this translation helpful? Give feedback.
All reactions