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

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 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 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 long_ratio = 1.0;
let short_ratio = 1.0;
let shrink_turn = 'long';
// 1. 模擬排版:找出能讓全體塞入的最佳字體組合
while (s >= 12) {
let short_s_px = s * 1.333;
let hasShort = mid.some(n => (n.length * short_s_px) <= th);
// 2. 動態排版與比例縮小迴圈
while (true) {
// 套用當前的縮小比例
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%
if (long_s < 12) long_s = 12;
let long_s_px = long_s * 1.333;
let cols = []; // 用陣列記錄每一實體欄位的寬度
let current_col_h = 0;
let current_col_w = 0;
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) <= th;
let size = isShort ? s : long_s;//isMulti ? long_s : s;
let size_px = size * 1.333; //isMulti ? long_s_px : short_s_px;
for (let i = 0; i < items.length; i++) {
let item = items[i];
let size_px = item.size * 1.333;
let isMulti = !isShort && (l * size_px >= h);
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;
}
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 {
currentColHeight = 0;
totalWidth += size_px + gap;
cols.push(current_col_w); // 封裝這一行
current_col_h = item_h;
current_col_w = size_px;
}
}
}
if (totalWidth > 0) totalWidth -= gap;
// 總寬度未爆框,確定最佳組合
if (totalWidth <= w) {
if (hasShort) {
sizes = tempSizes;
break;
} else {
if (!anyWrapped || s === 12) {
sizes = tempSizes;
break;
// 長名字必定獨佔或多佔欄位,先將前面的短名欄位封裝
if (current_col_h > 0) {
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) {
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 容器
let $namelist = $(`<div class='nameList'></div>`).css({
"writing-mode": "vertical-rl",
@@ -445,9 +571,8 @@
});
sizes.forEach(item => {
let th = Number(d.textHeight) || Number(d.height)
let minH = item.isShort ? `${th}px` : `${d.height}px`
;
let alignStyle = item.isMulti ? "start" : "justify";
let minH = item.isShort ? `${th}px` : `${d.height}px` ;
let alignStyle = item.isMulti || (!item.isMulti && !item.isShort) ? "start" : "justify";
let $span= $(`<span style="font-size: ${item.size}pt;">${item.name}</span>`).css({
display: "block",
@@ -480,14 +605,14 @@
<span class="sub-text">${parts[1] || ''}</span>
</div>`;
} 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)
} 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)
}
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)
}
if (newFontSize < 10) {
@@ -1019,15 +1144,22 @@
let font = this.getTextSize("講", parseInt(fontSize));
//自動判斷縮小字型的規則,要同時縮小間距
//if (dStyle.elementID === 'title1') {//表示是一般正名,也就是牌位正中間的一般格式,排法是上下上下
if ((Math.ceil(txtContent.length / 2) * font.width) * 2 > parseFloat(elementWidth)) {
let newfontSize = parseInt(fontSize) - 1;
// 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) {
return newfontSize;
}
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;
},
breakWord(txtContent, style, dStyle) {