@@ -66,6 +66,11 @@ <h2>QSL Card Designer (QSLカードデザイナー)</h2>
6666 < label > QSL Card Background Image (QSLカード背景画像):
6767 < input type ="file " class ="bg-image-input " id ="bgInput " accept ="image/* ">
6868 </ label >
69+ < div style ="margin-top:8px; ">
70+ < button class ="btn " id ="toggleSizeMode " onclick ="toggleDisplayMode() " style ="width:100%;font-size:11px;padding:4px; ">
71+ Mode: Fit to Screen (画面に合わせる)
72+ </ button >
73+ </ div >
6974 </ div >
7075 < div style ="margin-top:18px; ">
7176 < button class ="btn " onclick ="downloadAsPNG() " style ="width:100%; "> Download as PNG (PNGとしてダウンロード)</ button >
@@ -131,6 +136,8 @@ <h2>QSL Card Designer (QSLカードデザイナー)</h2>
131136let movingFieldIdx = null , offsetX = 0 , offsetY = 0 ;
132137let resizingFieldIdx = null , resizeStartX = 0 , resizeStartY = 0 , startWidth = 0 , startHeight = 0 ;
133138let cardWidth = 500 , cardHeight = 320 ;
139+ let displayMode = 'fit-screen' ; // 'fit-screen' or 'full-size'
140+ let currentBgImage = null ; // Store current background image
134141
135142const defaultFields = [
136143 { name : "STATION_CALLSIGN" , label : "Station Callsign (無線局コールサイン)" } ,
@@ -321,6 +328,13 @@ <h2>QSL Card Designer (QSLカードデザイナー)</h2>
321328 return ;
322329 }
323330 const url = URL . createObjectURL ( file ) ;
331+ currentBgImage = { file : file , url : url } ; // Store for mode switching
332+ loadBackgroundImage ( img , area ) ;
333+ img . src = url ;
334+ img . style . display = '' ;
335+ } ) ;
336+
337+ function loadBackgroundImage ( img , area ) {
324338 img . onload = function ( ) {
325339 const naturalWidth = img . naturalWidth ;
326340 const naturalHeight = img . naturalHeight ;
@@ -343,35 +357,60 @@ <h2>QSL Card Designer (QSLカードデザイナー)</h2>
343357 }
344358 }
345359
346- // 画面サイズを取得(サイドバーとマージンを考慮)
347- const designerRect = document . querySelector ( '.designer' ) . getBoundingClientRect ( ) ;
348- const maxWidth = Math . min ( scaledWidth , window . innerWidth - designerRect . left - 60 ) ;
349- const maxHeight = Math . min ( scaledHeight , window . innerHeight - designerRect . top - 100 ) ;
350-
351- // アスペクト比を維持しながら画面サイズに収める
352- const aspectRatio = scaledWidth / scaledHeight ;
353- if ( scaledWidth > maxWidth || scaledHeight > maxHeight ) {
354- if ( maxWidth / aspectRatio <= maxHeight ) {
355- cardWidth = maxWidth ;
356- cardHeight = maxWidth / aspectRatio ;
360+ if ( displayMode === 'fit-screen' ) {
361+ // 画面サイズに合わせるモード
362+ const designerRect = document . querySelector ( '.designer' ) . getBoundingClientRect ( ) ;
363+ const maxWidth = Math . min ( scaledWidth , window . innerWidth - designerRect . left - 60 ) ;
364+ const maxHeight = Math . min ( scaledHeight , window . innerHeight - designerRect . top - 100 ) ;
365+
366+ const aspectRatio = scaledWidth / scaledHeight ;
367+ if ( scaledWidth > maxWidth || scaledHeight > maxHeight ) {
368+ if ( maxWidth / aspectRatio <= maxHeight ) {
369+ cardWidth = maxWidth ;
370+ cardHeight = maxWidth / aspectRatio ;
371+ } else {
372+ cardWidth = maxHeight * aspectRatio ;
373+ cardHeight = maxHeight ;
374+ }
357375 } else {
358- cardWidth = maxHeight * aspectRatio ;
359- cardHeight = maxHeight ;
376+ cardWidth = scaledWidth ;
377+ cardHeight = scaledHeight ;
360378 }
361379 } else {
380+ // フルサイズモード(最大1900px)
362381 cardWidth = scaledWidth ;
363382 cardHeight = scaledHeight ;
364383 }
365-
384+
366385 area . classList . add ( 'has-bg' ) ;
367386 area . style . width = cardWidth + 'px' ;
368387 area . style . height = cardHeight + 'px' ;
369388 updatePreviewSize ( ) ;
370389 updateDesignerArea ( ) ;
371390 } ;
372- img . src = url ;
373- img . style . display = '' ;
374- } ) ;
391+ }
392+
393+ function toggleDisplayMode ( ) {
394+ const btn = document . getElementById ( 'toggleSizeMode' ) ;
395+ if ( displayMode === 'fit-screen' ) {
396+ displayMode = 'full-size' ;
397+ btn . textContent = 'Mode: Full Size (フルサイズ)' ;
398+ } else {
399+ displayMode = 'fit-screen' ;
400+ btn . textContent = 'Mode: Fit to Screen (画面に合わせる)' ;
401+ }
402+
403+ // 背景画像がある場合は再読み込み
404+ if ( currentBgImage ) {
405+ const img = document . getElementById ( 'designerBg' ) ;
406+ const area = document . getElementById ( 'designerArea' ) ;
407+ loadBackgroundImage ( img , area ) ;
408+ // Force reload by resetting src
409+ const currentSrc = img . src ;
410+ img . src = '' ;
411+ img . src = currentSrc ;
412+ }
413+ }
375414
376415// Designer area preview (fields positioning, update on qso change)
377416function updateDesignerArea ( ) {
@@ -580,7 +619,9 @@ <h2>QSL Card Designer (QSLカードデザイナー)</h2>
580619
581620function updatePreviewSize ( ) {
582621 const sizeText = document . getElementById ( 'previewSize' ) ;
583- sizeText . textContent = `Preview Area (プレビューエリア) (${ cardWidth } ×${ cardHeight } px)` ;
622+ const w = Math . round ( cardWidth ) ;
623+ const h = Math . round ( cardHeight ) ;
624+ sizeText . textContent = `Preview Area (プレビューエリア) (${ w } ×${ h } px)` ;
584625}
585626
586627// On window resize (for bg images)
0 commit comments