This commit is contained in:
minom committed 2026-11-04 18:03:01 +08:00
1 parent 1cb2a7a35e
commit 8db6019ba3
10 files changed
+1120 -703

No files matched your search

+209 -58
View File
@@ -833,7 +833,7 @@
let txt = $(`<div class='${d.elementID}'></div>`).css({
"z-index": 9999, visibility: d.visibility, width: d.width, height: d.height, padding: "1px",
"writing-mode": "vertical-rl", display: "flex", "flex-direction": "row", "flex-wrap": "wrap", margin: "auto",
"column-gap": `${d.textSpan}px`, "align-items": "flex-start", "justify-content": "start"
"column-gap": `${d.textSpan}px`, "align-items": "center", "justify-content": "start"
});
mid.forEach(x => {
$(txt).append($(`<div>${x}</div>`).css({ "margin-bottom": "10px", "margin-left": "5px", "text-justify": "inter-character", "white-space": "pre-line" }));
@@ -841,7 +841,10 @@
return txt;
},
renderNormal(mid, d) {
return $(`<div class='${d.elementID}'>${mid}</div>`).css({ "z-index": 9999, visibility: d.visibility, width: d.width, height: d.height });
return $(`<div class='${d.elementID}'>${mid}</div>`).
css({
"z-index": 9999, visibility: d.visibility, display: "flex",
"align-items": "center", width: d.width, height: d.height });
},
/*renderNameList(names, d, newFontSize, style, colWidth) {
let h = parseFloat(d.height), w = parseFloat(d.width), th = parseFloat(d.textHeight) || h;
@@ -1035,6 +1038,8 @@
}
return { name: x.name, size: final_s, isMulti: x.isMulti, isShort: x.isShort };
});
let minFinalSize = Math.min(...sizes.map(item => item.size));
sizes.forEach(item => item.size = minFinalSize);
break;
}
@@ -1224,12 +1229,24 @@
let s = parseFloat(el.fontSize);
if (names.length == 2) {
h = th + v_gap;
}
let maxLen = Math.max(...names.map(x => x.length), 1);
//if (names.length == 2) {
// h = th + v_gap;
//}
const init_size_px = s * 1.333;
let items = names.map(rawName => {
let name = rawName.trim();
let l = name.length;
// 6個字以內,或換算後能塞入預設區塊的視為短名
let isShort = (l <= 6) || ((l * init_size_px) <= (th + (v_gap / 2)));
if (names.length == 2) {
isShort = false;
}
return { name: name, l: l, isShort: isShort, isMulti: false };
});
// 取得短名的最大字數作為標準網格基準
let maxShortLen = Math.max(...items.filter(x => x.isShort).map(x => x.l), 1);
// 2. 單一變數 s 全局統一縮放,長字串為主計算
while (s >= shrinkLimit) {
let size_px = s * 1.333;
let current_col_h = 0;
@@ -1237,31 +1254,16 @@
let cols_width = [];
let any_wrapped = false;
for (let i = 0; i < names.length; i++) {
let l = names[i].length;
for (let i = 0; i < items.length; i++) {
let item = items[i];
let l = item.l;
let natural_max_h = maxLen * size_px;
let item_h = Math.max(th, natural_max_h);
if (item.isShort) {
// 短字串照原規則疊加
let natural_max_h = maxShortLen * size_px;
let item_h = Math.max(th, natural_max_h);
if (item_h > natural_max_h * 1.5) item_h = natural_max_h * 1.5;
if (item_h > natural_max_h * 1.5) {
item_h = natural_max_h * 1.5;
}
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 {
if (current_col_h === 0) {
current_col_h = item_h;
current_col_w = size_px;
@@ -1273,17 +1275,34 @@
current_col_h = item_h;
current_col_w = size_px;
}
} else {
// 長字串處理:一旦遇到長字串,強制換行並獨佔一整欄 (配發 h 高度)
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 ((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(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);
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)) {
if (totalWidth <= w) {
break;
}
s -= 1;
}
@@ -1297,53 +1316,140 @@
"align-items": "center",
"margin": "auto",
"width": `${w}px`,
"height": `${h}px`,
"height": `${h}px`, // 這裡的 h 已經恢復維持原設定值!
"border": "0px solid transparent",
"padding": "0px",
"font-family": el.fontFamily,
"font-family": el.style ? el.style.fontFamily : el.fontFamily,
"column-gap": `${v_gap}px`
});
names.forEach(name => {
$namelist.append(this.renderLiveSpan(name, el, s, maxLen));
let self = this;
// 3. 將 item 物件傳入,讓 renderLiveSpan 知道它是長或短
items.forEach(item => {
$namelist.append(self.renderLiveSpan(item, el, s, maxShortLen));
});
return $namelist;
},
//let maxLen = Math.max(...names.map(x => x.length), 1);
renderLiveSpan(name, el, fontSize, maxLen = 1) {
//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;
// for (let i = 0; i < names.length; i++) {
// let l = names[i].length;
// let natural_max_h = maxLen * size_px;
// let item_h = Math.max(th, natural_max_h);
// if (item_h > natural_max_h * 1.5) {
// item_h = natural_max_h * 1.5;
// }
// 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 {
// 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);
// 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 < shrinkLimit) s = shrinkLimit;
//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": `${v_gap}px`
//});
//names.forEach(name => {
// $namelist.append(this.renderLiveSpan(name, el, s, maxLen));
//});
//return $namelist;
},
renderLiveSpan(item, el, fontSize, maxLen = 1) {
let h = parseFloat(el.height);
let th = parseFloat(el.textHeight) || h;
let size_px = fontSize * 1.333;
let l = name.length;
// 支援舊有單純傳入字串的防呆
let nameStr = typeof item === 'string' ? item : item.name;
let isShort = typeof item === 'string' ? true : item.isShort;
let isMulti = typeof item === 'string' ? false : item.isMulti;
let l = nameStr.length;
// 4. 高度分配邏輯:長字串佔滿全高 h,短字串用網格標準高度
let natural_max_h = maxLen * size_px;
let boxH_num = Math.max(th, natural_max_h);
let boxH_num = isShort ? Math.max(th, natural_max_h) : h;
if (boxH_num > natural_max_h * 1.5) {
if (isShort && boxH_num > natural_max_h * 1.5) {
boxH_num = natural_max_h * 1.5;
}
let minH = `${boxH_num}px`;
let alignStyle = "justify";
let spanDisplay = "block";
let spanJustifyContent = "flex-start";
let contentH = l * size_px;
let emptySpace = boxH_num - contentH;
let gapsCount = l > 1 ? (l - 1) : 1;
let avgGap = emptySpace / gapsCount;
// 預設對齊:長字串/多行靠上 (start),短字串預設分散 (justify)
let alignStyle = isMulti || (!isMulti && !isShort) ? "start" : "justify";
if (alignStyle === "justify" && avgGap > (size_px * 1.5)) {
alignStyle = "justify";
spanDisplay = "block";
spanJustifyContent = "space-between";
if (isShort) {
let contentH = l * size_px;
let emptySpace = boxH_num - contentH;
let gapsCount = l > 1 ? (l - 1) : 1;
let avgGap = emptySpace / gapsCount;
// 短名防過度拉扯:字距超過字體的 1.5 倍時自動靠上切齊
if (alignStyle === "justify" && avgGap > (size_px * 1.5)) {
alignStyle = "start";
}
}
return $(`<span style="font-size: ${fontSize}pt;">${name}</span>`).css({
"display": spanDisplay,
"justify-content": spanJustifyContent,
"align-items": "center",
// 完全使用 block 與原生對齊,避免 Flex 破壞直書對齊
return $(`<span style="font-size: ${fontSize}pt;">${nameStr}</span>`).css({
"display": "block",
"min-height": minH,
"max-height": `${h}px`,
"width": "auto",
@@ -1356,6 +1462,51 @@
"white-space": "pre-line"
});
},
//renderLiveSpan(name, el, fontSize, maxLen = 1) {
// let h = parseFloat(el.height);
// let th = parseFloat(el.textHeight) || h;
// let size_px = fontSize * 1.333;
// let l = name.length;
// let natural_max_h = maxLen * size_px;
// let boxH_num = Math.max(th, natural_max_h);
// if (boxH_num > natural_max_h * 1.5) {
// boxH_num = natural_max_h * 1.5;
// }
// let minH = `${boxH_num}px`;
// let alignStyle = "justify";
// let spanDisplay = "block";
// let spanJustifyContent = "flex-start";
// let contentH = l * size_px;
// let emptySpace = boxH_num - contentH;
// let gapsCount = l > 1 ? (l - 1) : 1;
// let avgGap = emptySpace / gapsCount;
// if (alignStyle === "justify" && avgGap > (size_px * 1.5)) {
// alignStyle = "justify";
// spanDisplay = "block";
// spanJustifyContent = "space-between";
// }
// return $(`<span style="font-size: ${fontSize}pt;">${name}</span>`).css({
// "display": spanDisplay,
// "justify-content": spanJustifyContent,
// "align-items": "center",
// "min-height": minH,
// "max-height": `${h}px`,
// "width": "auto",
// "text-align": alignStyle,
// "text-align-last": alignStyle,
// "margin-left": "0px",
// "margin-top": "0px",
// "text-justify": "inter-character",
// "word-break": "break-all",
// "white-space": "pre-line"
// });
//},
renderRoster(names, el) {
if (!names.length) return '';