fix(mobile): inject QR directly into SVG XML for pixel-perfect placement
This commit is contained in:
@@ -3,7 +3,6 @@ import { router } from "expo-router";
|
||||
import {
|
||||
ActivityIndicator,
|
||||
Alert,
|
||||
Image,
|
||||
Pressable,
|
||||
ScrollView,
|
||||
Share,
|
||||
@@ -45,6 +44,23 @@ export default function QrScreen() {
|
||||
const activePreset: QrStandPreset = (QR_STAND_PRESETS[selectedKey] || Object.values(QR_STAND_PRESETS)[0])!;
|
||||
const currentSvgRaw = MOBILE_SVG_TEMPLATES[selectedKey] || MOBILE_SVG_TEMPLATES["qr-4"] || Object.values(MOBILE_SVG_TEMPLATES)[0] || "";
|
||||
|
||||
// Inject the live QR code image directly into the SVG's #qr-placeholder group
|
||||
function buildSvgWithQr(svgRaw: string, pngBase64: string): string {
|
||||
const qrImgTag = `<g id="qr-placeholder" transform="translate(90, 215)">
|
||||
<rect width="220" height="220" rx="20" fill="#FFFFFF"/>
|
||||
<image href="data:image/png;base64,${pngBase64}" x="10" y="10" width="200" height="200" preserveAspectRatio="xMidYMid meet"/>
|
||||
</g>`;
|
||||
// Replace the entire qr-placeholder group
|
||||
const replaced = svgRaw.replace(
|
||||
/<g id="qr-placeholder"[\s\S]*?<\/g>/,
|
||||
qrImgTag
|
||||
);
|
||||
// Also ensure the SVG scales properly by setting width/height to 100%
|
||||
return replaced
|
||||
.replace(/width="400"/, 'width="100%"')
|
||||
.replace(/height="650"/, 'height="100%"');
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
const activeRest = await getActiveRestaurant();
|
||||
@@ -301,47 +317,25 @@ export default function QrScreen() {
|
||||
}}
|
||||
>
|
||||
<ViewShot ref={viewShotRef} options={{ format: "png", quality: 1.0 }}>
|
||||
{/* SVG with QR code injected directly — no overlay, pixel-perfect */}
|
||||
<View
|
||||
style={{
|
||||
width: 300,
|
||||
height: 487.5,
|
||||
borderRadius: 24,
|
||||
overflow: "hidden",
|
||||
position: "relative",
|
||||
backgroundColor: "#0C0C0E",
|
||||
}}
|
||||
>
|
||||
{/* Exact Vector SVG Artwork */}
|
||||
{currentSvgRaw ? (
|
||||
<SvgXml xml={currentSvgRaw} width={300} height={487.5} />
|
||||
) : null}
|
||||
|
||||
{/* Centered QR Code Box Overlay */}
|
||||
<View
|
||||
style={{
|
||||
position: "absolute",
|
||||
top: 161.25, // (215 / 650) * 487.5
|
||||
left: 67.5, // (90 / 400) * 300
|
||||
width: 165, // (220 / 400) * 300
|
||||
height: 165,
|
||||
borderRadius: 15,
|
||||
backgroundColor: "#FFFFFF",
|
||||
padding: 8,
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
shadowColor: "#000",
|
||||
shadowOffset: { width: 0, height: 4 },
|
||||
shadowOpacity: 0.25,
|
||||
shadowRadius: 8,
|
||||
elevation: 4,
|
||||
}}
|
||||
>
|
||||
<Image
|
||||
source={{ uri: `data:image/png;base64,${qr.pngBase64}` }}
|
||||
style={{ width: "100%", height: "100%", borderRadius: 8 }}
|
||||
resizeMode="contain"
|
||||
<SvgXml
|
||||
xml={buildSvgWithQr(currentSvgRaw, qr.pngBase64)}
|
||||
width={300}
|
||||
height={487.5}
|
||||
viewBox="0 0 400 650"
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
/>
|
||||
</View>
|
||||
) : null}
|
||||
</View>
|
||||
</ViewShot>
|
||||
</View>
|
||||
|
||||
Reference in New Issue
Block a user