調整牌位,還是有點怪怪的

This commit is contained in:
2026-08-20 17:46:25 +08:00
parent 466ec11c91
commit 7c5e5ab984
+203 -71
View File
@@ -347,86 +347,212 @@
let w = Number(d.width); let w = Number(d.width);
let th = Number(d.textHeight) || h; let th = Number(d.textHeight) || h;
let gap = 5; // 對應 span 的 margin-left 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 s = Number(d.fontSize);
let h_gap = 5;
let base_s_px = Number(d.fontSize) * 1.333;
// 1. 保留每個名字獨立的「專屬最大字體」,3個字跟5個字的短名大小會各自獨立計算
let items = mid.map(name => {
let l = name.length;
let isShort = (l * base_s_px) <= (th + v_gap);
let optimal_s = Math.floor((isShort ? th : h) / (l * 1.333));
if (optimal_s > Number(d.fontSize)) optimal_s = Number(d.fontSize);
if (optimal_s < 6) optimal_s = 6;
return { name: name, l: l, isShort: isShort, optimal_s: optimal_s, size: optimal_s, isMulti: false };
});
let sizes = []; let sizes = [];
let long_ratio = 1.0;
let short_ratio = 1.0;
let shrink_turn = 'long';
// 1. 模擬排版:找出能讓全體塞入的最佳字體組合 // 2. 動態排版與比例縮小迴圈
while (s >= 12) { while (true) {
let short_s_px = s * 1.333; // 套用當前的縮小比例
let hasShort = mid.some(n => (n.length * short_s_px) <= th); items.forEach(x => {
let s = Math.floor(x.optimal_s * (x.isShort ? short_ratio : long_ratio));
x.size = s < 6 ? 6 : s;
x.isMulti = false;
});
let long_s = hasShort ? Math.floor(s * 0.75) : s; // 長字體最多縮小 25% let cols = []; // 用陣列記錄每一實體欄位的寬度
if (long_s < 12) long_s = 12; let current_col_h = 0;
let long_s_px = long_s * 1.333; let current_col_w = 0;
let currentColHeight = 0; for (let i = 0; i < items.length; i++) {
let totalWidth = 0; let item = items[i];
let tempSizes = []; let size_px = item.size * 1.333;
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) <= th;
let size = isShort ? s : long_s;//isMulti ? long_s : s;
let size_px = size * 1.333; //isMulti ? long_s_px : short_s_px;
let isMulti = !isShort && (l * size_px >= h); if (item.isShort) {
if (isMulti) anyWrapped = true; let item_h = Math.max(th, item.l * size_px);
if (current_col_h === 0) {
tempSizes.push({ name: name, size: size, isMulti: isMulti,isShort:isShort }); current_col_h = item_h;
current_col_w = size_px;
if (isMulti) { } else if (current_col_h + v_gap + item_h <= h) {
// 多行長名 current_col_h += v_gap + item_h;
let charsPerCol = Math.floor(h / size_px); if (size_px > current_col_w) current_col_w = 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 { } else {
currentColHeight = 0; cols.push(current_col_w); // 封裝這一行
totalWidth += size_px + gap; current_col_h = item_h;
current_col_w = size_px;
} }
}
}
if (totalWidth > 0) totalWidth -= gap;
// 總寬度未爆框,確定最佳組合
if (totalWidth <= w) {
if (hasShort) {
sizes = tempSizes;
break;
} else { } else {
if (!anyWrapped || s === 12) { // 長名字必定獨佔或多佔欄位,先將前面的短名欄位封裝
sizes = tempSizes; if (current_col_h > 0) {
break; cols.push(current_col_w);
current_col_h = 0;
current_col_w = 0;
} }
}
let item_w = size_px;
if (item.l * size_px > h) {
item.isMulti = true;
let chars_per_col = Math.floor(h / 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);
}
cols.push(item_w);
}
}
if (current_col_h > 0) cols.push(current_col_w);
// 總寬度 = 所有欄寬總和 + 欄間距
let totalWidth = cols.reduce((a, b) => a + b, 0) + (cols.length > 1 ? (cols.length - 1) * h_gap : 0);
if (totalWidth <= w) {
sizes = items.map(x => ({ name: x.name, size: x.size, isMulti: x.isMulti, isShort: x.isShort }));
break;
}
// 3. 寬度爆框,啟動「輪流比例縮小」
let tryShrink = (type) => {
let didShrink = false;
items.forEach(x => {
if ((type === 'long' ? !x.isShort : x.isShort) && x.size > 6) {
// 模擬扣減 5% 後,字體是否真的有變小
let nextRatio = (type === 'long' ? long_ratio : short_ratio) - 0.05;
let nextSize = Math.floor(x.optimal_s * nextRatio);
if (nextSize < x.size) didShrink = true;
}
});
if (didShrink) {
if (type === 'long') long_ratio -= 0.05;
else short_ratio -= 0.05;
}
return didShrink;
};
let reduced = false;
if (shrink_turn === 'long') {
if (tryShrink('long')) { reduced = true; shrink_turn = 'short'; }
else if (tryShrink('short')) { reduced = true; shrink_turn = 'long'; }
} else {
if (tryShrink('short')) { reduced = true; shrink_turn = 'long'; }
else if (tryShrink('long')) { reduced = true; shrink_turn = 'short'; }
}
// 全部到達極限,強制退出
if (!reduced) {
sizes = items.map(x => ({ name: x.name, size: x.size, isMulti: x.isMulti, isShort: x.isShort }));
break;
} }
s -= 1;
} }
// 處理極端情況 // 防呆處理
if (sizes.length === 0) { if (sizes.length === 0) {
sizes = mid.map(name => { sizes = mid.map(name => {
return { name: name, size: 12, isMulti: (name.length * 12 * 1.333) > th }; return { name: name, size: 6, isMulti: false, isShort: true };
}); });
} }
// 2. 建立外層的 Flexbox 容器 // 2. 建立外層的 Flexbox 容器
let $namelist = $(`<div class='nameList'></div>`).css({ let $namelist = $(`<div class='nameList'></div>`).css({
"writing-mode": "vertical-rl", "writing-mode": "vertical-rl",
@@ -445,9 +571,8 @@
}); });
sizes.forEach(item => { sizes.forEach(item => {
let th = Number(d.textHeight) || Number(d.height) let th = Number(d.textHeight) || Number(d.height)
let minH = item.isShort ? `${th}px` : `${d.height}px` let minH = item.isShort ? `${th}px` : `${d.height}px` ;
; let alignStyle = item.isMulti || (!item.isMulti && !item.isShort) ? "start" : "justify";
let alignStyle = item.isMulti ? "start" : "justify";
let $span= $(`<span style="font-size: ${item.size}pt;">${item.name}</span>`).css({ let $span= $(`<span style="font-size: ${item.size}pt;">${item.name}</span>`).css({
display: "block", display: "block",
@@ -480,14 +605,14 @@
<span class="sub-text">${parts[1] || ''}</span> <span class="sub-text">${parts[1] || ''}</span>
</div>`; </div>`;
} else if (d.elementID === "address") { } else if (d.elementID === "address") {
newFontSize = self.scaleFontSize(mid, d.fontSize, d.width); newFontSize = self.scaleFontSize(address, d.fontSize, d.height);
html = self.renderNormal(address, d) html = self.renderNormal(address, d)
} else if (d.elementID === "lefttitle") { } else if (d.elementID === "lefttitle") {
newFontSize = self.scaleFontSize(mid, d.fontSize, d.width); newFontSize = self.scaleFontSize(lefttitle, d.fontSize, d.height);
html = self.renderNormal(lefttitle, d) html = self.renderNormal(lefttitle, d)
} }
else if (d.elementID === "righttitle") { else if (d.elementID === "righttitle") {
newFontSize = self.scaleFontSize(mid, d.fontSize, d.width); newFontSize = self.scaleFontSize(righttitle, d.fontSize, d.height);
html = self.renderNormal(righttitle, d) html = self.renderNormal(righttitle, d)
} }
if (newFontSize < 10) { if (newFontSize < 10) {
@@ -1019,15 +1144,22 @@
let font = this.getTextSize("講", parseInt(fontSize)); let font = this.getTextSize("講", parseInt(fontSize));
//自動判斷縮小字型的規則,要同時縮小間距 //自動判斷縮小字型的規則,要同時縮小間距
// console.log("scaleFontSize:", txtContent, fontSize, elementWidth)
//if (dStyle.elementID === 'title1') {//表示是一般正名,也就是牌位正中間的一般格式,排法是上下上下 if (Math.ceil(txtContent.length * fontSize * (4 / 3) * 1.1) > Number(elementWidth)) {
if ((Math.ceil(txtContent.length / 2) * font.width) * 2 > parseFloat(elementWidth)) { let newfontSize = Number(fontSize) - 1;
let newfontSize = parseInt(fontSize) - 1;
if (newfontSize <= 10) { if (newfontSize <= 10) {
return newfontSize; return newfontSize;
} }
return this.scaleFontSize(txtContent, newfontSize, elementWidth); return this.scaleFontSize(txtContent, newfontSize, elementWidth);
} }
//if (dStyle.elementID === 'title1') {//表示是一般正名,也就是牌位正中間的一般格式,排法是上下上下
//if ((Math.ceil(txtContent.length / 2) * font.width) * 2 > parseFloat(elementWidth)) {
// let newfontSize = parseInt(fontSize) - 1;
// if (newfontSize <= 10) {
// return newfontSize;
// }
// return this.scaleFontSize(txtContent, newfontSize, elementWidth);
//}
return fontSize; return fontSize;
}, },
breakWord(txtContent, style, dStyle) { breakWord(txtContent, style, dStyle) {