76 lines
2.2 KiB
TypeScript
76 lines
2.2 KiB
TypeScript
import { useEffect, useState } from 'react';
|
|
import { View, Canvas } from '@tarojs/components';
|
|
import Taro from '@tarojs/taro';
|
|
import {
|
|
REDEEM_QR_DISPLAY_SIZE,
|
|
buildRedeemQrDataUrl,
|
|
drawRedeemQrOnCanvas,
|
|
} from '../lib/redeem-qr';
|
|
|
|
const CANVAS_ID = 'redeem-qr-canvas';
|
|
|
|
type RedeemQrCodeProps = {
|
|
token: string;
|
|
};
|
|
|
|
function drawOnWeappCanvas(token: string) {
|
|
const page = Taro.getCurrentInstance().page;
|
|
const query = page ? Taro.createSelectorQuery().in(page) : Taro.createSelectorQuery();
|
|
query
|
|
.select(`#${CANVAS_ID}`)
|
|
.fields({ node: true, size: true })
|
|
.exec((res) => {
|
|
const item = res[0] as { node?: WechatMiniprogram.Canvas; width?: number; height?: number } | undefined;
|
|
const canvas = item?.node;
|
|
if (!canvas) return;
|
|
|
|
const layoutW = item.width || REDEEM_QR_DISPLAY_SIZE;
|
|
const layoutH = item.height || REDEEM_QR_DISPLAY_SIZE;
|
|
const drawSize = Math.min(layoutW, layoutH);
|
|
|
|
const ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
|
|
const dpr = Taro.getSystemInfoSync().pixelRatio || 2;
|
|
canvas.width = layoutW * dpr;
|
|
canvas.height = layoutH * dpr;
|
|
ctx.scale(dpr, dpr);
|
|
drawRedeemQrOnCanvas(ctx, token, drawSize);
|
|
});
|
|
}
|
|
|
|
export default function RedeemQrCode({ token }: RedeemQrCodeProps) {
|
|
const [imgSrc, setImgSrc] = useState('');
|
|
const isWeapp = process.env.TARO_ENV === 'weapp';
|
|
|
|
useEffect(() => {
|
|
if (!token) {
|
|
setImgSrc('');
|
|
return;
|
|
}
|
|
|
|
if (isWeapp) {
|
|
const timer = setTimeout(() => drawOnWeappCanvas(token), 120);
|
|
return () => clearTimeout(timer);
|
|
}
|
|
|
|
let cancelled = false;
|
|
void buildRedeemQrDataUrl(token).then((url) => {
|
|
if (!cancelled) setImgSrc(url);
|
|
});
|
|
return () => {
|
|
cancelled = true;
|
|
};
|
|
}, [token, isWeapp]);
|
|
|
|
return (
|
|
<View className="redeem-qr-box">
|
|
<View className="redeem-qr-placeholder" />
|
|
{isWeapp ? (
|
|
<Canvas type="2d" id={CANVAS_ID} canvasId={CANVAS_ID} className="redeem-qr-canvas" />
|
|
) : imgSrc ? (
|
|
<View className="redeem-qr-img" style={{ backgroundImage: `url(${imgSrc})` }} />
|
|
) : null}
|
|
<View className="redeem-qr-scanline" />
|
|
</View>
|
|
);
|
|
}
|