Skip to content

Commit 7cca471

Browse files
authored
Merge pull request #14 from shvyac/claude/practical-turing
fix: move buttons to designer frame and fix PNG output resolution
2 parents a9d87e4 + c71b066 commit 7cca471

File tree

1 file changed

+35
-23
lines changed

1 file changed

+35
-23
lines changed

QSL_card_designer.html

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,6 @@ <h2>QSL Card Designer (QSLカードデザイナー)</h2>
3131
<label>QSL Card Background Image (QSLカード背景画像):
3232
<input type="file" class="bg-image-input" id="bgInput" accept="image/*">
3333
</label>
34-
<div style="margin-top:8px;">
35-
<button class="btn" id="toggleSizeMode" onclick="toggleDisplayMode()" style="width:100%;font-size:11px;padding:4px;">
36-
Mode: Fit to Screen (画面に合わせる)
37-
</button>
38-
</div>
3934
</div>
4035
<div style="margin-top:18px;">
4136
<label>Import ADIF File (ADIFファイルをインポート): <input type="file" id="adifInput" accept=".adi,.adif"></label>
@@ -62,9 +57,6 @@ <h2>QSL Card Designer (QSLカードデザイナー)</h2>
6257
<div class="qso-list" id="qsoListDiv" style="display:none;margin-top:18px;">
6358
<label>Select QSO (QSO選択): <br><select id="qsoSelect"></select></label>
6459
</div>
65-
<div style="margin-top:18px;">
66-
<button class="btn" onclick="downloadAsPNG()" style="width:100%;">Download as PNG (PNGとしてダウンロード)</button>
67-
</div>
6860
</div>
6961
<div class="designer">
7062
<div style="text-align:center;"><b id="previewSize">Preview Area (プレビューエリア) (500×320 px)</b></div>
@@ -73,6 +65,12 @@ <h2>QSL Card Designer (QSLカードデザイナー)</h2>
7365
<img id="designerBg" alt="bg" style="display: none;" />
7466
<!-- movable fields appended here -->
7567
</div>
68+
<div style="margin-top:10px;display:flex;gap:10px;">
69+
<button class="btn" id="toggleSizeMode" onclick="toggleDisplayMode()" style="flex:1;font-size:11px;padding:6px;">
70+
Mode: Fit to Screen (画面に合わせる)
71+
</button>
72+
<button class="btn" onclick="downloadAsPNG()" style="flex:1;">Download as PNG (PNGとしてダウンロード)</button>
73+
</div>
7674
</div>
7775
</div>
7876

@@ -125,7 +123,8 @@ <h2>QSL Card Designer (QSLカードデザイナー)</h2>
125123
];
126124
let movingFieldIdx = null, offsetX = 0, offsetY = 0;
127125
let resizingFieldIdx = null, resizeStartX = 0, resizeStartY = 0, startWidth = 0, startHeight = 0;
128-
let cardWidth = 500, cardHeight = 320;
126+
let cardWidth = 500, cardHeight = 320; // preview (screen) dimensions
127+
let fullCardWidth = 500, fullCardHeight = 320; // full-resolution output dimensions
129128
let displayMode = 'fit-screen'; // 'fit-screen' or 'full-size'
130129
let currentBgImage = null; // Store current background image
131130

@@ -331,6 +330,8 @@ <h2>QSL Card Designer (QSLカードデザイナー)</h2>
331330
area.classList.remove('has-bg');
332331
cardWidth = 500;
333332
cardHeight = 320;
333+
fullCardWidth = 500;
334+
fullCardHeight = 320;
334335
area.style.width = cardWidth + 'px';
335336
area.style.height = cardHeight + 'px';
336337
updatePreviewSize();
@@ -367,6 +368,10 @@ <h2>QSL Card Designer (QSLカードデザイナー)</h2>
367368
}
368369
}
369370

371+
// Always store full-resolution dimensions for PNG export
372+
fullCardWidth = scaledWidth;
373+
fullCardHeight = scaledHeight;
374+
370375
if (displayMode === 'fit-screen') {
371376
// 画面サイズに合わせるモード
372377
const designerRect = document.querySelector('.designer').getBoundingClientRect();
@@ -631,7 +636,10 @@ <h2>QSL Card Designer (QSLカードデザイナー)</h2>
631636
const sizeText = document.getElementById('previewSize');
632637
const w = Math.round(cardWidth);
633638
const h = Math.round(cardHeight);
634-
sizeText.textContent = `Preview Area (プレビューエリア) (${w}×${h} px)`;
639+
const fw = Math.round(fullCardWidth);
640+
const fh = Math.round(fullCardHeight);
641+
const suffix = (fw !== w || fh !== h) ? ` → Output: ${fw}×${fh} px` : '';
642+
sizeText.textContent = `Preview Area (プレビューエリア) (${w}×${h} px)${suffix}`;
635643
}
636644

637645
// On window resize (for bg images)
@@ -643,29 +651,33 @@ <h2>QSL Card Designer (QSLカードデザイナー)</h2>
643651
const area = document.getElementById('designerArea');
644652
const bgImg = document.getElementById('designerBg');
645653

646-
// Canvasを作成
654+
// Canvasを作成(フル解像度で出力)
647655
const canvas = document.createElement('canvas');
648-
canvas.width = cardWidth;
649-
canvas.height = cardHeight;
656+
canvas.width = fullCardWidth;
657+
canvas.height = fullCardHeight;
650658
const ctx = canvas.getContext('2d');
651-
659+
660+
// Scale factor from preview size to full output size
661+
const scaleX = fullCardWidth / cardWidth;
662+
const scaleY = fullCardHeight / cardHeight;
663+
652664
// 背景色を白に設定(背景画像がない場合)
653665
ctx.fillStyle = '#eee';
654-
ctx.fillRect(0, 0, cardWidth, cardHeight);
655-
666+
ctx.fillRect(0, 0, fullCardWidth, fullCardHeight);
667+
656668
// 背景画像を描画
657669
if (bgImg.style.display !== 'none' && bgImg.complete && bgImg.naturalWidth > 0) {
658-
ctx.drawImage(bgImg, 0, 0, cardWidth, cardHeight);
670+
ctx.drawImage(bgImg, 0, 0, fullCardWidth, fullCardHeight);
659671
}
660-
661-
// フィールドを描画
672+
673+
// フィールドを描画(プレビュー座標をフル解像度にスケール)
662674
const rec = adifRecords[qsoIdx] || {};
663675
designerFields.forEach((f) => {
664676
const v = (rec[f.name] !== undefined ? rec[f.name] : "");
665-
const w = f.width || 160;
666-
const h = f.height || 16;
667-
const x = f.x || 0;
668-
const y = f.y || 0;
677+
const w = (f.width || 160) * scaleX;
678+
const h = (f.height || 16) * scaleY;
679+
const x = (f.x || 0) * scaleX;
680+
const y = (f.y || 0) * scaleY;
669681

670682
// フィールドの背景(透明なのでスキップ)
671683
// テキストを描画

0 commit comments

Comments
 (0)