UNPKG

alpha-version-dce-check-in-ui

Version:

UI for taking attendance and checking people in.

155 lines (131 loc) 4.71 kB
// Import QR generator import QRCode from 'qrcode'; /*------------------------------------------------------------------------*/ /* ------------------------------ Constants ----------------------------- */ /*------------------------------------------------------------------------*/ /*----------------------------------------*/ /* ---------- Adjustable Params --------- */ /*----------------------------------------*/ // Width of generated image const WIDTH_PX = 800; // Card styling const BACKGROUND_COLOR = '#A41034'; // Harvard Crimson const WIDTH_TO_HEIGHT_RATIO = 1.2; const CARD_BORDER_RADIUS_RATIO = 0.06; // Text styling const TEXT_COLOR = 'white'; const TEXT = 'Scan to Check In'; const TEXT_SIZE_RATIO = 0.11; const TEXT_TO_TOP_BORDER_RATIO = 0.1; // QR code styling const CARD_TO_QR_CODE_WIDTH_RATIO = 0.85; const QR_BORDER_RADIUS_RATIO = 0.04; /*----------------------------------------*/ /* ---- Dynamically-generated Params ---- */ /*----------------------------------------*/ // Don't customize the look here, these are based on params above // Canvas size const canvasWidth = WIDTH_PX * window.devicePixelRatio; const canvasHeight = canvasWidth * WIDTH_TO_HEIGHT_RATIO; // Card size and location const cardWidth = WIDTH_PX; const cardHeight = WIDTH_TO_HEIGHT_RATIO * WIDTH_PX; const cardRadius = CARD_BORDER_RADIUS_RATIO * WIDTH_PX; // Text size and location const textFontSize = TEXT_SIZE_RATIO * WIDTH_PX; const textX = WIDTH_PX / 2; const textY = TEXT_TO_TOP_BORDER_RATIO * WIDTH_PX; // Sub-text size and location const subTextFontSize = textFontSize / 1.6; const subTextX = textX; const subTextY = 2 * textY; // QR code size and location const qrWidth = WIDTH_PX * CARD_TO_QR_CODE_WIDTH_RATIO; const qrX = WIDTH_PX * (1 - CARD_TO_QR_CODE_WIDTH_RATIO) / 2; const qrY = (WIDTH_PX * WIDTH_TO_HEIGHT_RATIO) - qrX - (WIDTH_PX * CARD_TO_QR_CODE_WIDTH_RATIO) + (TEXT_TO_TOP_BORDER_RATIO * WIDTH_PX / 5.25); const qrRadius = QR_BORDER_RADIUS_RATIO * WIDTH_PX; /*------------------------------------------------------------------------*/ /* ---------------------------- QR Generator ---------------------------- */ /*------------------------------------------------------------------------*/ /** * Create a QR code card, with specified text, QR code value, and background color. * Could be made server-side via the node-canvas package * @author Benedikt Arnarsson * @author Gabe Abrams * @param value the URL which the QR code will hold * @returns the dataURL representing the QR card image */ const getQrCardImg = async (value: string, subText=''): Promise<string> => { // Create invisible canvas // Reference: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html#non-null-assertion-operator const canvas = document.createElement('canvas'); const context = canvas.getContext('2d')!; context.canvas.hidden = true; // Configure canvas size // See SO: https://stackoverflow.com/a/65124939 canvas.width = canvasWidth; canvas.height = canvasHeight; context.scale(window.devicePixelRatio, window.devicePixelRatio); // Card background context.beginPath(); context.fillStyle = BACKGROUND_COLOR; context.roundRect( 0, 0, cardWidth, cardHeight, cardRadius, ); context.stroke(); context.fill(); // QR background context.beginPath(); context.fillStyle = 'white'; context.strokeStyle = 'white'; context.roundRect(qrX, qrY, qrWidth, qrWidth, qrRadius); context.stroke(); context.fill(); // Text context.font = `bold ${textFontSize}px arial`; context.textAlign = 'center'; context.textBaseline = 'middle'; context.fillStyle = TEXT_COLOR; context.fillText(TEXT, textX, textY); // Sub-text const formattedSubText = ( subText.length >= 15 ? `${subText.substring(0, 15)}...` : subText ); context.font = `bold ${subTextFontSize}px arial`; context.textAlign = 'center'; context.textBaseline = 'middle'; context.fillStyle = TEXT_COLOR; context.fillText(formattedSubText, subTextX, subTextY); // QR code // > Generate QR code image const qrCodeDataURL = await QRCode.toDataURL( value, { width: qrWidth, margin: 2, color: { light: '#ffffff00', // white, fully transparent }, }, ); // > Convert to HTML Image const qrImg = new Image(); qrImg.src = qrCodeDataURL; // > Wait for image to process/load await new Promise((resolve) => { qrImg.onload = resolve; }); // > Draw image to canvas context.drawImage(qrImg, qrX, qrY, qrWidth, qrWidth); // Return data URL and destroy canvas const qrCard = canvas.toDataURL(); canvas.remove(); return qrCard; }; export default getQrCardImg;