窯整縮放

This commit is contained in:
2026-07-29 20:59:49 +08:00
parent ced4eabe71
commit cc85cb5bd7
+68 -73
View File
@@ -1365,45 +1365,22 @@ html, body, * {
// fontSize = el.style.fontSize; // fontSize = el.style.fontSize;
// rowWidth = fontSize * 2; // rowWidth = fontSize * 2;
//} //}
fontSize = el.style.fontSize;
// 1. 依據 textHeight 與 textSpan 計算一行(垂直列)最多能放幾個名字
// 1. 初始化最大字體 let th = Number(el.textHeight) || 0;
let s = Number(el.style.fontSize); let span = Number(el.textSpan) || 0;
let h = Number(el.height); let h = Number(el.height);
let w = Number(el.width); let w = Number(el.width);
let gap = 5; // 對應 span 樣式裡的 margin-left: 5px
// 2. 模擬所有名字的總寬度,找出不會爆框的最佳字體 let namesPerCol = Math.floor((h + span) / (th + span));
while (s >= 8) { if (namesPerCol < 1) namesPerCol = 1;
let s_px = s * 2; // 將 pt 轉 px
let charsPerCol = Math.floor(h / s_px); // 這個字體大小下,垂直一行最多能塞幾個字
console.log(charsPerCol);
if (charsPerCol < 1) charsPerCol = 1;
let totalWidth = 0; // 2. 計算總共會產生幾列 (cols),並推算出每個名字能分配到的最大欄寬
let cols = Math.ceil(slice.length / namesPerCol);
if (cols < 1) cols = 1;
let colWidth = Math.floor(w / cols);
// 加總這批名單的真正排版寬度 html = this.renderNameList(slice, el, colWidth);
slice.forEach((name, index) => {
let cols = Math.ceil(name.length / charsPerCol); // 計算這個人需要折成幾行
let nameWidth = cols * (s_px * 2); // 1.1 為緊密行高 (line-height)
totalWidth += nameWidth;
if (index < slice.length - 1) {
totalWidth += gap; // 加上每個人之間的間距
}
});
// 3. 如果總寬度小於等於容器寬度,代表這個字體剛好能讓所有人塞進去!
if (totalWidth <= w) {
break;
}
s -= 1; // 放不下就縮小 1pt 繼續嘗試
}
// 確保極限最小字體為 4pt
let fontSize = s < 8 ? 8 : s;
html = this.renderNameList(slice, el, 0);
} }
else if (el.id === 'alive') { else if (el.id === 'alive') {
//console.log("createEl:", slice, el) //console.log("createEl:", slice, el)
@@ -1428,6 +1405,35 @@ html, body, * {
}) })
.html(html); .html(html);
}, },
calcIndividualFontSize(name, el, maxW) {
let s = Number(el.style.fontSize);
let maxH = Number(el.textHeight); // 限制在單一名字預設的區塊高度內
let l = Number(name.length);
while (s >= 12) {
let s_px = s * 1.333; // 將 pt 轉換為 px
// 如果單行高度夠放,直接回傳當下大小 (不會過度縮小)
if (l * s_px <= maxH) {
return s;
}
// 單行放不下,模擬多行折疊後的總寬度
let charsPerCol = Math.floor(maxH / s_px);
if (charsPerCol < 1) charsPerCol = 1;
let cols = Math.ceil(l / charsPerCol);
let neededWidth = cols * (s_px * 1.1); // 1.1 為緊密行高
// 如果折疊後的總寬度不超過分配到的橫向欄寬,就是最佳字體
if (neededWidth <= maxW) {
return s;
}
s -= 1; // 否則繼續縮小 1pt
}
return 12; // 極限最小字體
},
countFontSize(name, el, baseFontSize) { countFontSize(name, el, baseFontSize) {
let s = Number(baseFontSize); let s = Number(baseFontSize);
let h = Number(el.height); let h = Number(el.height);
@@ -1484,15 +1490,25 @@ html, body, * {
}) })
return $namelist; return $namelist;
}, },
renderNameSpan(name, el, rowWidth) { renderNameSpan(name, el, colWidth) {
return $(`<span>${name}</span>`).css({ // 為「這個名字」獨立計算出專屬的最完美字體大小
let indSize = this.calcIndividualFontSize(name, el, colWidth);
// 2. 判斷是否發生了折行 (名字長度 * 單字像素高度 > 分配到的最大高度)
let s_px = indSize * 1.333;
let isMultiLine = (name.length * s_px) > Number(el.textHeight);
// 3. 根據是否折行動態決定對齊方式
// 單行:分散對齊 (justify) / 多行:置中對齊 (center) 或是改為 靠上對齊 (start)
let alignStyle = isMultiLine ? "start" : "justify";
return $(`<span style="font-size: ${indSize}pt;">${name}</span>`).css({
display: "block", display: "block",
"min-height": `${el.textHeight}px`, // ★ 拿掉原本的 textHeight 限制,避免短字被硬撐 "min-height": `${el.textHeight}px`,
"max-height": `${el.height}px`, "max-height": `${el.height}px`,
width: "auto", // ★ 讓多行文字自然撐開寬度 width: "auto",
"line-height": "1.1", // ★ 緊密行高,讓折行的「劉三..」跟「陳五」黏緊 "line-height": "1.1",
"text-align": "justify", "text-align": alignStyle, // ★ 動態套用對齊方式
"text-align-last": "justify", "text-align-last": alignStyle, // ★ 動態套用最後一行對齊方式
"margin-left": "5px", "margin-left": "5px",
"text-justify": "inter-character", "text-justify": "inter-character",
"word-break": "break-all" "word-break": "break-all"
@@ -1687,45 +1703,24 @@ html, body, * {
// rowWidth = fontSize * 2; // rowWidth = fontSize * 2;
//} //}
// 1. 初始化最大字體 // 1. 依據 textHeight 與 textSpan 計算一行(垂直列)最多能放幾個名字
let s = Number(el.style.fontSize); let th = Number(el.textHeight) || 0;
let span = Number(el.textSpan) || 0;
let h = Number(el.height); let h = Number(el.height);
let w = Number(el.width); let w = Number(el.width);
let gap = 5; // 對應 span 樣式裡的 margin-left: 5px
// 2. 模擬所有名字的總寬度,找出不會爆框的最佳字體 let namesPerCol = Math.floor((h + span) / (th + span));
while (s >= 8) { if (namesPerCol < 1) namesPerCol = 1;
let s_px = s *2; // 將 pt 轉 px
let charsPerCol = Math.floor(h / s_px); // 這個字體大小下,垂直一行最多能塞幾個字
if (charsPerCol < 1) charsPerCol = 1;
let totalWidth = 0; // 2. 計算總共會產生幾列 (cols),並推算出每個名字能分配到的最大欄寬
let cols = Math.ceil(slice.length / namesPerCol);
if (cols < 1) cols = 1;
let colWidth = Math.floor(w / cols);
// 加總這批名單的真正排版寬度
slice.forEach((name, index) => {
let cols = Math.ceil(name.length / charsPerCol); // 計算這個人需要折成幾行
let nameWidth = cols * (s_px * 2); // 1.1 為緊密行高 (line-height)
totalWidth += nameWidth;
if (index < slice.length - 1) {
totalWidth += gap; // 加上每個人之間的間距
}
});
// 3. 如果總寬度小於等於容器寬度,代表這個字體剛好能讓所有人塞進去!
if (totalWidth <= w) {
break;
}
s -= 1; // 放不下就縮小 1pt 繼續嘗試
}
// 確保極限最小字體為 4pt
let fontSize = s < 8 ? 8 : s;
//console.log(el.height, el.textHeight, perRow, rows, rowWidth, fontSize) //console.log(el.height, el.textHeight, perRow, rows, rowWidth, fontSize)
html = this.renderNameList(slice, el, 0);//el.style.fontSize html = this.renderNameList(slice, el, colWidth);//el.style.fontSize
$(`.tablet-element[id="${this.activeId}"]`).css({ $(`.tablet-element[id="${this.activeId}"]`).css({
position: "absolute", left: el.x + "mm", top: el.y + "mm", fontSize: fontSize + 'pt', fontFamily: el.style.fontFamily, "z-index": 9999, visibility: el.style.visibility position: "absolute", left: el.x + "mm", top: el.y + "mm", fontSize: el.style.fontSize + 'pt', fontFamily: el.style.fontFamily, "z-index": 9999, visibility: el.style.visibility
}).html(html); }).html(html);
} else if (this.activeId === "alive") { } else if (this.activeId === "alive") {
let names = el.text.split('\n').filter(s => s.trim()); let names = el.text.split('\n').filter(s => s.trim());