牌位顯示版面調整
This commit is contained in:
@@ -57,6 +57,12 @@
|
||||
<label class="small" for="textHeight">物件高度</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<div class="form-floating mb-3">
|
||||
<input type="text" id="contentHeight" class="form-control form-control-sm mb-2" onchange="Printer.changeSetup('textHeight')" />
|
||||
<label class="small" for="contentHeight">文字高度</label>
|
||||
</div>
|
||||
</div>
|
||||
<%-- <div class="col-6">
|
||||
<div class="form-floating mb-3">
|
||||
<input type="text" id="textBreakCount" class="form-control form-control-sm mb-2" onchange="Printer.changeWidth()" />
|
||||
@@ -266,10 +272,8 @@
|
||||
let wrap = $("<div class='row-wrapper'></div>")
|
||||
let mode = "origin"
|
||||
this.printData.forEach(x => {
|
||||
|
||||
let style = self.allStyle.find(y => y.styleID == x.style);
|
||||
//用來印內容的尺寸
|
||||
//console.log("style.paperSize:", style.paperSize)
|
||||
let size = self.allSize.find(y => y.paperID == style.paperSize);
|
||||
//包含空白用來折的尺寸
|
||||
let printSize = self.allSize.find(y => y.paperID == style.printSize);
|
||||
@@ -299,7 +303,14 @@
|
||||
tabletpaper = $(` <div class="tablet-paper" >
|
||||
</div>`)
|
||||
let img = self.bg.find(y => y.name == style.backendImg);
|
||||
let tablet = JSON.parse(x.f_num_tablet);
|
||||
|
||||
let tablet = {}
|
||||
try {
|
||||
tablet = JSON.parse(x.f_num_tablet);
|
||||
} catch (e) {
|
||||
console.log(x.order_no,x.num,x.print_id,e);
|
||||
return
|
||||
}
|
||||
|
||||
let mid_items = tablet.mid_items;
|
||||
let left_items = tablet.left_items;
|
||||
@@ -345,147 +356,194 @@
|
||||
|
||||
let h = Number(d.height);
|
||||
let w = Number(d.width);
|
||||
//let th = Number(d.textHeight) || h;
|
||||
//let gap = 5; // 對應 span 的 margin-left
|
||||
//let v_gap = Number(d.textSpan)
|
||||
|
||||
//let s = Number(d.fontSize);
|
||||
//let sizes = [];
|
||||
//let base_s_px = s * 1.333;
|
||||
|
||||
//// 1. 模擬排版:找出能讓全體塞入的最佳字體組合
|
||||
//while (s >= 12) {
|
||||
// let short_s_px = s * 1.333*1.1;
|
||||
// let hasShort = mid.some(n => (n.length * short_s_px) <=Number(th) + Number(d.textSpan));
|
||||
|
||||
// let long_s = hasShort ? Math.floor(s * 0.75) : s; // 長字體最多縮小 25%
|
||||
// if (long_s < 12) long_s = 12;
|
||||
// let long_s_px = long_s * 1.333*1.1;
|
||||
|
||||
// let currentColHeight = 0;
|
||||
// let totalWidth = 0;
|
||||
// let tempSizes = [];
|
||||
// let anyWrapped = false;
|
||||
// for (let i = 0; i < mid.length; i++) {
|
||||
// let name = mid[i];
|
||||
// let l = name.length;
|
||||
// //let isMulti = (l * short_s_px) > th;
|
||||
// let isShort = (l * short_s_px) <= (Number(th) + Number(d.textSpan));
|
||||
// console.log("冷涼:",name,(l * short_s_px), (Number(d.textHeight) + Number(d.textSpan)),s,isShort)
|
||||
// let size = isShort ? s : long_s;//isMulti ? long_s : s;
|
||||
// let size_px = size * (4 / 3); //isMulti ? long_s_px : short_s_px;
|
||||
// let padding = (name.length > 10) ? 5 : 0
|
||||
// let isMulti = !isShort && (l * size_px >= h - padding);
|
||||
// if (isMulti) anyWrapped = true;
|
||||
|
||||
// tempSizes.push({ name: name, size: size, isMulti: isMulti,isShort:isShort });
|
||||
|
||||
// if (isMulti) {
|
||||
// // 多行長名
|
||||
// let charsPerCol = Math.floor(h / size_px);
|
||||
// if (charsPerCol < 1) charsPerCol = 1;
|
||||
// let lines = Math.ceil(l / charsPerCol);
|
||||
// let nameW = lines * (size_px * 1.1); // 1.1倍行距
|
||||
|
||||
// if (currentColHeight > 0) currentColHeight = 0;
|
||||
// totalWidth += nameW + gap;
|
||||
// } else {
|
||||
// if (isShort) {
|
||||
// // 單行短名
|
||||
// if (currentColHeight > 0 && (currentColHeight + th + gap) <= h) {
|
||||
// currentColHeight += th + gap;
|
||||
// } else {
|
||||
// currentColHeight = th;
|
||||
// totalWidth += short_s_px + gap;
|
||||
// }
|
||||
// } else {
|
||||
// currentColHeight = 0;
|
||||
// totalWidth += size_px + gap;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (totalWidth > 0) totalWidth -= gap;
|
||||
// console.log("QQ:",name,totalWidth,w)
|
||||
// // 總寬度未爆框,確定最佳組合
|
||||
// if (totalWidth <= w) {
|
||||
// if (hasShort) {
|
||||
// sizes = tempSizes;
|
||||
// break;
|
||||
// } else {
|
||||
// if (!anyWrapped || s === 12) {
|
||||
// sizes = tempSizes;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// }
|
||||
|
||||
// s -= 1;
|
||||
// console.log("計算過:",s)
|
||||
//}
|
||||
|
||||
//// 處理極端情況
|
||||
//if (sizes.length === 0) {
|
||||
// sizes = mid.map(name => {
|
||||
// return { name: name, size: 12, isMulti: (name.length * 12 * 1.333) > th };
|
||||
// });
|
||||
//}
|
||||
|
||||
let s = Number(d.fontSize);
|
||||
//let th = parseFloat(d.textHeight) || parseFloat(d.height);
|
||||
//let v_gap = parseFloat(d.textSpan) || 0;
|
||||
//let h_gap = 5;
|
||||
//let shrinkLimit = 6;
|
||||
//if (Number(d.height) < Number(500)) {
|
||||
// shrinkLimit = 8;
|
||||
//}
|
||||
//// 1. 固定的長短名判斷
|
||||
//let items = mid.map(name => {
|
||||
// let l = name.length;
|
||||
// let isShort = (mid.length > 1) && ((l * 40) <= (th + 40));
|
||||
// return { name: name, l: l, isShort: isShort, isMulti: false, size: 0 };
|
||||
//});
|
||||
|
||||
//let long_s = parseFloat(d.fontSize);
|
||||
//let short_s = parseFloat(d.fontSize);
|
||||
|
||||
//// 🌟 核心修復:在排版前,預先剔除「幽靈扣血」區間!
|
||||
//// 算出短名跟長名的「真實極限大小」,讓它們直接從極限起跑,絕不空轉。
|
||||
//let max_short_effective = shrinkLimit;
|
||||
//let min_long_limit = parseFloat(d.fontSize);
|
||||
|
||||
//items.forEach(item => {
|
||||
// if (item.isShort) {
|
||||
// let max_s_for_th = Math.floor(th / (item.l * 1.333));
|
||||
// if (max_s_for_th > max_short_effective) max_short_effective = max_s_for_th;
|
||||
// } else {
|
||||
// // 算出長名字不折行的極限大小
|
||||
// let max_s_for_h = Math.floor((h - 10) / (item.l * 1.333));
|
||||
// if (max_s_for_h < min_long_limit) min_long_limit = max_s_for_h;
|
||||
// }
|
||||
//});
|
||||
|
||||
//// 直接把虛胖的字體壓到物理極限
|
||||
//if (short_s > max_short_effective) short_s = max_short_effective;
|
||||
//if (long_s > min_long_limit) long_s = min_long_limit;
|
||||
|
||||
//let sizes = [];
|
||||
//let shrink_turn = 'long';
|
||||
|
||||
//while (true) {
|
||||
// let totalWidth = 0;
|
||||
// let current_col_h = 0;
|
||||
// let current_col_w = 0;
|
||||
// let cols_width = [];
|
||||
// let any_wrapped = false;
|
||||
|
||||
// for (let i = 0; i < items.length; i++) {
|
||||
// let item = items[i];
|
||||
// let s = item.isShort ? short_s : long_s;
|
||||
|
||||
// // 讓 3個字 跟 4個字 的短名字能在格子內各自完美對齊
|
||||
// if (item.isShort) {
|
||||
// let max_s_for_th = Math.floor(th / (item.l * 1.333));
|
||||
// if (s > max_s_for_th) s = max_s_for_th;
|
||||
// }
|
||||
|
||||
// item.size = s;
|
||||
// let size_px = s * 1.333;
|
||||
|
||||
// if (item.isShort) {
|
||||
// let item_h = Math.max(th, item.l * size_px);
|
||||
// if (current_col_h === 0) {
|
||||
// current_col_h = item_h;
|
||||
// current_col_w = size_px;
|
||||
// } else if ((current_col_h + v_gap + item_h) <= h) {
|
||||
// current_col_h += (v_gap + item_h);
|
||||
// if (size_px > current_col_w) current_col_w = size_px;
|
||||
// } else {
|
||||
// cols_width.push(current_col_w);
|
||||
// current_col_h = item_h;
|
||||
// current_col_w = size_px;
|
||||
// }
|
||||
// } else {
|
||||
// if (current_col_h > 0) {
|
||||
// cols_width.push(current_col_w);
|
||||
// current_col_h = 0;
|
||||
// current_col_w = 0;
|
||||
// }
|
||||
|
||||
// let item_w = size_px;
|
||||
// if ((item.l * size_px) > (h - 10)) {
|
||||
// item.isMulti = true;
|
||||
// any_wrapped = true;
|
||||
// let chars_per_col = Math.floor((h - 10) / size_px);
|
||||
// if (chars_per_col < 1) chars_per_col = 1;
|
||||
// let item_cols = Math.ceil(item.l / chars_per_col);
|
||||
// item_w = item_cols * (size_px * 1.1);
|
||||
// } else {
|
||||
// item.isMulti = false;
|
||||
// }
|
||||
|
||||
// cols_width.push(item_w);
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (current_col_h > 0) cols_width.push(current_col_w);
|
||||
// totalWidth = cols_width.reduce((a, b) => a + b, 0) + (cols_width.length > 1 ? (cols_width.length - 1) * h_gap : 0);
|
||||
|
||||
// // 🌟 過關條件
|
||||
// if (totalWidth <= w && (!any_wrapped || long_s === 6)) {
|
||||
// sizes = items.map(x => ({ name: x.name, size: x.size, isMulti: x.isMulti, isShort: x.isShort }));
|
||||
// break;
|
||||
// }
|
||||
|
||||
// // 真實的輪流縮小機制
|
||||
// if (any_wrapped && long_s > shrinkLimit) {
|
||||
// long_s--; // 高度爆框,只懲罰長名字
|
||||
// } else {
|
||||
// // 寬度爆框,輪流真槍實彈互扣
|
||||
// let hasLong = items.some(x => !x.isShort);
|
||||
// let hasShort = items.some(x => x.isShort);
|
||||
|
||||
// if (hasLong && hasShort) {
|
||||
// if (shrink_turn === 'long') {
|
||||
// if (long_s > shrinkLimit) { long_s--; shrink_turn = 'short'; }
|
||||
// else if (short_s > shrinkLimit) { short_s--; shrink_turn = 'long'; }
|
||||
// else break;
|
||||
// } else {
|
||||
// if (short_s > shrinkLimit) { short_s--; shrink_turn = 'long'; }
|
||||
// else if (long_s > shrinkLimit) { long_s--; shrink_turn = 'short'; }
|
||||
// else break;
|
||||
// }
|
||||
// } else if (hasLong) {
|
||||
// if (long_s > shrinkLimit) long_s--;
|
||||
// else break;
|
||||
// } else {
|
||||
// if (short_s > shrinkLimit) short_s--;
|
||||
// else break;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
let th = Number(d.textHeight) || Number(d.height);
|
||||
let v_gap = Number(d.textSpan) || 0;
|
||||
let h_gap = 5;
|
||||
|
||||
// 1. 設定初始字體 (不再主動放大,統一從預設大小開始測試)
|
||||
let shrinkLimit = 6;
|
||||
if (Number(d.height) < Number(500)) {
|
||||
shrinkLimit =8;
|
||||
}else if (Number(d.height) < Number(300)) {
|
||||
shrinkLimit = 12;
|
||||
}
|
||||
let long_s = Number(d.fontSize);
|
||||
let short_s = Number(d.fontSize);
|
||||
let base_s_px = Number(d.fontSize) * 1.333;
|
||||
|
||||
// 2. 判斷誰是長名、誰是短名 (以預設大小判定,判斷後永遠不變)
|
||||
if (mid.length==1&&mid[0].includes("暨無始劫以來累世冤親債主")) {
|
||||
mid = mid[0].split("暨")
|
||||
mid[0] = mid[0] + "暨";
|
||||
console.log("mid:",mid)
|
||||
}
|
||||
// 1. 沿用你確認成功的版本:用固定的 40px 當作長短名尺規,徹底解決短名字被強佔 800px 變三行的問題!
|
||||
let items = mid.map(name => {
|
||||
let l = name.length;
|
||||
let isShort = (l * base_s_px) <= (th + v_gap);
|
||||
let isShort = (mid.length > 1) &&(l * 40) <= (th + (v_gap/2));
|
||||
return { name: name, l: l, isShort: isShort, isMulti: false, size: 0 };
|
||||
});
|
||||
|
||||
|
||||
let sizes = [];
|
||||
let shrink_turn = 'long'; // 設定交替縮小指標,優先從長名開始
|
||||
let shrink_turn = 'long';
|
||||
|
||||
// 3. 預測排版與縮小迴圈
|
||||
while (true) {
|
||||
let totalWidth = 0;
|
||||
let current_col_h = 0;
|
||||
let current_col_w = 0;
|
||||
let cols_width = []; // 用來收集每一實體行的真實寬度
|
||||
let cols_width = [];
|
||||
let any_wrapped = false; // 🌟 專門用來監測長名字有沒有折行
|
||||
|
||||
for (let i = 0; i < items.length; i++) {
|
||||
let item = items[i];
|
||||
|
||||
// 賦予當前迴圈測試中的字體大小
|
||||
let s = item.isShort ? short_s : long_s;
|
||||
item.size = s;
|
||||
let size_px = s * 1.333;
|
||||
|
||||
if (item.isShort) {
|
||||
// 短名字計算 (高度至少為 th,若字數過多則取實際字體高度)
|
||||
let item_h = Math.max(th, item.l * size_px);
|
||||
|
||||
if (current_col_h === 0) {
|
||||
// 開新行
|
||||
current_col_h = item_h;
|
||||
current_col_w = size_px;
|
||||
} else if ((current_col_h + v_gap + item_h) <= h) {
|
||||
// 該行高度夠放,繼續疊在同一行
|
||||
current_col_h += (v_gap + item_h);
|
||||
if (size_px > current_col_w) current_col_w = size_px; // 取該行最寬的字體寬度
|
||||
if (size_px > current_col_w) current_col_w = size_px;
|
||||
} else {
|
||||
// 該行放不下,結算並折到下一行
|
||||
cols_width.push(current_col_w);
|
||||
current_col_h = item_h;
|
||||
current_col_w = size_px;
|
||||
}
|
||||
} else {
|
||||
// 長名字計算:遇到長名字,必須獨佔或多佔空間,先把前面短名字的行結算掉
|
||||
if (current_col_h > 0) {
|
||||
cols_width.push(current_col_w);
|
||||
current_col_h = 0;
|
||||
@@ -493,13 +551,16 @@
|
||||
}
|
||||
|
||||
let item_w = size_px;
|
||||
// 判斷長名字是否會超過總高度 h,需不需要折成多行
|
||||
if ((item.l * size_px) > h) {
|
||||
|
||||
// 🌟 解決長名字折行:加上安全邊距 (h - 10),一旦超過就標記 any_wrapped
|
||||
if ((item.l * size_px) > (h - 10)) {
|
||||
item.isMulti = true;
|
||||
let chars_per_col = Math.floor(h / size_px);
|
||||
any_wrapped = true; // 抓到長名字折行了!
|
||||
|
||||
let chars_per_col = Math.floor((h - 10) / size_px);
|
||||
if (chars_per_col < 1) chars_per_col = 1;
|
||||
let item_cols = Math.ceil(item.l / chars_per_col);
|
||||
item_w = item_cols * (size_px * 1.1); // 計算折行後的總寬度
|
||||
item_w = item_cols * (size_px * 1.1);
|
||||
} else {
|
||||
item.isMulti = false;
|
||||
}
|
||||
@@ -507,40 +568,48 @@
|
||||
cols_width.push(item_w);
|
||||
}
|
||||
}
|
||||
// 迴圈結束,補上最後一行還沒結算的寬度
|
||||
|
||||
if (current_col_h > 0) cols_width.push(current_col_w);
|
||||
|
||||
// 4. 結算總寬度 = 所有行寬加總 + 行與行之間的水平間距
|
||||
totalWidth = cols_width.reduce((a, b) => a + b, 0) + (cols_width.length > 1 ? (cols_width.length - 1) * h_gap : 0);
|
||||
|
||||
// 判斷是否完美塞進設定的總寬度 w 裡面
|
||||
if (totalWidth <= w) {
|
||||
sizes = items.map(x => ({ name: x.name, size: x.size, isMulti: x.isMulti, isShort: x.isShort }));
|
||||
// 🌟 核心修正:除了總寬度沒爆框,還必須【沒有發生長名字折行】(或長名字已經縮到極限 6pt 退無可退),才會滿意並停止縮小!
|
||||
if (totalWidth <= w && (!any_wrapped || long_s === shrinkLimit)) {
|
||||
sizes = items.map(x => {
|
||||
let final_s = x.size;
|
||||
if (x.isShort) {
|
||||
// 算出這個字數能剛好塞進 th 的最大字體
|
||||
let max_s_for_th = Math.floor(th / (x.l * 1.333));
|
||||
// 如果統算出來的 short_s 太大,就把它壓低到剛好符合 th 高度
|
||||
if (final_s > max_s_for_th) {
|
||||
final_s = max_s_for_th;
|
||||
}
|
||||
}
|
||||
|
||||
return { name: x.name, size: final_s, isMulti: x.isMulti, isShort: x.isShort };
|
||||
});
|
||||
break;
|
||||
}
|
||||
|
||||
// 5. 若超過寬度,啟動輪流縮小字體再算一次 (每次 -1)
|
||||
// 沿用成功的輪流互相縮小機制 (-1pt)
|
||||
let hasLong = items.some(x => !x.isShort);
|
||||
let hasShort = items.some(x => x.isShort);
|
||||
|
||||
if (hasLong && hasShort) {
|
||||
// 長短名皆有,輪流互相縮小
|
||||
if (shrink_turn === 'long') {
|
||||
if (long_s > 6) { long_s--; shrink_turn = 'short'; }
|
||||
else if (short_s > 6) { short_s--; shrink_turn = 'long'; }
|
||||
else break; // 都縮到底限,強制跳出
|
||||
if (long_s > shrinkLimit) { long_s--; shrink_turn = 'short'; }
|
||||
else if (short_s > shrinkLimit) { short_s--; shrink_turn = 'long'; }
|
||||
else break;
|
||||
} else {
|
||||
if (short_s > 6) { short_s--; shrink_turn = 'long'; }
|
||||
else if (long_s > 6) { long_s--; shrink_turn = 'short'; }
|
||||
if (short_s > shrinkLimit) { short_s--; shrink_turn = 'long'; }
|
||||
else if (long_s > shrinkLimit) { long_s--; shrink_turn = 'short'; }
|
||||
else break;
|
||||
}
|
||||
} else if (hasLong) {
|
||||
// 只有長名字,一路縮長名字
|
||||
if (long_s > 6) long_s--;
|
||||
if (long_s > shrinkLimit) long_s--;
|
||||
else break;
|
||||
} else {
|
||||
// 只有短名字,一路縮短名字
|
||||
if (short_s > 6) short_s--;
|
||||
if (short_s > shrinkLimit) short_s--;
|
||||
else break;
|
||||
}
|
||||
}
|
||||
@@ -548,7 +617,7 @@
|
||||
// 防呆處理
|
||||
if (sizes.length === 0) {
|
||||
sizes = mid.map(name => {
|
||||
return { name: name, size: 6, isMulti: false, isShort: true };
|
||||
return { name: name, size: shrinkLimit, isMulti: false, isShort: true };
|
||||
});
|
||||
}
|
||||
// 2. 建立外層的 Flexbox 容器
|
||||
@@ -993,51 +1062,90 @@
|
||||
return 12; // 極限最小字體
|
||||
},
|
||||
renderLiveList(names, el) {
|
||||
|
||||
let h = Number(el.height);
|
||||
let w = Number(el.width);
|
||||
let th = Number(el.textHeight) || h;
|
||||
let h = parseFloat(el.height);
|
||||
let w = parseFloat(el.width);
|
||||
let th = parseFloat(el.textHeight) || h;
|
||||
|
||||
// 1. 單純計算總共有幾行 (列)
|
||||
let namesPerCol = Math.floor(h / th);
|
||||
if (namesPerCol < 1) namesPerCol = 1;
|
||||
// 🌟 軸向修正:textSpan 其實是「垂直」堆疊間距!
|
||||
let v_gap = parseFloat(el.textSpan) || 0;
|
||||
// 水平換行的間距,給予固定的安全值 5px
|
||||
let h_gap = 5;
|
||||
let shrinkLimit = 4;
|
||||
if (Number(el.height) < 300) {
|
||||
shrinkLimit = 8;
|
||||
} else if (Number(el.height) < 500) {
|
||||
shrinkLimit = 6;
|
||||
}
|
||||
let s = parseFloat(el.fontSize);
|
||||
|
||||
let cols = Math.ceil(names.length / namesPerCol); // 總行數
|
||||
while (s >= shrinkLimit) {
|
||||
let size_px = s * 1.333;
|
||||
let current_col_h = 0;
|
||||
let current_col_w = 0;
|
||||
let cols_width = [];
|
||||
let any_wrapped = false;
|
||||
|
||||
// 2. 根據行數,縮小字體直到總寬度放得下
|
||||
let s = Number(el.fontSize);
|
||||
while (s >= 4) {
|
||||
let s_px = s * (4 / 3); // pt 轉 px
|
||||
let lh = 1.1; // 行高
|
||||
let gap = 0; // 對應 span 的 margin-left
|
||||
for (let i = 0; i < names.length; i++) {
|
||||
let l = names[i].length;
|
||||
|
||||
// 總寬度 = 總行數 * (單行像素寬度 + 間距)
|
||||
let totalWidth = cols * (s_px * lh + gap);
|
||||
// 實際佔用高度
|
||||
let item_h = Math.max(th, l * size_px);
|
||||
|
||||
// 放得下就停止縮小
|
||||
if (totalWidth <= w) {
|
||||
// 1. 若單一名字高度超過容器,視為長名字折行
|
||||
if (item_h > (h - 5)) {
|
||||
any_wrapped = true;
|
||||
if (current_col_h > 0) {
|
||||
cols_width.push(current_col_w);
|
||||
current_col_h = 0;
|
||||
current_col_w = 0;
|
||||
}
|
||||
let chars_per_col = Math.floor((h - 5) / size_px);
|
||||
if (chars_per_col < 1) chars_per_col = 1;
|
||||
let item_cols = Math.ceil(l / chars_per_col);
|
||||
cols_width.push(item_cols * (size_px * 1.1));
|
||||
} else {
|
||||
// 2. 短名字正常堆疊,並套用正確的 v_gap (30px)
|
||||
if (current_col_h === 0) {
|
||||
current_col_h = item_h;
|
||||
current_col_w = size_px;
|
||||
} else if (current_col_h + v_gap + item_h <= h) {
|
||||
current_col_h += v_gap + item_h; // 高度夠,疊在同一行
|
||||
if (size_px > current_col_w) current_col_w = size_px;
|
||||
} else {
|
||||
cols_width.push(current_col_w); // 高度不夠,換行
|
||||
current_col_h = item_h;
|
||||
current_col_w = size_px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (current_col_h > 0) cols_width.push(current_col_w);
|
||||
|
||||
// 總寬度計算 = 所有欄寬加總 + (欄數-1)*5px
|
||||
let totalWidth = cols_width.reduce((a, b) => a + b, 0) + (cols_width.length > 1 ? (cols_width.length - 1) * h_gap : 0);
|
||||
|
||||
if (totalWidth <= w && (!any_wrapped || s === shrinkLimit)) {
|
||||
break;
|
||||
}
|
||||
|
||||
s -= 1;
|
||||
}
|
||||
|
||||
if (s < 4) s = 4;
|
||||
if (s < shrinkLimit) s = shrinkLimit;
|
||||
|
||||
// 3. 建立外層 Flexbox 容器
|
||||
let $namelist = $(`<div class='liveList'></div>`).css({
|
||||
"writing-mode": "vertical-rl",
|
||||
display: "flex",
|
||||
"flex-direction": "row",
|
||||
"flex-wrap": "wrap",
|
||||
"display": "flex",
|
||||
"flex-flow": "wrap",
|
||||
"align-content": "center",
|
||||
"align-items": "center",
|
||||
margin: "auto",
|
||||
width: `${w}px`,
|
||||
height: `${h}px`,
|
||||
border: "0px solid #ccc",
|
||||
padding: "0px",
|
||||
"margin": "auto",
|
||||
"width": `${w}px`,
|
||||
"height": `${h}px`,
|
||||
"border": "0px solid transparent",
|
||||
"padding": "0px",
|
||||
"font-family": el.fontFamily,
|
||||
"column-gap": `${el.textSpan}px`,
|
||||
"column-gap": `${v_gap}px` // 直書模式下,column-gap 對應的就是垂直間距!
|
||||
});
|
||||
|
||||
let self = this;
|
||||
@@ -1046,21 +1154,190 @@
|
||||
});
|
||||
return $namelist;
|
||||
},
|
||||
|
||||
renderLiveSpan(name, el, fontSize) {
|
||||
let th = Number(el.textHeight) || Number(el.height);
|
||||
let h = parseFloat(el.height);
|
||||
let th = parseFloat(el.textHeight) || h;
|
||||
|
||||
return $(`<span style="font-size: ${fontSize}pt;">${name}</span>`).css({
|
||||
display: "block",
|
||||
"min-height": `${th}px`, // ★ 固定分配高度,交給 Flexbox 自動排版
|
||||
"max-height": `${el.height}px`,
|
||||
width: "auto",//`${fontSize*1.33}`,
|
||||
"text-align": "justify", // 統一分散對齊
|
||||
"display": "block",
|
||||
"min-height": `${th}px`,
|
||||
"max-height": `${h}px`,
|
||||
"width": "auto",
|
||||
"text-align": "justify",
|
||||
"text-align-last": "justify",
|
||||
"margin-left": "0px", // 配合 JS 計算的 h_gap = 5
|
||||
"text-justify": "inter-character",
|
||||
"word-break": "break-all",
|
||||
"white-space": "pre-line"
|
||||
});
|
||||
},
|
||||
//renderLiveList(names, el) {
|
||||
// let h = parseFloat(el.height);
|
||||
// let w = parseFloat(el.width);
|
||||
// let th = parseFloat(el.textHeight) || h;
|
||||
// let h_gap = parseFloat(el.textSpan) || 0; // 陽上的 textSpan 通常作為水平欄距 (column-gap)
|
||||
// let v_gap = 0; // 陽上通常不需要垂直間距
|
||||
|
||||
// let s = parseFloat(el.fontSize);
|
||||
|
||||
// // 🌟 預測排版與縮小迴圈:同時嚴格檢查「高度」與「寬度」
|
||||
// while (s >= 6) {
|
||||
// let size_px = s * 1.333;
|
||||
// let cols = 0;
|
||||
// let current_col_h = 0;
|
||||
// let out_of_height = false; // 監測是否捅破天花板
|
||||
|
||||
// for (let i = 0; i < names.length; i++) {
|
||||
// let name = names[i];
|
||||
// let l = name.length;
|
||||
|
||||
// // 實際佔用高度:最少為 th,字多則以實際字數乘上字級
|
||||
// let item_h = Math.max(th, l * size_px);
|
||||
|
||||
// // 1. 如果單一名字的長度直接超過總高度 h,判定失敗,強制縮小!
|
||||
// if (item_h > h) {
|
||||
// out_of_height = true;
|
||||
// break;
|
||||
// }
|
||||
|
||||
// // 2. 模擬 Flexbox 垂直堆疊
|
||||
// if (current_col_h === 0) {
|
||||
// current_col_h = item_h;
|
||||
// cols++;
|
||||
// } else if (current_col_h + v_gap + item_h <= h) {
|
||||
// current_col_h += v_gap + item_h; // 高度夠,疊在同一行
|
||||
// } else {
|
||||
// cols++; // 高度不夠,換下一行
|
||||
// current_col_h = item_h;
|
||||
// }
|
||||
// }
|
||||
|
||||
// // 如果發現高度爆表,扣減字體並重新測試
|
||||
// if (out_of_height) {
|
||||
// s -= 1;
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// // 3. 檢查總寬度是否爆框
|
||||
// let totalWidth = cols * size_px + (cols > 1 ? (cols - 1) * h_gap : 0);
|
||||
// if (totalWidth <= w) {
|
||||
// break; // 長寬都完美過關,結束縮小!
|
||||
// }
|
||||
|
||||
// s -= 1;
|
||||
// }
|
||||
|
||||
// if (s < 6) s = 6; // 最低底限保底
|
||||
|
||||
// let $namelist = $(`<div class='liveList'></div>`).css({
|
||||
// "writing-mode": "vertical-rl",
|
||||
// "display": "flex",
|
||||
// "flex-flow": "wrap",
|
||||
// "align-content": "center",
|
||||
// "align-items": "center",
|
||||
// "margin": "auto",
|
||||
// "width": `${w}px`,
|
||||
// "height": `${h}px`,
|
||||
// "border": "0px solid transparent",
|
||||
// "padding": "0px",
|
||||
// "font-family": el.fontFamily,
|
||||
// "column-gap": `${h_gap}px`
|
||||
// });
|
||||
|
||||
// let self = this;
|
||||
// names.forEach(name => {
|
||||
// $namelist.append(self.renderLiveSpan(name, el, s));
|
||||
// });
|
||||
// return $namelist;
|
||||
//},
|
||||
|
||||
//renderLiveSpan(name, el, fontSize) {
|
||||
// let h = parseFloat(el.height);
|
||||
// let th = parseFloat(el.textHeight) || h;
|
||||
|
||||
// return $(`<span style="font-size: ${fontSize}pt;">${name}</span>`).css({
|
||||
// "display": "block",
|
||||
// "min-height": `${th}px`, // 統一給予基礎高度
|
||||
// "max-height": `${h}px`,
|
||||
// "width": "auto",
|
||||
// "text-align": "justify",
|
||||
// "text-align-last": "justify",
|
||||
// "text-justify": "inter-character",
|
||||
// "word-break": "break-all",
|
||||
// "white-space": "pre-line"
|
||||
// });
|
||||
//},
|
||||
|
||||
//renderLiveList(names, el) {
|
||||
|
||||
// let h = Number(el.height);
|
||||
// let w = Number(el.width);
|
||||
// let th = Number(el.textHeight) || h;
|
||||
|
||||
// // 1. 單純計算總共有幾行 (列)
|
||||
// let namesPerCol = Math.floor(h / th);
|
||||
// if (namesPerCol < 1) namesPerCol = 1;
|
||||
|
||||
// let cols = Math.ceil(names.length / namesPerCol); // 總行數
|
||||
|
||||
// // 2. 根據行數,縮小字體直到總寬度放得下
|
||||
// let s = Number(el.fontSize);
|
||||
// while (s >= 4) {
|
||||
// let s_px = s * (4 / 3); // pt 轉 px
|
||||
// let lh = 1.1; // 行高
|
||||
// let gap = 0; // 對應 span 的 margin-left
|
||||
|
||||
// // 總寬度 = 總行數 * (單行像素寬度 + 間距)
|
||||
// let totalWidth = cols * (s_px * lh + gap);
|
||||
|
||||
// // 放得下就停止縮小
|
||||
// if (totalWidth <= w) {
|
||||
// break;
|
||||
// }
|
||||
// s -= 1;
|
||||
// }
|
||||
|
||||
// if (s < 4) s = 4;
|
||||
|
||||
// // 3. 建立外層 Flexbox 容器
|
||||
// let $namelist = $(`<div class='liveList'></div>`).css({
|
||||
// "writing-mode": "vertical-rl",
|
||||
// display: "flex",
|
||||
// "flex-direction": "row",
|
||||
// "flex-wrap": "wrap",
|
||||
// "align-content": "center",
|
||||
// "align-items": "center",
|
||||
// margin: "auto",
|
||||
// width: `${w}px`,
|
||||
// height: `${h}px`,
|
||||
// border: "0px solid #ccc",
|
||||
// padding: "0px",
|
||||
// "font-family": el.fontFamily,
|
||||
// "column-gap": `${el.textSpan}px`,
|
||||
// });
|
||||
|
||||
// let self = this;
|
||||
// names.forEach(name => {
|
||||
// $namelist.append(self.renderLiveSpan(name, el, s));
|
||||
// });
|
||||
// return $namelist;
|
||||
//},
|
||||
//renderLiveSpan(name, el, fontSize) {
|
||||
// let th = Number(el.textHeight) || Number(el.height);
|
||||
|
||||
// return $(`<span style="font-size: ${fontSize}pt;">${name}</span>`).css({
|
||||
// display: "block",
|
||||
// "min-height": `${th}px`, // ★ 固定分配高度,交給 Flexbox 自動排版
|
||||
// "max-height": `${el.height}px`,
|
||||
// width: "auto",//`${fontSize*1.33}`,
|
||||
// "text-align": "justify", // 統一分散對齊
|
||||
// "text-align-last": "justify",
|
||||
// "text-justify": "inter-character",
|
||||
// "word-break": "break-all",
|
||||
// "white-space": "pre-line"
|
||||
// });
|
||||
//},
|
||||
// 品字佈局邏輯:一上二下
|
||||
renderRoster(names, el) {
|
||||
if (!names.length) return '';
|
||||
@@ -1142,7 +1419,6 @@
|
||||
|
||||
let font = this.getTextSize("講", parseInt(fontSize));
|
||||
//自動判斷縮小字型的規則,要同時縮小間距
|
||||
// console.log("scaleFontSize:", txtContent, fontSize, elementWidth)
|
||||
if (Math.ceil(txtContent.length * fontSize * (4 / 3) * 1.1) > Number(elementWidth)) {
|
||||
let newfontSize = Number(fontSize) - 1;
|
||||
if (newfontSize <= 10) {
|
||||
@@ -1168,7 +1444,6 @@
|
||||
async changeSetup(config) {
|
||||
|
||||
let classList = ["liveList", "nameList", "address", "ancestor-wrapper", "lefttitle", "righttitle", "rosterList", "print_id"]
|
||||
console.log("changeSetup:",config);
|
||||
switch (config) {
|
||||
case "X":
|
||||
if ($("#indivualSetup").prop("checked")) {
|
||||
@@ -1208,7 +1483,11 @@
|
||||
break;
|
||||
case "fontSize":
|
||||
if ($("#indivualSetup").prop("checked")) {
|
||||
$(this.selected).css("font-size", $("#fontSize").val())
|
||||
if (this.selected.find(".nameList").length >= 1) {
|
||||
this.selected.find(".nameList").children().css("font-size", $("#fontSize").val())
|
||||
} else {
|
||||
$(this.selected).css("font-size", $("#fontSize").val())
|
||||
}
|
||||
} else if ($("#allSetup").prop("checked")) {
|
||||
if (this.selected.find(".liveList").length >= 1 || this.selected.find(".nameList").length >= 1 ||
|
||||
this.selected.find(".rosterList").length >= 1) {
|
||||
@@ -1219,9 +1498,13 @@
|
||||
})
|
||||
}
|
||||
});
|
||||
} else if (this.selected.hasClass("nameSpan")) {
|
||||
$(".nameSpan").css("font-size", $("#fontSize").val())
|
||||
|
||||
} //else if (this.selected.hasClass("nameSpan")) {
|
||||
else if (this.selected.find(".nameList").length >= 1) {
|
||||
//$(".nameSpan").css("font-size", $("#fontSize").val())
|
||||
document.querySelectorAll(".nameList > span").forEach(el => {
|
||||
el.style.fontSize = $("#fontSize").val();
|
||||
});
|
||||
|
||||
} else if (this.selected.hasClass("liveSpan")) {
|
||||
$(".liveSpan").css("font-size", $("#fontSize").val())
|
||||
} else if (this.selected.hasClass("rosterSpan")) {
|
||||
@@ -1330,6 +1613,25 @@
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "textHeight":
|
||||
if ($("#indivualSetup").prop("checked")) {
|
||||
if (this.selected.find(".liveList").length >= 1) {
|
||||
this.selected.find(".liveList").children().css("minHeight", $("#contentHeight").val() + 'px')
|
||||
} else if (this.selected.find(".nameList").length >= 1) {
|
||||
this.selected.find(".nameList").children().css("minHeight", $("#contentHeight").val() + 'px')
|
||||
}
|
||||
} else if ($("#allSetup").prop("checked")) {
|
||||
if (this.selected.find(".liveList").length >= 1) {
|
||||
document.querySelectorAll(".liveList > span").forEach(el => {
|
||||
el.style.minHeight = $("#contentHeight").val() + 'px';
|
||||
})
|
||||
} else if (this.selected.find(".nameList").length >= 1) {
|
||||
document.querySelectorAll(".nameList > span").forEach(el => {
|
||||
el.style.minHeight = $("#contentHeight").val() + 'px';
|
||||
})
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "breakCount":
|
||||
if ($("#indivualSetup").prop("checked")) {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user