react-native-qrcode-svg
Version:
A QR Code generator for React Native based on react-native-svg and javascript-qrcode.
161 lines (153 loc) • 3.67 kB
JavaScript
import React, { useMemo } from 'react'
import Svg, {
Defs,
G,
Path,
Rect,
Image,
ClipPath,
LinearGradient,
Stop
} from 'react-native-svg'
import genMatrix from './genMatrix'
import transformMatrixIntoPath from './transformMatrixIntoPath'
const renderLogo = ({
size,
logo,
logoSize,
logoBackgroundColor,
logoMargin,
logoBorderRadius
}) => {
const logoPosition = (size - 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-background'>
<Rect
width={logoBackgroundSize}
height={logoBackgroundSize}
rx={logoBackgroundBorderRadius}
ry={logoBackgroundBorderRadius}
/>
</ClipPath>
<ClipPath id='clip-logo'>
<Rect
width={logoSize}
height={logoSize}
rx={logoBorderRadius}
ry={logoBorderRadius}
/>
</ClipPath>
</Defs>
<G>
<Rect
width={logoBackgroundSize}
height={logoBackgroundSize}
fill={logoBackgroundColor}
clipPath='url(#clip-logo-background)'
/>
</G>
<G x={logoMargin} y={logoMargin}>
<Image
width={logoSize}
height={logoSize}
preserveAspectRatio='xMidYMid slice'
href={logo}
clipPath='url(#clip-logo)'
/>
</G>
</G>
)
}
const QRCode = ({
value = 'this is a QR code',
size = 100,
color = 'black',
backgroundColor = 'white',
logo,
logoSize = size * 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 result = useMemo(() => {
try {
return transformMatrixIntoPath(genMatrix(value, ecl), size)
} catch (error) {
if (onError && typeof onError === 'function') {
onError(error)
} else {
// Pass the error when no handler presented
throw error
}
}
}, [value, size, ecl])
if (!result) {
return null
}
const { path, cellSize } = result
return (
<Svg
ref={getRef}
viewBox={[
-quietZone,
-quietZone,
size + quietZone * 2,
size + quietZone * 2
].join(' ')}
width={size}
height={size}
>
<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={size + quietZone * 2}
height={size + quietZone * 2}
fill={backgroundColor}
/>
</G>
<G>
<Path
d={path}
strokeLinecap='butt'
stroke={enableLinearGradient ? 'url(#grad)' : color}
strokeWidth={cellSize}
/>
</G>
{logo &&
renderLogo({
size,
logo,
logoSize,
logoBackgroundColor,
logoMargin,
logoBorderRadius
})}
</Svg>
)
}
export default QRCode