diff --git a/index.d.ts b/index.d.ts index f3700cd..fcc26ff 100644 --- a/index.d.ts +++ b/index.d.ts @@ -1,5 +1,5 @@ import * as React from "react"; -import { Image, ImageSourcePropType } from "react-native"; +import { ImageSourcePropType } from "react-native"; declare class QRCode extends React.PureComponent {} @@ -35,6 +35,8 @@ export interface QRCodeProps { getRef?: (c: any) => any; /* error correction level */ ecl?: "L" | "M" | "Q" | "H"; + /* Renderind mode */ + mode?: "default" | "rounded"; /* error handler called when matrix fails to generate */ onError?: Function; } diff --git a/src/index.js b/src/index.js index 99c2e68..082dc35 100644 --- a/src/index.js +++ b/src/index.js @@ -1,16 +1,17 @@ import React, { useMemo } from 'react' import Svg, { + ClipPath, Defs, G, - Path, - Rect, Image, - ClipPath, LinearGradient, + Path, + Rect, Stop } from 'react-native-svg' import genMatrix from './genMatrix' import transformMatrixIntoPath from './transformMatrixIntoPath' +import transformMatrixIntoRoundedPath from './transformMatrixIntoRoundedPath' const renderLogo = ({ size, @@ -81,12 +82,18 @@ const QRCode = ({ gradientDirection = ['0%', '0%', '100%', '100%'], linearGradient = ['rgb(255,0,0)', 'rgb(0,255,255)'], ecl = 'M', + mode = 'default', getRef, onError }) => { const result = useMemo(() => { try { - return transformMatrixIntoPath(genMatrix(value, ecl), size) + const matrix = genMatrix(value, ecl); + switch (mode) { + case 'rounded': + return transformMatrixIntoRoundedPath(matrix, size); + default: return transformMatrixIntoPath(matrix, size); + } } catch (error) { if (onError && typeof onError === 'function') { onError(error) @@ -95,7 +102,7 @@ const QRCode = ({ throw error } } - }, [value, size, ecl]) + }, [value, size, ecl, mode]) if (!result) { return null @@ -135,15 +142,23 @@ const QRCode = ({ height={size + quietZone * 2} fill={backgroundColor} /> - - + + {mode === 'default' ? - + : null} + {mode === 'rounded' ? + + : null} {logo && renderLogo({ size, diff --git a/src/svg-rounded-rectangle-path.js b/src/svg-rounded-rectangle-path.js new file mode 100644 index 0000000..1e7a7eb --- /dev/null +++ b/src/svg-rounded-rectangle-path.js @@ -0,0 +1,26 @@ +/** + * Get path data for a rounded rectangle. Allows for different radius on each corner. + * @param {Number} w Width of rounded rectangle + * @param {Number} h Height of rounded rectangle + * @param {Number} tlr Top left corner radius + * @param {Number} trr Top right corner radius + * @param {Number} brr Bottom right corner radius + * @param {Number} blr Bottom left corner radius + * @return {String} Rounded rectangle SVG path data + */ + + +var roundedRectData = (positionX, positionY, width, height, topLeftRadius, topRightRadius, bottomRightRadius, bottomLeftRadius) => { + return `M${positionX + topLeftRadius},${positionY}\ + h${width - (topLeftRadius + topRightRadius)}\ + a${topRightRadius},${topRightRadius} 0 0 1 ${topRightRadius},${topRightRadius}\ + v${height - (topRightRadius + bottomRightRadius)}\ + a${bottomRightRadius},${bottomRightRadius} 0 0 1 -${bottomRightRadius},${bottomRightRadius}\ + h-${width - (bottomLeftRadius + bottomRightRadius)}\ + a${bottomLeftRadius},${bottomLeftRadius} 0 0 1 -${bottomLeftRadius},-${bottomLeftRadius}\ + v-${height - (topLeftRadius + bottomLeftRadius)}\ + a${topLeftRadius},${topLeftRadius} 0 0 1 ${topLeftRadius},-${topLeftRadius}\ + z`; + } + +export default roundedRectData \ No newline at end of file diff --git a/src/transformMatrixIntoRoundedPath.js b/src/transformMatrixIntoRoundedPath.js new file mode 100644 index 0000000..9a9304f --- /dev/null +++ b/src/transformMatrixIntoRoundedPath.js @@ -0,0 +1,29 @@ +import roundedRectData from "./svg-rounded-rectangle-path"; + +export default function transformMatrixIntoRoundedPath(matrix, size) { + const cellSize = size / matrix.length + let path = '' + + function drawRect(x, y) { + const radius = cellSize /2; + const tlr = matrix[x-1]?.[y] || matrix[x][y-1] ? 0 : radius; + const trr = matrix[x+1]?.[y] || matrix[x][y-1] ? 0 : radius; + const brr = matrix[x+1]?.[y] || matrix[x][y+1] ? 0 : radius; + const blr = matrix[x-1]?.[y] || matrix[x][y+1] ? 0 : radius; + return roundedRectData(cellSize * x, cellSize * y, cellSize, cellSize, tlr, trr, brr, blr) + ' ' + } + + matrix.forEach((row, i) => { + let needDraw = false + row.forEach((column, j) => { + if (column) { + path += drawRect(i, j) + } + }) + }) + + return { + cellSize, + path + } +} \ No newline at end of file