QRCodeCanvas.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. import _extends from "@babel/runtime/helpers/esm/extends";
  2. import _objectSpread from "@babel/runtime/helpers/esm/objectSpread2";
  3. import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
  4. import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
  5. var _excluded = ["value", "size", "level", "bgColor", "fgColor", "includeMargin", "minVersion", "marginSize", "style", "imageSettings"];
  6. import React from 'react';
  7. import { useQRCode } from "./hooks/useQRCode";
  8. import { DEFAULT_BACKGROUND_COLOR, DEFAULT_FRONT_COLOR, DEFAULT_NEED_MARGIN, DEFAULT_LEVEL, DEFAULT_MINVERSION, DEFAULT_SIZE, isSupportPath2d, excavateModules, generatePath } from "./utils";
  9. var QRCodeCanvas = /*#__PURE__*/React.forwardRef(function (props, ref) {
  10. var value = props.value,
  11. _props$size = props.size,
  12. size = _props$size === void 0 ? DEFAULT_SIZE : _props$size,
  13. _props$level = props.level,
  14. level = _props$level === void 0 ? DEFAULT_LEVEL : _props$level,
  15. _props$bgColor = props.bgColor,
  16. bgColor = _props$bgColor === void 0 ? DEFAULT_BACKGROUND_COLOR : _props$bgColor,
  17. _props$fgColor = props.fgColor,
  18. fgColor = _props$fgColor === void 0 ? DEFAULT_FRONT_COLOR : _props$fgColor,
  19. _props$includeMargin = props.includeMargin,
  20. includeMargin = _props$includeMargin === void 0 ? DEFAULT_NEED_MARGIN : _props$includeMargin,
  21. _props$minVersion = props.minVersion,
  22. minVersion = _props$minVersion === void 0 ? DEFAULT_MINVERSION : _props$minVersion,
  23. marginSize = props.marginSize,
  24. style = props.style,
  25. imageSettings = props.imageSettings,
  26. otherProps = _objectWithoutProperties(props, _excluded);
  27. var imgSrc = imageSettings === null || imageSettings === void 0 ? void 0 : imageSettings.src;
  28. var _canvas = React.useRef(null);
  29. var _image = React.useRef(null);
  30. var setCanvasRef = React.useCallback(function (node) {
  31. _canvas.current = node;
  32. if (typeof ref === 'function') {
  33. ref(node);
  34. } else if (ref) {
  35. ref.current = node;
  36. }
  37. }, [ref]);
  38. var _React$useState = React.useState(false),
  39. _React$useState2 = _slicedToArray(_React$useState, 2),
  40. setIsImageLoaded = _React$useState2[1];
  41. var _useQRCode = useQRCode({
  42. value: value,
  43. level: level,
  44. minVersion: minVersion,
  45. includeMargin: includeMargin,
  46. marginSize: marginSize,
  47. imageSettings: imageSettings,
  48. size: size
  49. }),
  50. margin = _useQRCode.margin,
  51. cells = _useQRCode.cells,
  52. numCells = _useQRCode.numCells,
  53. calculatedImageSettings = _useQRCode.calculatedImageSettings;
  54. React.useEffect(function () {
  55. if (_canvas.current) {
  56. var canvas = _canvas.current;
  57. var ctx = canvas.getContext('2d');
  58. if (!ctx) {
  59. return;
  60. }
  61. var cellsToDraw = cells;
  62. var image = _image.current;
  63. var haveImageToRender = calculatedImageSettings != null && image !== null && image.complete && image.naturalHeight !== 0 && image.naturalWidth !== 0;
  64. if (haveImageToRender) {
  65. if (calculatedImageSettings.excavation != null) {
  66. cellsToDraw = excavateModules(cells, calculatedImageSettings.excavation);
  67. }
  68. }
  69. var pixelRatio = window.devicePixelRatio || 1;
  70. canvas.height = canvas.width = size * pixelRatio;
  71. var scale = size / numCells * pixelRatio;
  72. ctx.scale(scale, scale);
  73. ctx.fillStyle = bgColor;
  74. ctx.fillRect(0, 0, numCells, numCells);
  75. ctx.fillStyle = fgColor;
  76. if (isSupportPath2d) {
  77. ctx.fill(new Path2D(generatePath(cellsToDraw, margin)));
  78. } else {
  79. cells.forEach(function (row, rdx) {
  80. row.forEach(function (cell, cdx) {
  81. if (cell) {
  82. ctx.fillRect(cdx + margin, rdx + margin, 1, 1);
  83. }
  84. });
  85. });
  86. }
  87. if (calculatedImageSettings) {
  88. ctx.globalAlpha = calculatedImageSettings.opacity;
  89. }
  90. if (haveImageToRender) {
  91. ctx.drawImage(image, calculatedImageSettings.x + margin, calculatedImageSettings.y + margin, calculatedImageSettings.w, calculatedImageSettings.h);
  92. }
  93. }
  94. });
  95. React.useEffect(function () {
  96. setIsImageLoaded(false);
  97. }, [imgSrc]);
  98. var canvasStyle = _objectSpread({
  99. height: size,
  100. width: size
  101. }, style);
  102. var img = null;
  103. if (imgSrc != null) {
  104. img = /*#__PURE__*/React.createElement("img", {
  105. src: imgSrc,
  106. key: imgSrc,
  107. style: {
  108. display: 'none'
  109. },
  110. onLoad: function onLoad() {
  111. setIsImageLoaded(true);
  112. },
  113. ref: _image
  114. // when crossOrigin is not set, the image will be tainted
  115. // and the canvas cannot be exported to an image
  116. ,
  117. crossOrigin: calculatedImageSettings === null || calculatedImageSettings === void 0 ? void 0 : calculatedImageSettings.crossOrigin
  118. });
  119. }
  120. return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("canvas", _extends({
  121. style: canvasStyle,
  122. height: size,
  123. width: size,
  124. ref: setCanvasRef,
  125. role: "img"
  126. }, otherProps)), img);
  127. });
  128. if (process.env.NODE_ENV !== 'production') {
  129. QRCodeCanvas.displayName = 'QRCodeCanvas';
  130. }
  131. export { QRCodeCanvas };