@@ -11,6 +11,19 @@ interface Props {
1111 onReset : ( ) => void
1212}
1313
14+ const DESKTOP_CERT_UI_SCALE = 0.604
15+ const CERT_RENDER_WIDTH = 794
16+ const CERT_RENDER_HEIGHT = 1123
17+
18+ function clamp ( value : number , min : number , max : number ) {
19+ return Math . min ( max , Math . max ( min , value ) )
20+ }
21+
22+ function getCertificateUiScale ( viewportWidth : number ) {
23+ if ( viewportWidth > 900 ) return DESKTOP_CERT_UI_SCALE
24+ return clamp ( ( viewportWidth - 170 ) / CERT_RENDER_WIDTH , 0.18 , 0.32 )
25+ }
26+
1427const SOCIAL_BG = '#E8E8E8'
1528const SOCIAL_EXPORT_FORMATS = {
1629 instagramPortrait : { width : 1080 , height : 1350 , padding : 64 , filename : 'instagram-portrait' } ,
@@ -66,6 +79,7 @@ export default function CertificateCard({ cert, onReset }: Props) {
6679 const visibleStampRef = useRef < HTMLDivElement > ( null )
6780 const exportStampRef = useRef < HTMLDivElement > ( null )
6881 const [ visible , setVisible ] = useState ( false )
82+ const [ uiScale , setUiScale ] = useState ( DESKTOP_CERT_UI_SCALE )
6983 const [ isGeneratingShare , setIsGeneratingShare ] = useState ( false )
7084 const [ showInlineShare , setShowInlineShare ] = useState ( false )
7185 const [ copied , setCopied ] = useState ( false )
@@ -75,6 +89,14 @@ export default function CertificateCard({ cert, onReset }: Props) {
7589 return ( ) => clearTimeout ( t )
7690 } , [ ] )
7791
92+ useEffect ( ( ) => {
93+ if ( typeof window === 'undefined' ) return
94+ const applyScale = ( ) => setUiScale ( getCertificateUiScale ( window . innerWidth ) )
95+ applyScale ( )
96+ window . addEventListener ( 'resize' , applyScale )
97+ return ( ) => window . removeEventListener ( 'resize' , applyScale )
98+ } , [ ] )
99+
78100 async function exportBlob ( pixelRatio : number , watermark = false ) : Promise < Blob | null > {
79101 if ( ! exportCardRef . current ) return null
80102 const wrapper = wrapperRef . current
@@ -84,8 +106,8 @@ export default function CertificateCard({ cert, onReset }: Props) {
84106 cacheBust : true ,
85107 pixelRatio,
86108 backgroundColor : '#FAF6EF' ,
87- width : 794 ,
88- height : 1123 ,
109+ width : CERT_RENDER_WIDTH ,
110+ height : CERT_RENDER_HEIGHT ,
89111 } )
90112 if ( ! watermark && exportStampRef . current ) exportStampRef . current . style . visibility = ''
91113 if ( wrapper ) wrapper . style . zoom = ''
@@ -280,11 +302,11 @@ export default function CertificateCard({ cert, onReset }: Props) {
280302 < div
281303 ref = { wrapperRef }
282304 style = { {
283- width : '794px' ,
305+ width : ` ${ CERT_RENDER_WIDTH } px` ,
284306 flexShrink : 0 ,
285307 transformOrigin : 'top center' ,
286- transform : ' scale(var(--cert-ui-scale, 0.604))' ,
287- marginBottom : ' calc((1123px * var(--cert-ui-scale, 0.604)) - 1123px)' ,
308+ transform : ` scale(${ uiScale } )` ,
309+ marginBottom : ` calc((${ CERT_RENDER_HEIGHT } px * ${ uiScale } ) - ${ CERT_RENDER_HEIGHT } px)` ,
288310 } }
289311 >
290312 < CertificateFixed
@@ -305,8 +327,8 @@ export default function CertificateCard({ cert, onReset }: Props) {
305327 position : 'fixed' ,
306328 left : '-10000px' ,
307329 top : 0 ,
308- width : '794px' ,
309- height : '1123px' ,
330+ width : ` ${ CERT_RENDER_WIDTH } px` ,
331+ height : ` ${ CERT_RENDER_HEIGHT } px` ,
310332 opacity : 0 ,
311333 pointerEvents : 'none' ,
312334 overflow : 'hidden' ,
0 commit comments