react-native-qrcode-package
Version:
This package include QR code generator and QR code Scanner for React Native.
171 lines (162 loc) • 4.2 kB
JavaScript
import React, {useMemo} from 'react';
import Svg, {
Defs,
G,
Path,
Rect,
Image,
ClipPath,
LinearGradient,
Stop,
} from 'react-native-svg';
import generateMatrix from './GenerateMatrix';
import transformMatrixIntoPath from './TransformMatrixIntoPath';
const CLIP_LOGO_ID_BACKGROUND = 'clip-logo-background';
const CLIP_LOGO_BACKGROUND = 'url(#clip-logo-background)';
const CLIP_LOGO_ID = 'clip-logo';
const CLIP_LOGO = 'url(#clip-logo)';
const PRESERVE_ASPECT_RATIO = 'xMidYMid slice';
const STYLE_LINE = 'butt';
const GRADIENT_COLOR = 'url(#grad)';
const renderLogo = ({
sizeQRCode,
logo,
logoSize,
logoBackgroundColor,
logoMargin,
logoBorderRadius,
}) => {
const logoPosition = (sizeQRCode - logoSize - logoMargin * 2) / 2;
const logoBackgroundSize = logoSize + logoMargin * 2;
const logoBackgroundBorderRadius =
logoBorderRadius + (logoMargin / logoSize) * logoBorderRadius;
return (
<G x={logoPosition} y={logoPosition}>
<Defs>
<ClipPath id={CLIP_LOGO_ID_BACKGROUND}>
<Rect
width={logoBackgroundSize}
height={logoBackgroundSize}
rx={logoBackgroundBorderRadius}
ry={logoBackgroundBorderRadius}
/>
</ClipPath>
<ClipPath id={CLIP_LOGO_ID}>
<Rect
width={logoSize}
height={logoSize}
rx={logoBorderRadius}
ry={logoBorderRadius}
/>
</ClipPath>
</Defs>
<G>
<Rect
width={logoBackgroundSize}
height={logoBackgroundSize}
fill={logoBackgroundColor}
clipPath={CLIP_LOGO_BACKGROUND}
/>
</G>
<G x={logoMargin} y={logoMargin}>
<Image
width={logoSize}
height={logoSize}
preserveAspectRatio={PRESERVE_ASPECT_RATIO}
href={logo}
clipPath={CLIP_LOGO}
/>
</G>
</G>
);
};
const GenerateQRCode = ({
jsonObject = {},
sizeQRCode = 150,
colorQRCode = 'black',
backgroundColorQRCode = 'white',
logo,
logoSize = sizeQRCode * 0.2,
logoBackgroundColor = 'transparent',
logoMargin = 2,
logoBorderRadius = 0,
quietZone = 0,
enableLinearGradient = false,
gradientDirection = ['0%', '0%', '100%', '100%'],
linearGradient = ['rgb(255,0,0)', 'rgb(0,255,255)'],
ecl = 'M',
getRef,
onError,
}) => {
const qrCodeValue = JSON.stringify(jsonObject);
const result = useMemo(() => {
try {
return transformMatrixIntoPath(
generateMatrix(qrCodeValue, ecl),
sizeQRCode,
);
} catch (error) {
if (onError && typeof onError === 'function') {
onError(error);
} else {
// Throw an error when no handler set
throw error;
}
}
}, [qrCodeValue, ecl, sizeQRCode, onError]);
if (!result) {
return null;
}
const {path, cellSize} = result;
return (
<Svg
ref={getRef}
viewBox={[
-quietZone,
-quietZone,
sizeQRCode + quietZone * 2,
sizeQRCode + quietZone * 2,
].join(' ')}
width={sizeQRCode}
height={sizeQRCode}>
<Defs>
<LinearGradient
id="grad"
x1={gradientDirection[0]}
y1={gradientDirection[1]}
x2={gradientDirection[2]}
y2={gradientDirection[3]}>
<Stop offset="0" stopColor={linearGradient[0]} stopOpacity="1" />
<Stop offset="1" stopColor={linearGradient[1]} stopOpacity="1" />
</LinearGradient>
</Defs>
<G>
<Rect
x={-quietZone}
y={-quietZone}
width={sizeQRCode + quietZone * 2}
height={sizeQRCode + quietZone * 2}
fill={backgroundColorQRCode}
/>
</G>
<G>
<Path
d={path}
strokeLinecap={STYLE_LINE}
stroke={enableLinearGradient ? {GRADIENT_COLOR} : colorQRCode}
strokeWidth={cellSize}
/>
</G>
{logo &&
renderLogo({
sizeQRCode,
logo,
logoSize,
logoBackgroundColor,
logoMargin,
logoBorderRadius,
})}
</Svg>
);
};
export default GenerateQRCode;