diff --git a/src/components/SignatureOverlay.css b/src/components/SignatureOverlay.css index 44ca178..a62ed8d 100644 --- a/src/components/SignatureOverlay.css +++ b/src/components/SignatureOverlay.css @@ -17,19 +17,6 @@ box-sizing: border-box; } -/* Phones in portrait: rotate the whole stage to use landscape space */ -@media (orientation: portrait) and (max-width: 820px) { - .signature-overlay-stage { - inset: auto; - top: 50%; - left: 50%; - width: 100dvh; - height: 100dvw; - transform: translate(-50%, -50%) rotate(90deg); - transform-origin: center center; - } -} - .signature-overlay-bar { display: flex; align-items: center; @@ -50,7 +37,6 @@ border-radius: 12px; background: #ffffff; overflow: hidden; - /* keep room from screen edges so iOS back-swipe doesn't intercept */ margin: 0 4px; } @@ -73,3 +59,41 @@ .signature-overlay-actions { flex-shrink: 0; } + +.signature-overlay-rotate { + position: absolute; + inset: 0; + z-index: 1; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 24px; + gap: 14px; + background: #f8fafc; + text-align: center; +} + +.signature-overlay-rotate-icon { + font-size: 64px; + color: #1677ff; + animation: signature-rotate-hint 1.6s ease-in-out infinite; +} + +@keyframes signature-rotate-hint { + 0%, 100% { transform: rotate(0deg); } + 50% { transform: rotate(90deg); } +} + +.signature-overlay-rotate-text { + font-size: 17px; + font-weight: 500; + color: #1f2937; + margin: 0; +} + +.signature-overlay-rotate-hint { + font-size: 13px; + color: #6b7280; + margin: 0 0 8px; +} diff --git a/src/components/SignatureOverlay.tsx b/src/components/SignatureOverlay.tsx index 73cfcd3..f285c18 100644 --- a/src/components/SignatureOverlay.tsx +++ b/src/components/SignatureOverlay.tsx @@ -1,5 +1,6 @@ import { useEffect, useRef, useState } from 'react'; import { Button } from 'antd'; +import { RotateRightOutlined } from '@ant-design/icons'; import SignaturePad, { type SignaturePadHandle } from './SignaturePad'; import './SignatureOverlay.css'; @@ -9,26 +10,38 @@ interface SignatureOverlayProps { onConfirm: (dataUrl: string) => void; } +const isLandscapeNow = () => + typeof window !== 'undefined' && window.matchMedia('(orientation: landscape)').matches; + function SignatureOverlay({ open, onCancel, onConfirm }: SignatureOverlayProps) { const padRef = useRef(null); - const [data, setData] = useState(''); + const [, setData] = useState(''); + const [landscape, setLandscape] = useState(isLandscapeNow); useEffect(() => { if (!open) return; + const mq = window.matchMedia('(orientation: landscape)'); + const update = () => setLandscape(mq.matches); + update(); + mq.addEventListener('change', update); + const orientation = (screen as Screen & { - orientation?: { lock?: (o: string) => Promise }; + orientation?: { lock?: (o: string) => Promise; unlock?: () => void }; }).orientation; if (orientation?.lock) { orientation.lock('landscape').catch(() => { - // ignore; iOS Safari etc. don't permit lock outside fullscreen + // ignore; iOS Safari and most browsers refuse outside fullscreen }); } const prevOverflow = document.body.style.overflow; document.body.style.overflow = 'hidden'; + return () => { + mq.removeEventListener('change', update); document.body.style.overflow = prevOverflow; + orientation?.unlock?.(); }; }, [open]); @@ -40,15 +53,29 @@ function SignatureOverlay({ open, onCancel, onConfirm }: SignatureOverlayProps) }; const handleConfirm = () => { - if (padRef.current?.isEmpty()) return; - const url = padRef.current?.getDataURL() || data; - if (!url) return; - onConfirm(url); + const pad = padRef.current; + if (!pad || pad.isEmpty()) return; + onConfirm(pad.getDataURL()); }; return (
-
+ {!landscape && ( +
+ +

请将手机横置以开始签名

+

+ 如果无法旋转,请检查手机是否锁定了竖屏方向 +

+ +
+ )} + {/* SignaturePad stays mounted so its strokes survive accidental rotation flips */} +