牌位排版調整
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
using DocumentFormat.OpenXml.Drawing.Spreadsheet;
|
using DocumentFormat.OpenXml.Drawing.Spreadsheet;
|
||||||
|
using MINOM.COM.Utility;
|
||||||
using Model;
|
using Model;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Org.BouncyCastle.Crypto;
|
using Org.BouncyCastle.Crypto;
|
||||||
@@ -67,6 +68,8 @@ public class activityController : ApiController
|
|||||||
|
|
||||||
// DELETE api/<controller>/5
|
// DELETE api/<controller>/5
|
||||||
public void Delete(int id)
|
public void Delete(int id)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
var prod = _db.activities.Where(q => q.num == id).FirstOrDefault(); //刪除該筆資料
|
var prod = _db.activities.Where(q => q.num == id).FirstOrDefault(); //刪除該筆資料
|
||||||
if (prod != null)
|
if (prod != null)
|
||||||
@@ -98,6 +101,12 @@ public class activityController : ApiController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogUtility log=new LogUtility();
|
||||||
|
log.writeErrorPath(ex.ToString()+ex.StackTrace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[HttpDelete]
|
[HttpDelete]
|
||||||
[Route("api/activity/DeleteItem/{id}")]
|
[Route("api/activity/DeleteItem/{id}")]
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using MINOM.COM.Utility;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
@@ -46,14 +47,23 @@ public class ezAuthorizeAttribute : AuthorizeAttribute
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected override bool IsAuthorized(HttpActionContext actionContext)
|
protected override bool IsAuthorized(HttpActionContext actionContext)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
MyWeb.admin admin = new MyWeb.admin();
|
MyWeb.admin admin = new MyWeb.admin();
|
||||||
bool isLogin = admin.isLoign();
|
bool isLogin = admin.isLoign();
|
||||||
//if (admin.chkAdmIP && (admin.chkTwIP || admin.chkAdmIP_Enable)) { }
|
//if (admin.chkAdmIP && (admin.chkTwIP || admin.chkAdmIP_Enable)) { }
|
||||||
//判斷是否登入
|
//判斷是否登入
|
||||||
if (!isLogin) {
|
if (!isLogin)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogUtility log = new LogUtility();
|
||||||
|
log.writeErrorPath(ex.ToString()+ex.StackTrace);
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
if (actionContext == null)
|
if (actionContext == null)
|
||||||
{
|
{
|
||||||
|
|||||||
+351
-105
@@ -1365,6 +1365,7 @@ html, body, * {
|
|||||||
// fontSize = el.style.fontSize;
|
// fontSize = el.style.fontSize;
|
||||||
// rowWidth = fontSize * 2;
|
// rowWidth = fontSize * 2;
|
||||||
//}
|
//}
|
||||||
|
|
||||||
fontSize = el.style.fontSize;
|
fontSize = el.style.fontSize;
|
||||||
// 1. 依據 textHeight 與 textSpan 計算一行(垂直列)最多能放幾個名字
|
// 1. 依據 textHeight 與 textSpan 計算一行(垂直列)最多能放幾個名字
|
||||||
let th = Number(el.textHeight) || 0;
|
let th = Number(el.textHeight) || 0;
|
||||||
@@ -1380,31 +1381,77 @@ html, body, * {
|
|||||||
if (cols < 1) cols = 1;
|
if (cols < 1) cols = 1;
|
||||||
let colWidth = Math.floor(w / cols);
|
let colWidth = Math.floor(w / cols);
|
||||||
|
|
||||||
html = this.renderNameList(slice, el, colWidth);
|
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)
|
||||||
let perRow = Math.floor(Number(el.height) / Number(el.textHeight));
|
//let perRow = Math.floor(Number(el.height) / Number(el.textHeight));
|
||||||
let rows = Math.ceil(Number(slice.length) / Number(perRow));//總行數
|
//let rows = Math.ceil(Number(slice.length) / Number(perRow));//總行數
|
||||||
let rowWidth = Math.floor(Number(el.width) / rows);
|
//let rowWidth = Math.floor(Number(el.width) / rows);
|
||||||
fontSize = Math.floor(rowWidth / 2);
|
//fontSize = Math.floor(rowWidth / 2);
|
||||||
if (fontSize > el.style.fontSize) {
|
//if (fontSize > el.style.fontSize) {
|
||||||
fontSize = el.style.fontSize;
|
// fontSize = el.style.fontSize;
|
||||||
rowWidth = fontSize * 2;
|
// rowWidth = fontSize * 2;
|
||||||
}
|
//}
|
||||||
html = this.renderLiveList(slice, el, rowWidth);
|
let th = Number(el.textHeight) || 0;
|
||||||
|
let span = Number(el.textSpan) || 0;
|
||||||
|
let h = Number(el.height);
|
||||||
|
let w = Number(el.width);
|
||||||
|
|
||||||
|
let namesPerCol = Math.floor((h + span) / (th + span));
|
||||||
|
if (namesPerCol < 1) namesPerCol = 1;
|
||||||
|
|
||||||
|
// 2. 計算總共會產生幾列 (cols),並推算出每個名字能分配到的最大欄寬
|
||||||
|
let cols = Math.ceil(slice.length / namesPerCol);
|
||||||
|
if (cols < 1) cols = 1;
|
||||||
|
let colWidth = Math.floor(w / cols);
|
||||||
|
html = this.renderLiveList(slice, el, colWidth);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
html = el.text;
|
let normal = []
|
||||||
|
normal.push(el.text);
|
||||||
|
html = this.renderNormalWithSpace(normal,el)
|
||||||
|
//html = el.text;
|
||||||
}
|
}
|
||||||
//el.style.fontSize
|
//el.style.fontSize
|
||||||
return $(`<div class="tablet-element vertical-text ${this.activeId === el.id ? 'selected' : ''}" id="${el.id}"></div>`)
|
return $(`<div class="tablet-element vertical-text ${this.activeId === el.id ? 'selected' : ''}" id="${el.id}"></div>`)
|
||||||
.css({
|
.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", fontFamily: el.style.fontFamily, "z-index": 9999, visibility: el.style.visibility
|
||||||
//position: "absolute", left: el.startX + "mm", top: el.startY + "mm", fontSize: el.fontSize + 'pt', fontFamily: el.fontFamily, "z-index": 9999, visibility: el.isActive
|
//position: "absolute", left: el.startX + "mm", top: el.startY + "mm", fontSize: el.fontSize + 'pt', fontFamily: el.fontFamily, "z-index": 9999, visibility: el.isActive
|
||||||
})
|
})
|
||||||
.html(html);
|
.html(html);
|
||||||
},
|
},
|
||||||
|
renderNormalWithSpace(mid, d) {
|
||||||
|
console.log("renderNormal:", d)
|
||||||
|
let self = this;
|
||||||
|
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",
|
||||||
|
//"letter-spacing": "0.1em",
|
||||||
|
"column-gap": `${d.textSpan}px`,
|
||||||
|
//"row-gap": "1px",
|
||||||
|
"align-items": "flex-start",
|
||||||
|
"justify-content": "start",
|
||||||
|
"font-size":`${d.style?d.style.fontSize:d.fontSize}pt`
|
||||||
|
});
|
||||||
|
//console.log("吼優:",mid);
|
||||||
|
mid.forEach(x => {
|
||||||
|
let dd = $(`<div>${x}</div>`).css({
|
||||||
|
"margin-bottom": "10px",
|
||||||
|
"margin-left": "5px",
|
||||||
|
"text-justify": "inter-character",
|
||||||
|
"white-space": "pre-line",
|
||||||
|
});
|
||||||
|
$(txt).append(dd);
|
||||||
|
});
|
||||||
|
return txt;
|
||||||
|
},
|
||||||
calcIndividualFontSize(name, el, maxW) {
|
calcIndividualFontSize(name, el, maxW) {
|
||||||
let s = Number(el.style.fontSize);
|
let s = Number(el.style.fontSize);
|
||||||
let maxH = Number(el.textHeight); // 限制在單一名字預設的區塊高度內
|
let maxH = Number(el.textHeight); // 限制在單一名字預設的區塊高度內
|
||||||
@@ -1413,106 +1460,257 @@ html, body, * {
|
|||||||
while (s >= 12) {
|
while (s >= 12) {
|
||||||
let s_px = s * 1.333; // 將 pt 轉換為 px
|
let s_px = s * 1.333; // 將 pt 轉換為 px
|
||||||
|
|
||||||
|
|
||||||
// 如果單行高度夠放,直接回傳當下大小 (不會過度縮小)
|
// 如果單行高度夠放,直接回傳當下大小 (不會過度縮小)
|
||||||
if (l * s_px <= maxH) {
|
//if (l * s_px <= maxH) {
|
||||||
return s;
|
// return s;
|
||||||
}
|
//}
|
||||||
|
|
||||||
// 單行放不下,模擬多行折疊後的總寬度
|
// 單行放不下,模擬多行折疊後的總寬度
|
||||||
let charsPerCol = Math.floor(maxH / s_px);
|
let charsPerCol = Math.floor(maxH / s_px);
|
||||||
if (charsPerCol < 1) charsPerCol = 1;
|
if (charsPerCol < 1) charsPerCol = 1;
|
||||||
|
|
||||||
let cols = Math.ceil(l / charsPerCol);
|
let cols = Math.ceil(l / charsPerCol);
|
||||||
let neededWidth = cols * (s_px * 1.1); // 1.1 為緊密行高
|
let neededWidth = (cols===1)?s_px:cols * (s_px * 1.1); // 1.1 為緊密行高
|
||||||
|
|
||||||
// 如果折疊後的總寬度不超過分配到的橫向欄寬,就是最佳字體
|
// 如果折疊後的總寬度不超過分配到的橫向欄寬,就是最佳字體
|
||||||
if (neededWidth <= maxW) {
|
if (neededWidth <= maxW&&(cols>1||l*s_px<=maxH)) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
s -= 1; // 否則繼續縮小 1pt
|
s -= 1; // 否則繼續縮小 1pt
|
||||||
}
|
}
|
||||||
return 12; // 極限最小字體
|
return 12; // 極限最小字體
|
||||||
},
|
},
|
||||||
|
renderNameList(names, el, rowWidth) {
|
||||||
countFontSize(name, el, baseFontSize) {
|
|
||||||
let s = Number(baseFontSize);
|
|
||||||
let h = Number(el.height);
|
let h = Number(el.height);
|
||||||
let w = Number(el.width);
|
let w = Number(el.width);
|
||||||
let l = Number(name.length);
|
let th = Number(el.textHeight) || h;
|
||||||
|
let gap = 5; // 對應 span 的 margin-left
|
||||||
|
|
||||||
// 逐步縮小字體 (最低限制到 4pt)
|
let s = Number(el.style.fontSize);
|
||||||
while (s >= 4) {
|
let sizes = [];
|
||||||
// ★ 關鍵修正:將 pt 轉換為實際的像素(px)高度 (1pt ≈ 1.333px)
|
|
||||||
let s_px = s * 1.333;
|
|
||||||
|
|
||||||
// 如果單行的高度夠放
|
//// 1. 模擬排版:找出能讓全體塞入的最佳字體組合
|
||||||
if (l * s_px <= h) {
|
//while (s >= 12) {
|
||||||
// 如果原本的字體就放得下回傳 0,否則回傳縮小後的字體大小
|
// let short_s_px = s * 1.333;
|
||||||
return s === Number(baseFontSize) ? 0 : s;
|
// let long_s = Math.floor(s * 0.75); // 長字體最多縮小 25%
|
||||||
}
|
// if (long_s < 12) long_s = 12;
|
||||||
|
// let long_s_px = long_s * 1.333;
|
||||||
|
|
||||||
// 單行放不下,必須折行
|
// let currentColHeight = 0;
|
||||||
let charsPerCol = Math.floor(h / s_px); // 一行(垂直)最多能塞幾個字
|
// let totalWidth = 0;
|
||||||
|
// let tempSizes = [];
|
||||||
|
|
||||||
|
// for (let i = 0; i < names.length; i++) {
|
||||||
|
// let name = names[i];
|
||||||
|
// let l = name.length;
|
||||||
|
// let isMulti = (l * short_s_px) > th;
|
||||||
|
|
||||||
|
// let size = isMulti ? long_s : s;
|
||||||
|
// let size_px = isMulti ? long_s_px : short_s_px;
|
||||||
|
|
||||||
|
// tempSizes.push({ name: name, size: size, isMulti: isMulti });
|
||||||
|
|
||||||
|
// 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 (currentColHeight > 0 && (currentColHeight + th + gap) <= h) {
|
||||||
|
// currentColHeight += th + gap;
|
||||||
|
// } else {
|
||||||
|
// currentColHeight = th;
|
||||||
|
// totalWidth += short_s_px + gap;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (totalWidth > 0) totalWidth -= gap;
|
||||||
|
|
||||||
|
// // 總寬度未爆框,確定最佳組合
|
||||||
|
// if (totalWidth <= w) {
|
||||||
|
// sizes = tempSizes;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// s -= 1;
|
||||||
|
//}
|
||||||
|
|
||||||
|
//// 處理極端情況
|
||||||
|
//if (sizes.length === 0) {
|
||||||
|
// sizes = names.map(name => {
|
||||||
|
// return { name: name, size: 12, isMulti: (name.length * 12 * 1.333) > th };
|
||||||
|
// });
|
||||||
|
//}
|
||||||
|
// 1. 模擬排版:找出能讓全體塞入的最佳字體組合
|
||||||
|
while (s >= 12) {
|
||||||
|
let short_s_px = s * 1.333;
|
||||||
|
let hasShort = names.some(n => (n.length * short_s_px) <= th);
|
||||||
|
|
||||||
|
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 currentColHeight = 0;
|
||||||
|
let totalWidth = 0;
|
||||||
|
let tempSizes = [];
|
||||||
|
let anyWrapped = false;
|
||||||
|
for (let i = 0; i < names.length; i++) {
|
||||||
|
let name = names[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 (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;
|
if (charsPerCol < 1) charsPerCol = 1;
|
||||||
|
let lines = Math.ceil(l / charsPerCol);
|
||||||
|
let nameW = lines * (size_px * 1.1); // 1.1倍行距
|
||||||
|
|
||||||
let cols = Math.ceil(l / charsPerCol); // 計算總共需要折成幾行
|
if (currentColHeight > 0) currentColHeight = 0;
|
||||||
let neededWidth = cols * (s_px * 1.2); // 估算折行後需要的總像素寬度 (1.2為行距緩衝)
|
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;
|
||||||
if (neededWidth <= w) {
|
|
||||||
return s;
|
// 總寬度未爆框,確定最佳組合
|
||||||
|
if (totalWidth <= w) {
|
||||||
|
if (hasShort) {
|
||||||
|
sizes = tempSizes;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if (!anyWrapped || s === 12) {
|
||||||
|
sizes = tempSizes;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
s -= 1; // 放不下則縮小 1pt 繼續嘗試
|
|
||||||
}
|
}
|
||||||
return 8; // 極限最小字體
|
|
||||||
},
|
}
|
||||||
renderNameList(names, el,rowWidth) {
|
s -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 處理極端情況
|
||||||
|
if (sizes.length === 0) {
|
||||||
|
sizes = names.map(name => {
|
||||||
|
return { name: name, size: 12, isMulti: (name.length * 12 * 1.333) > th };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 建立外層的 Flexbox 容器
|
||||||
let $namelist = $(`<div class='nameList'></div>`).css({
|
let $namelist = $(`<div class='nameList'></div>`).css({
|
||||||
"writing-mode": "vertical rl",
|
"writing-mode": "vertical-rl",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
"flex-direction": "row",
|
"flex-direction": "row",
|
||||||
"flex-wrap": "wrap",
|
"flex-wrap": "wrap",
|
||||||
|
"align-content": "center",
|
||||||
|
"align-items": "center", // 確保元素靠上對齊
|
||||||
margin: "auto",
|
margin: "auto",
|
||||||
width: `${el.width}px`,
|
width: `${el.width}px`,
|
||||||
height: `${el.height}px`,
|
height: `${el.height}px`,
|
||||||
border: "0px solid #ccc",
|
border: "0px solid #ccc",
|
||||||
padding: "1px",
|
padding: "1px",
|
||||||
"font-family": el.fontFamily,
|
|
||||||
//"letter-spacing": `${el.textSpan}px`,
|
|
||||||
"column-gap": `${el.textSpan}px`,
|
"column-gap": `${el.textSpan}px`,
|
||||||
"align-items": "center",
|
"font-family": el.fontFamily
|
||||||
});
|
});
|
||||||
//
|
|
||||||
//"row-gap": "1px",
|
// 3. 將資料物件傳給 renderNameSpan 產生子元素
|
||||||
let self = this;
|
let self = this;
|
||||||
names.forEach(n => {
|
sizes.forEach(item => {
|
||||||
$namelist.append(self.renderNameSpan(n, el, rowWidth))
|
$namelist.append(self.renderNameSpan(item, el));
|
||||||
})
|
});
|
||||||
|
|
||||||
return $namelist;
|
return $namelist;
|
||||||
|
//let $namelist = $(`<div class='nameList'></div>`).css({
|
||||||
|
// "writing-mode": "vertical rl",
|
||||||
|
// display: "flex",
|
||||||
|
// "flex-direction": "row",
|
||||||
|
// "flex-wrap": "wrap",
|
||||||
|
// margin: "auto",
|
||||||
|
// width: `${el.width}px`,
|
||||||
|
// height: `${el.height}px`,
|
||||||
|
// border: "0px solid #ccc",
|
||||||
|
// padding: "1px",
|
||||||
|
// "font-family": el.fontFamily,
|
||||||
|
// //"letter-spacing": `${el.textSpan}px`,
|
||||||
|
// "column-gap": `${el.textSpan}px`,
|
||||||
|
// "align-items": "center",
|
||||||
|
//});
|
||||||
|
////
|
||||||
|
////"row-gap": "1px",
|
||||||
|
//let self = this;
|
||||||
|
//names.forEach(n => {
|
||||||
|
// $namelist.append(self.renderNameSpan(n, el, rowWidth))
|
||||||
|
//})
|
||||||
|
//return $namelist;
|
||||||
},
|
},
|
||||||
renderNameSpan(name, el, colWidth) {
|
renderNameSpan(item, el, colWidth) {
|
||||||
// 為「這個名字」獨立計算出專屬的最完美字體大小
|
let th = Number(el.textHeight) || Number(el.height)
|
||||||
let indSize = this.calcIndividualFontSize(name, el, colWidth);
|
//let minH = item.isMulti ? `${d.height}px` : `${d.textHeight}px`;
|
||||||
// 2. 判斷是否發生了折行 (名字長度 * 單字像素高度 > 分配到的最大高度)
|
let minH = item.isShort ? `${th}px` : `${el.height}px`
|
||||||
let s_px = indSize * 1.333;
|
;
|
||||||
let isMultiLine = (name.length * s_px) > Number(el.textHeight);
|
let alignStyle = item.isMulti ? "start" : "justify";
|
||||||
|
|
||||||
// 3. 根據是否折行動態決定對齊方式
|
return $(`<span style="font-size: ${item.size}pt;">${item.name}</span>`).css({
|
||||||
// 單行:分散對齊 (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`,
|
"min-height": minH, // 強制多行長名撐滿高度,避免其他名字墊底
|
||||||
"max-height": `${el.height}px`,
|
"max-height": `${el.height}px`,
|
||||||
width: "auto",
|
width: "auto",
|
||||||
"line-height": "1.1",
|
"line-height": "1.1",
|
||||||
"text-align": alignStyle, // ★ 動態套用對齊方式
|
"text-align": alignStyle,
|
||||||
"text-align-last": alignStyle, // ★ 動態套用最後一行對齊方式
|
"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"
|
||||||
});
|
});
|
||||||
|
//// 為「這個名字」獨立計算出專屬的最完美字體大小
|
||||||
|
//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",
|
||||||
|
// "min-height": `${el.textHeight}px`,
|
||||||
|
// "max-height": `${el.height}px`,
|
||||||
|
// width: "auto",
|
||||||
|
// "line-height": "1.1",
|
||||||
|
// "text-align": alignStyle, // ★ 動態套用對齊方式
|
||||||
|
// "text-align-last": alignStyle, // ★ 動態套用最後一行對齊方式
|
||||||
|
// "margin-left": "5px",
|
||||||
|
// "text-justify": "inter-character",
|
||||||
|
// "word-break": "break-all"
|
||||||
|
//});
|
||||||
//return $(`<span>${name}</span>`).css({
|
//return $(`<span>${name}</span>`).css({
|
||||||
// display: "block",
|
// display: "block",
|
||||||
// "min-height": `${el.textHeight}px`,
|
// "min-height": `${el.textHeight}px`,
|
||||||
@@ -1551,19 +1749,42 @@ html, body, * {
|
|||||||
})
|
})
|
||||||
return $namelist;
|
return $namelist;
|
||||||
},
|
},
|
||||||
renderLiveSpan(name, el, rowWidth) {
|
renderLiveSpan(name, el, colWidth) {
|
||||||
//console.log("renderLiveSpan:", name, el );
|
|
||||||
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`,
|
"min-height": `${el.textHeight}px`,
|
||||||
"max-height": `${el.height}px`,
|
"max-height": `${el.height}px`,
|
||||||
width: `${rowWidth}px`,
|
width: "auto",
|
||||||
"text-align": "justify",
|
"line-height": "1.1",
|
||||||
"text-align-last": "justify",
|
"text-align": alignStyle, // ★ 動態套用對齊方式
|
||||||
|
"text-align-last": alignStyle, // ★ 動態套用最後一行對齊方式
|
||||||
"margin-left": "5px",
|
"margin-left": "5px",
|
||||||
"text-justify": "inter-character",
|
"text-justify": "inter-character",
|
||||||
});//"margin-bottom": `${el.textSpan}px`,
|
"word-break": "break-all"
|
||||||
|
});
|
||||||
|
//console.log("renderLiveSpan:", name, el );
|
||||||
|
//return $(`<span>${name}</span>`).css({
|
||||||
|
// display: "block",
|
||||||
|
// "min-height": `${el.textHeight}px`,
|
||||||
|
// "max-height": `${el.height}px`,
|
||||||
|
// width: `${rowWidth}px`,
|
||||||
|
// "text-align": "justify",
|
||||||
|
// "text-align-last": "justify",
|
||||||
|
|
||||||
|
// "margin-left": "5px",
|
||||||
|
// "text-justify": "inter-character",
|
||||||
|
//});//"margin-bottom": `${el.textSpan}px`,
|
||||||
},
|
},
|
||||||
// 品字佈局邏輯:一上二下
|
// 品字佈局邏輯:一上二下
|
||||||
renderRoster(names, el,rowWidth) {
|
renderRoster(names, el,rowWidth) {
|
||||||
@@ -1704,6 +1925,7 @@ html, body, * {
|
|||||||
//}
|
//}
|
||||||
|
|
||||||
// 1. 依據 textHeight 與 textSpan 計算一行(垂直列)最多能放幾個名字
|
// 1. 依據 textHeight 與 textSpan 計算一行(垂直列)最多能放幾個名字
|
||||||
|
|
||||||
let th = Number(el.textHeight) || 0;
|
let th = Number(el.textHeight) || 0;
|
||||||
let span = Number(el.textSpan) || 0;
|
let span = Number(el.textSpan) || 0;
|
||||||
let h = Number(el.height);
|
let h = Number(el.height);
|
||||||
@@ -1718,47 +1940,71 @@ html, body, * {
|
|||||||
let colWidth = Math.floor(w / cols);
|
let colWidth = Math.floor(w / cols);
|
||||||
|
|
||||||
//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, colWidth);//el.style.fontSize
|
html = this.renderNameList(slice, el, 0);//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: el.style.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());
|
||||||
let slice = names.slice(0 * this.rosterLimit, (0 + 1) * this.rosterLimit);
|
let slice = names.slice(0 * this.rosterLimit, (0 + 1) * this.rosterLimit);
|
||||||
let perRow = Math.floor(Number(el.height) / Number(el.textHeight));
|
//let perRow = Math.floor(Number(el.height) / Number(el.textHeight));
|
||||||
let rows = Math.ceil(Number(slice.length) / Number(perRow));//總行數
|
//let rows = Math.ceil(Number(slice.length) / Number(perRow));//總行數
|
||||||
let rowWidth = Math.floor(Number(el.width) / rows);
|
//let rowWidth = Math.floor(Number(el.width) / rows);
|
||||||
let fontSize = Math.floor(rowWidth / 2);
|
//let fontSize = Math.floor(rowWidth / 2);
|
||||||
if (fontSize > el.style.fontSize) {
|
//if (fontSize > el.style.fontSize) {
|
||||||
fontSize = el.style.fontSize;
|
// fontSize = el.style.fontSize;
|
||||||
rowWidth = fontSize * 2;
|
// rowWidth = fontSize * 2;
|
||||||
}
|
//}
|
||||||
html = this.renderLiveList(slice, el, rowWidth);
|
let th = Number(el.textHeight) || 0;
|
||||||
$(`.tablet-element[id="${this.activeId}"]`).css({
|
let span = Number(el.textSpan) || 0;
|
||||||
position: "absolute", left: el.x + "mm", top: el.y + "mm", fontSize: fontSize + 'pt', fontFamily: el.style.fontFamily, "z-index": 9999, visibility: el.style.visibility
|
let h = Number(el.height);
|
||||||
}).html(html);
|
let w = Number(el.width);
|
||||||
} else if (this.activeId === "righttitle") {
|
|
||||||
$(`.tablet-element[id="${this.activeId}"]`).css({
|
let namesPerCol = Math.floor((h + span) / (th + span));
|
||||||
position: "absolute", left: el.x + "mm", top: el.y + "mm", fontSize: el.style.fontSize + 'pt',
|
if (namesPerCol < 1) namesPerCol = 1;
|
||||||
fontFamily: el.style.fontFamily, "z-index": 9999, visibility: el.style.visibility,
|
|
||||||
width: el.width, height: el.height
|
// 2. 計算總共會產生幾列 (cols),並推算出每個名字能分配到的最大欄寬
|
||||||
}).text(el.text);
|
let cols = Math.ceil(slice.length / namesPerCol);
|
||||||
} else if (this.activeId === "lefttitle") {
|
if (cols < 1) cols = 1;
|
||||||
$(`.tablet-element[id="${this.activeId}"]`).css({
|
let colWidth = Math.floor(w / cols);
|
||||||
position: "absolute", left: el.x + "mm", top: el.y + "mm", fontSize: el.style.fontSize + 'pt',
|
html = this.renderLiveList(slice, el, colWidth);
|
||||||
fontFamily: el.style.fontFamily, "z-index": 9999, visibility: el.style.visibility,
|
|
||||||
width: el.width, height: el.height
|
|
||||||
}).text(el.text);
|
|
||||||
} else if (this.activeId === "address") {
|
|
||||||
$(`.tablet-element[id="${this.activeId}"]`).css({
|
|
||||||
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,
|
|
||||||
width: el.width, height: el.height
|
|
||||||
}).text(el.text);
|
|
||||||
} else {
|
|
||||||
$(`.tablet-element[id="${this.activeId}"]`).css({
|
$(`.tablet-element[id="${this.activeId}"]`).css({
|
||||||
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
|
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
|
||||||
}).text(el.text);
|
}).html(html);
|
||||||
|
} else if (this.activeId === "righttitle") {
|
||||||
|
let normal = [];
|
||||||
|
normal.push(el.text)
|
||||||
|
html = this.renderNormalWithSpace(normal,el)
|
||||||
|
$(`.tablet-element[id="${this.activeId}"]`).css({
|
||||||
|
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,
|
||||||
|
width: el.width, height: el.height
|
||||||
|
}).html(html)//.text(el.text);
|
||||||
|
} else if (this.activeId === "lefttitle") {
|
||||||
|
let normal = [];
|
||||||
|
normal.push(el.text)
|
||||||
|
html = this.renderNormalWithSpace(normal, el)
|
||||||
|
$(`.tablet-element[id="${this.activeId}"]`).css({
|
||||||
|
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,
|
||||||
|
width: el.width, height: el.height
|
||||||
|
}).html(html)//.text(el.text);
|
||||||
|
} else if (this.activeId === "address") {
|
||||||
|
let normal = [];
|
||||||
|
normal.push(el.text)
|
||||||
|
html = this.renderNormalWithSpace(normal, el)
|
||||||
|
$(`.tablet-element[id="${this.activeId}"]`).css({
|
||||||
|
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,
|
||||||
|
width: el.width, height: el.height
|
||||||
|
}).html(html)//.text(el.text);
|
||||||
|
} else {
|
||||||
|
let normal = [];
|
||||||
|
normal.push(el.text)
|
||||||
|
html = this.renderNormalWithSpace(normal, el)
|
||||||
|
$(`.tablet-element[id="${this.activeId}"]`).css({
|
||||||
|
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)//.text(el.text);
|
||||||
}
|
}
|
||||||
//this.render();
|
//this.render();
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -147,9 +147,9 @@
|
|||||||
<rect fill="none" height="510.24" id="TXT_x5F_L" width="51.02" x="16.06" y="479.15"/>
|
<rect fill="none" height="510.24" id="TXT_x5F_L" width="51.02" x="16.06" y="479.15"/>
|
||||||
<rect fill="none" height="45.35" id="TXT_x5F_T1" width="283.46" x="39.43" y="4.16"/>
|
<rect fill="none" height="45.35" id="TXT_x5F_T1" width="283.46" x="39.43" y="4.16"/>
|
||||||
<rect fill="none" height="34.02" id="TXT_x5F_T2" width="70.87" x="274.24" y="57.72"/>
|
<rect fill="none" height="34.02" id="TXT_x5F_T2" width="70.87" x="274.24" y="57.72"/>
|
||||||
<text fill="#000000" font-family="DFKai-SB" font-size="24" font-weight="bold" id="svg_129" stroke="#000000" stroke-width="0" text-anchor="middle" x="46.58" xml:space="preserve" y="491.14">陽</text>
|
<text fill="#000000" font-family="DFKai-SB" font-size="24" font-weight="bold" id="svg_129" stroke="#000000" stroke-width="0" text-anchor="middle" x="35.58" xml:space="preserve" y="491.14">陽</text>
|
||||||
<text fill="#000000" font-family="DFKai-SB" font-size="24" font-weight="bold" id="svg_130" stroke="#000000" stroke-width="0" text-anchor="middle" x="46.58" xml:space="preserve" y="521.14">上</text>
|
<text fill="#000000" font-family="DFKai-SB" font-size="24" font-weight="bold" id="svg_130" stroke="#000000" stroke-width="0" text-anchor="middle" x="35.58" xml:space="preserve" y="521.14">上</text>
|
||||||
<text fill="#000000" font-family="DFKai-SB" font-size="24" font-weight="bold" id="svg_131" stroke="#000000" stroke-width="0" text-anchor="middle" x="46.58" xml:space="preserve" y="920.14">拜</text>
|
<text fill="#000000" font-family="DFKai-SB" font-size="24" font-weight="bold" id="svg_131" stroke="#000000" stroke-width="0" text-anchor="middle" x="35.58" xml:space="preserve" y="920.14">拜</text>
|
||||||
<text fill="#000000" font-family="DFKai-SB" font-size="24" font-weight="bold" id="svg_132" stroke="#000000" stroke-width="0" text-anchor="middle" x="46.58" xml:space="preserve" y="950.14">薦</text>
|
<text fill="#000000" font-family="DFKai-SB" font-size="24" font-weight="bold" id="svg_132" stroke="#000000" stroke-width="0" text-anchor="middle" x="35.58" xml:space="preserve" y="950.14">薦</text>
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 99 KiB After Width: | Height: | Size: 99 KiB |
@@ -367,92 +367,263 @@
|
|||||||
let ancestorFontSize = 16;
|
let ancestorFontSize = 16;
|
||||||
details.forEach(d => {
|
details.forEach(d => {
|
||||||
if (d.isActive != "hidden") {
|
if (d.isActive != "hidden") {
|
||||||
let newFontSize = self.scaleFontSize(mid, d.fontSize, d.width);
|
let newFontSize =d.fontSize //self.scaleFontSize(mid, d.fontSize, d.width);
|
||||||
|
|
||||||
let html = "";
|
let html = "";
|
||||||
let alive = "";
|
let alive = "";
|
||||||
let yang = "";
|
let yang = "";
|
||||||
let bi = "";
|
let bi = "";
|
||||||
if (d.elementID === 'title1') {
|
if (d.elementID === 'title1') {
|
||||||
let perRow = Math.floor(Number(d.height) / Number(d.textHeight));
|
|
||||||
let rows = Math.ceil(Number(mid.length) / Number(perRow));//總行數
|
let h = Number(d.height);
|
||||||
let rowWidth = Math.floor(Number(d.width) / rows);
|
let w = Number(d.width);
|
||||||
newFontSize = Math.floor(rowWidth / 2);
|
let th = Number(d.textHeight) || h;
|
||||||
if (newFontSize > d.fontSize) {
|
let gap = 5; // 對應 span 的 margin-left
|
||||||
newFontSize = d.fontSize;
|
|
||||||
rowWidth = newFontSize * 2;
|
let s = Number(d.fontSize);
|
||||||
|
let sizes = [];
|
||||||
|
|
||||||
|
// 1. 模擬排版:找出能讓全體塞入的最佳字體組合
|
||||||
|
while (s >= 12) {
|
||||||
|
let short_s_px = s * 1.333;
|
||||||
|
let hasShort = mid.some(n => (n.length * short_s_px) <= th);
|
||||||
|
|
||||||
|
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 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;
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
currentColHeight = 0;
|
||||||
|
totalWidth += size_px + gap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (totalWidth > 0) totalWidth -= gap;
|
||||||
|
|
||||||
|
// 總寬度未爆框,確定最佳組合
|
||||||
|
if (totalWidth <= w) {
|
||||||
|
if (hasShort) {
|
||||||
|
sizes = tempSizes;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if (!anyWrapped || s === 12) {
|
||||||
|
sizes = tempSizes;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
s -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 處理極端情況
|
||||||
|
if (sizes.length === 0) {
|
||||||
|
sizes = names.map(name => {
|
||||||
|
return { name: name, size: 12, isMulti: (name.length * 12 * 1.333) > th };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 建立外層的 Flexbox 容器
|
||||||
let $namelist = $(`<div class='nameList'></div>`).css({
|
let $namelist = $(`<div class='nameList'></div>`).css({
|
||||||
"writing-mode": "vertical rl",
|
"writing-mode": "vertical-rl",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
"flex-direction": "row",
|
"flex-direction": "row",
|
||||||
"flex-wrap": "wrap",
|
"flex-wrap": "wrap",
|
||||||
|
"align-content": "center",
|
||||||
|
"align-items": "center", // 確保元素靠上對齊
|
||||||
margin: "auto",
|
margin: "auto",
|
||||||
width: `${d.width}px`,
|
width: `${d.width}px`,
|
||||||
height: `${d.height}px`,
|
height: `${d.height}px`,
|
||||||
border: "0px solid #ccc",
|
border: "0px solid #ccc",
|
||||||
padding: "1px",
|
padding: "1px",
|
||||||
"font-family": style.fontFamily,
|
|
||||||
//"letter-spacing": "0.1em",
|
|
||||||
"column-gap": `${d.textSpan}px`,
|
"column-gap": `${d.textSpan}px`,
|
||||||
//"row-gap": "1px",
|
"font-family":d.fontFamily
|
||||||
"align-items": "center",
|
|
||||||
"justify-content": "start",
|
|
||||||
});
|
});
|
||||||
|
sizes.forEach(item => {
|
||||||
|
let th = Number(d.textHeight) || Number(d.height)
|
||||||
|
//let minH = item.isMulti ? `${d.height}px` : `${d.textHeight}px`;
|
||||||
|
let minH = item.isShort ? `${th}px` : `${d.height}px`
|
||||||
|
;
|
||||||
|
let alignStyle = item.isMulti ? "start" : "justify";
|
||||||
|
|
||||||
mid.forEach(z => {
|
let $span= $(`<span style="font-size: ${item.size}pt;">${item.name}</span>`).css({
|
||||||
let info = self.getTextInfo(z, newFontSize);
|
|
||||||
let spanWidth = mid.length > 1 ? newFontSize : d.width
|
|
||||||
let height = d.textHeight;
|
|
||||||
if (info.height >= d.textHeight) {//width
|
|
||||||
height = d.height;
|
|
||||||
}
|
|
||||||
let $span = $(`<span class="nameSpan">${z}</span>`).css({
|
|
||||||
display: "block",
|
display: "block",
|
||||||
"min-height": `${height}px`,
|
"min-height": minH, // 強制多行長名撐滿高度,避免其他名字墊底
|
||||||
"max-height": `${d.height}px`,
|
"max-height": `${d.height}px`,
|
||||||
"max-width": `${rowWidth}px`,
|
width: "auto",
|
||||||
//width: `${newFontSize}px`,
|
"line-height": "1.1",
|
||||||
"text-align": "justify",
|
"text-align": alignStyle,
|
||||||
"text-align-last": "justify",
|
"text-align-last": alignStyle,
|
||||||
//"margin-bottom": "20px",
|
|
||||||
"margin-left": "5px",
|
"margin-left": "5px",
|
||||||
"text-justify": "inter-character",
|
"text-justify": "inter-character",
|
||||||
"white-space": "pre-line",
|
"word-break": "break-all"
|
||||||
//"justify-content":"center"
|
|
||||||
});
|
});
|
||||||
$namelist.append($span);
|
$namelist.append($span);
|
||||||
});
|
});
|
||||||
|
//let perRow = Math.floor(Number(d.height) / Number(d.textHeight));
|
||||||
|
//let rows = Math.ceil(Number(mid.length) / Number(perRow));//總行數
|
||||||
|
//let rowWidth = Math.floor(Number(d.width) / rows);
|
||||||
|
//newFontSize = Math.floor(rowWidth / 2);
|
||||||
|
//if (newFontSize > d.fontSize) {
|
||||||
|
// newFontSize = d.fontSize;
|
||||||
|
// rowWidth = newFontSize * 2;
|
||||||
|
//}
|
||||||
|
//let th = Number(d.textHeight) || 0;
|
||||||
|
//let span = Number(d.textSpan) || 0;
|
||||||
|
//let h = Number(d.height);
|
||||||
|
//let w = Number(d.width);
|
||||||
|
|
||||||
|
//let namesPerCol = Math.floor((h + span) / (th + span));
|
||||||
|
//if (namesPerCol < 1) namesPerCol = 1;
|
||||||
|
|
||||||
|
//// 2. 計算總共會產生幾列 (cols),並推算出每個名字能分配到的最大欄寬
|
||||||
|
//let cols = Math.ceil(mid.length / namesPerCol);
|
||||||
|
//if (cols < 1) cols = 1;
|
||||||
|
//let colWidth = Math.floor(w / cols);
|
||||||
|
//let $namelist = $(`<div class='nameList'></div>`).css({
|
||||||
|
// "writing-mode": "vertical rl",
|
||||||
|
// display: "flex",
|
||||||
|
// "flex-direction": "row",
|
||||||
|
// "flex-wrap": "wrap",
|
||||||
|
// margin: "auto",
|
||||||
|
// width: `${d.width}px`,
|
||||||
|
// height: `${d.height}px`,
|
||||||
|
// border: "0px solid #ccc",
|
||||||
|
// padding: "1px",
|
||||||
|
// "font-family": style.fontFamily,
|
||||||
|
// //"letter-spacing": "0.1em",
|
||||||
|
// "column-gap": `${d.textSpan}px`,
|
||||||
|
// //"row-gap": "1px",
|
||||||
|
// "align-items": "center",
|
||||||
|
// "justify-content": "start",
|
||||||
|
//});
|
||||||
|
|
||||||
|
//mid.forEach(z => {
|
||||||
|
// //let info = self.getTextInfo(z, newFontSize);
|
||||||
|
// //let spanWidth = mid.length > 1 ? newFontSize : d.width
|
||||||
|
// //let height = d.textHeight;
|
||||||
|
// //if (info.height >= d.textHeight) {//width
|
||||||
|
// // height = d.height;
|
||||||
|
// //}
|
||||||
|
// //let $span = $(`<span class="nameSpan">${z}</span>`).css({
|
||||||
|
// // display: "block",
|
||||||
|
// // "min-height": `${height}px`,
|
||||||
|
// // "max-height": `${d.height}px`,
|
||||||
|
// // "max-width": `${rowWidth}px`,
|
||||||
|
// // //width: `${newFontSize}px`,
|
||||||
|
// // "text-align": "justify",
|
||||||
|
// // "text-align-last": "justify",
|
||||||
|
// // //"margin-bottom": "20px",
|
||||||
|
// // "margin-left": "5px",
|
||||||
|
// // "text-justify": "inter-character",
|
||||||
|
// // "white-space": "pre-line",
|
||||||
|
// // //"justify-content":"center"
|
||||||
|
// //});
|
||||||
|
// let indSize = this.calcIndividualFontSize(z, d, colWidth);
|
||||||
|
// // 2. 判斷是否發生了折行 (名字長度 * 單字像素高度 > 分配到的最大高度)
|
||||||
|
// let s_px = indSize * 1.333;
|
||||||
|
// let isMultiLine = (z.length * s_px) > Number(d.textHeight);
|
||||||
|
|
||||||
|
// // 3. 根據是否折行動態決定對齊方式
|
||||||
|
// // 單行:分散對齊 (justify) / 多行:置中對齊 (center) 或是改為 靠上對齊 (start)
|
||||||
|
// let alignStyle = isMultiLine ? "start" : "justify";
|
||||||
|
// let $span = $(`<span style="font-size: ${indSize}pt;">${z}</span>`).css({
|
||||||
|
// display: "block",
|
||||||
|
// "min-height": `${d.textHeight}px`,
|
||||||
|
// "max-height": `${d.height}px`,
|
||||||
|
// width: "auto",
|
||||||
|
// "line-height": "1.1",
|
||||||
|
// "text-align": alignStyle, // ★ 動態套用對齊方式
|
||||||
|
// "text-align-last": alignStyle, // ★ 動態套用最後一行對齊方式
|
||||||
|
// "margin-left": "5px",
|
||||||
|
// "text-justify": "inter-character",
|
||||||
|
// "word-break": "break-all"
|
||||||
|
// });
|
||||||
|
// $namelist.append($span);
|
||||||
|
//});
|
||||||
|
|
||||||
html = $namelist;
|
html = $namelist;
|
||||||
} else if (d.elementID === "alive") {
|
} else if (d.elementID === "alive") {
|
||||||
let perRow = Math.floor(Number(d.height) / Number(d.textHeight));
|
//let perRow = Math.floor(Number(d.height) / Number(d.textHeight));
|
||||||
let rows = Math.ceil(Number(left.length) / Number(perRow));//總行數
|
//let rows = Math.ceil(Number(left.length) / Number(perRow));//總行數
|
||||||
let rowWidth = Math.floor(Number(d.width) / rows);
|
//let rowWidth = Math.floor(Number(d.width) / rows);
|
||||||
newFontSize = Math.floor(rowWidth / 2);
|
//newFontSize = Math.floor(rowWidth / 2);
|
||||||
if (newFontSize > d.fontSize) {
|
//if (newFontSize > d.fontSize) {
|
||||||
newFontSize = d.fontSize;
|
// newFontSize = d.fontSize;
|
||||||
rowWidth = newFontSize * 2;
|
// rowWidth = newFontSize * 2;
|
||||||
}
|
//}
|
||||||
console.log(d.height,d.width,d.textHeight,perRow,rows,rowWidth,newFontSize,d)
|
let th = Number(d.textHeight) || 0;
|
||||||
html = self.renderLiveList(left, d, rowWidth);
|
let span = Number(d.textSpan) || 0;
|
||||||
|
let h = Number(d.height);
|
||||||
|
let w = Number(d.width);
|
||||||
|
|
||||||
|
let namesPerCol = Math.floor((h + span) / (th + span));
|
||||||
|
if (namesPerCol < 1) namesPerCol = 1;
|
||||||
|
|
||||||
|
// 2. 計算總共會產生幾列 (cols),並推算出每個名字能分配到的最大欄寬
|
||||||
|
let cols = Math.ceil(left.length / namesPerCol);
|
||||||
|
if (cols < 1) cols = 1;
|
||||||
|
let colWidth = Math.floor(w / cols);
|
||||||
|
|
||||||
|
html = self.renderLiveList(left, d, colWidth);
|
||||||
|
|
||||||
//newFontSize = d.fontSize;
|
//newFontSize = d.fontSize;
|
||||||
} else if (d.elementID === "titletriangle") {
|
} else if (d.elementID === "titletriangle") {
|
||||||
|
newFontSize = self.scaleFontSize(mid, d.fontSize, d.width);
|
||||||
html = self.renderRoster(mid, d)
|
html = self.renderRoster(mid, d)
|
||||||
} else if (d.elementID === "combined") {
|
} else if (d.elementID === "combined") {
|
||||||
ancestorFontSize = d.fontSize;
|
ancestorFontSize = d.fontSize;
|
||||||
|
newFontSize = self.scaleFontSize(mid, d.fontSize, d.width);
|
||||||
const parts = mid.join("\n").split('\n');
|
const parts = mid.join("\n").split('\n');
|
||||||
html = `<div class="ancestor-wrapper" style="width:${d.width}px !important;height:${d.height}px !important;" >
|
html = `<div class="ancestor-wrapper" style="width:${d.width}px !important;height:${d.height}px !important;" >
|
||||||
<span class="main-name" >${parts[0] || ''}</span>
|
<span class="main-name" >${parts[0] || ''}</span>
|
||||||
<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);
|
||||||
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);
|
||||||
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);
|
||||||
html = self.renderNormal(righttitle, d)
|
html = self.renderNormal(righttitle, d)
|
||||||
}
|
}
|
||||||
if (newFontSize < 10) {
|
if (newFontSize < 10) {
|
||||||
@@ -815,6 +986,35 @@
|
|||||||
fix2(val) {
|
fix2(val) {
|
||||||
return Number.parseFloat(val).toFixed(2);
|
return Number.parseFloat(val).toFixed(2);
|
||||||
},
|
},
|
||||||
|
calcIndividualFontSize(name, el, maxW) {
|
||||||
|
let s = Number(el.style ? el.style.fontSize : (el.fontSize ? el.fontSize : 18));
|
||||||
|
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 === 1) ? s_px : cols * (s_px * 1.1); // 1.1 為緊密行高
|
||||||
|
|
||||||
|
// 如果折疊後的總寬度不超過分配到的橫向欄寬,就是最佳字體
|
||||||
|
if (neededWidth <= maxW && (cols > 1 || l * s_px <= maxH)) {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
s -= 1; // 否則繼續縮小 1pt
|
||||||
|
}
|
||||||
|
return 12; // 極限最小字體
|
||||||
|
},
|
||||||
renderLiveList(names, el,rowWidth) {
|
renderLiveList(names, el,rowWidth) {
|
||||||
let $namelist = $(`<div class='liveList'></div>`).css({
|
let $namelist = $(`<div class='liveList'></div>`).css({
|
||||||
"writing-mode": "vertical rl",
|
"writing-mode": "vertical rl",
|
||||||
@@ -838,19 +1038,41 @@
|
|||||||
})
|
})
|
||||||
return $namelist;
|
return $namelist;
|
||||||
},
|
},
|
||||||
renderLiveSpan(name, el,rowWidth) {
|
renderLiveSpan(name, el, colWidth) {
|
||||||
return $(`<span class="liveSpan">${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`,
|
"min-height": `${el.textHeight}px`,
|
||||||
"max-height": `${el.height}px`,
|
"max-height": `${el.height}px`,
|
||||||
width: `${rowWidth}px`,
|
width: "auto",
|
||||||
|
"line-height": "1.1",
|
||||||
"text-align": "justify",
|
"text-align": alignStyle, // ★ 動態套用對齊方式
|
||||||
"text-align-last": "justify",
|
"text-align-last": alignStyle, // ★ 動態套用最後一行對齊方式
|
||||||
"margin-bottom": "10px",
|
"margin-left": "5px",
|
||||||
"text-justify": "inter-character",
|
"text-justify": "inter-character",
|
||||||
"white-space": "pre-line"
|
"word-break": "break-all"
|
||||||
});
|
});
|
||||||
|
//return $(`<span class="liveSpan">${name}</span>`).css({
|
||||||
|
// display: "block",
|
||||||
|
// "min-height": `${el.textHeight}px`,
|
||||||
|
// "max-height": `${el.height}px`,
|
||||||
|
// width: `${rowWidth}px`,
|
||||||
|
|
||||||
|
// "text-align": "justify",
|
||||||
|
// "text-align-last": "justify",
|
||||||
|
// "margin-bottom": "10px",
|
||||||
|
// "text-justify": "inter-character",
|
||||||
|
// "white-space": "pre-line"
|
||||||
|
//});
|
||||||
},
|
},
|
||||||
// 品字佈局邏輯:一上二下
|
// 品字佈局邏輯:一上二下
|
||||||
renderRoster(names, el) {
|
renderRoster(names, el) {
|
||||||
|
|||||||
@@ -368,13 +368,14 @@
|
|||||||
|
|
||||||
if (response.status == 200) {
|
if (response.status == 200) {
|
||||||
self.printData = response.data;
|
self.printData = response.data;
|
||||||
|
console.log("GetDetailToPrint:",response);
|
||||||
self.printData.forEach(x => {
|
self.printData.forEach(x => {
|
||||||
//console.log("GetDetailToPrint:",x.style);
|
//console.log("GetDetailToPrint:",x.style);
|
||||||
if (x.style != null && x.style != undefined) {
|
if (x.style != null && x.style != undefined) {
|
||||||
self.selectStyle.style = x.style;
|
self.selectStyle.style = x.style;
|
||||||
self.selected.style = x.style;
|
self.selected.style = x.style;
|
||||||
self.defaultStyle = x.style;
|
self.defaultStyle = x.style;
|
||||||
//$("#styleSel").val(x.style)
|
$("#styleSel").val(x.style)
|
||||||
}
|
}
|
||||||
if (x.f_num_tablet != "") {
|
if (x.f_num_tablet != "") {
|
||||||
let tablet = JSON.parse(x.f_num_tablet);
|
let tablet = JSON.parse(x.f_num_tablet);
|
||||||
@@ -500,33 +501,43 @@
|
|||||||
if (mid.length == 0) {
|
if (mid.length == 0) {
|
||||||
mid.push("請選擇")
|
mid.push("請選擇")
|
||||||
}
|
}
|
||||||
let perRow = Math.floor(Number(d.height) / Number(d.textHeight));
|
// 1. 依據 textHeight 與 textSpan 計算一行(垂直列)最多能放幾個名字
|
||||||
let rows = Math.ceil(Number(mid.length) / Number(perRow));//總行數
|
|
||||||
let rowWidth = Math.floor(Number(d.width) / rows);
|
let th = Number(d.textHeight) || 0;
|
||||||
newFontSize = Math.floor(rowWidth / 2);
|
let span = Number(d.textSpan) || 0;
|
||||||
if (newFontSize > d.fontSize) {
|
let h = Number(d.height);
|
||||||
newFontSize = d.fontSize;
|
let w = Number(d.width);
|
||||||
rowWidth = newFontSize * 2;
|
|
||||||
}
|
let namesPerCol = Math.floor((h + span) / (th + span));
|
||||||
|
if (namesPerCol < 1) namesPerCol = 1;
|
||||||
|
|
||||||
|
// 2. 計算總共會產生幾列 (cols),並推算出每個名字能分配到的最大欄寬
|
||||||
|
let cols = Math.ceil(mid.length / namesPerCol);
|
||||||
|
if (cols < 1) cols = 1;
|
||||||
|
let colWidth = Math.floor(w / cols);
|
||||||
//console.log(perRow, rows, rowWidth, newFontSize)
|
//console.log(perRow, rows, rowWidth, newFontSize)
|
||||||
html = self.renderNameList(mid, d, newFontSize, style, rowWidth);
|
html = self.renderNameList(mid, d, newFontSize, style, colWidth);
|
||||||
} else if (d.elementID === "alive") {
|
} else if (d.elementID === "alive") {
|
||||||
self.tabletType = "B";
|
self.tabletType = "B";
|
||||||
if (left.length == 0) {
|
if (left.length == 0) {
|
||||||
left.push("請選擇");
|
left.push("請選擇");
|
||||||
}
|
}
|
||||||
newFontSize = self.scaleFontSize(left, d.fontSize, d.Width);
|
newFontSize =d.fontSize //self.scaleFontSize(left, d.fontSize, d.Width);
|
||||||
let perRow = Math.floor(Number(d.height) / Number(d.textHeight));
|
let th = Number(d.textHeight) || 0;
|
||||||
let rows = Math.ceil(Number(left.length) / Number(perRow));//總行數
|
let span = Number(d.textSpan) || 0;
|
||||||
let rowWidth = Math.floor(Number(d.width) / rows);
|
let h = Number(d.height);
|
||||||
newFontSize = Math.floor(rowWidth / 2);
|
let w = Number(d.width);
|
||||||
if (newFontSize > d.fontSize) {
|
|
||||||
newFontSize = d.fontSize;
|
let namesPerCol = Math.floor((h + span) / (th + span));
|
||||||
rowWidth = newFontSize * 2;
|
if (namesPerCol < 1) namesPerCol = 1;
|
||||||
}
|
|
||||||
|
// 2. 計算總共會產生幾列 (cols),並推算出每個名字能分配到的最大欄寬
|
||||||
|
let cols = Math.ceil(left.length / namesPerCol);
|
||||||
|
if (cols < 1) cols = 1;
|
||||||
|
let colWidth = Math.floor(w / cols);
|
||||||
//console.log(perRow, rows, rowWidth, newFontSize)
|
//console.log(perRow, rows, rowWidth, newFontSize)
|
||||||
//newFontSize = d.fontSize;
|
//newFontSize = d.fontSize;
|
||||||
html = self.renderLiveList(left, d, rowWidth);
|
html = self.renderLiveList(left, d, colWidth);
|
||||||
|
|
||||||
} else if (d.elementID === "titletriangle") {
|
} else if (d.elementID === "titletriangle") {
|
||||||
if (mid.length == 0) {
|
if (mid.length == 0) {
|
||||||
@@ -1320,16 +1331,29 @@
|
|||||||
Object.assign(left, self.alive);
|
Object.assign(left, self.alive);
|
||||||
//this.printData.forEach(x => {
|
//this.printData.forEach(x => {
|
||||||
let d = details.find(y => y.elementID == "alive");
|
let d = details.find(y => y.elementID == "alive");
|
||||||
let perRow = Math.floor(Number(d.height) / Number(d.textHeight));
|
//let perRow = Math.floor(Number(d.height) / Number(d.textHeight));
|
||||||
let rows = Math.ceil(Number(left.length) / Number(perRow));//總行數
|
//let rows = Math.ceil(Number(left.length) / Number(perRow));//總行數
|
||||||
let rowWidth = Math.floor(Number(d.width) / rows);
|
//let rowWidth = Math.floor(Number(d.width) / rows);
|
||||||
let newFontSize = Math.floor(rowWidth / 2);
|
//let newFontSize = Math.floor(rowWidth / 2);
|
||||||
if (newFontSize > d.fontSize) {
|
//if (newFontSize > d.fontSize) {
|
||||||
newFontSize = d.fontSize;
|
// newFontSize = d.fontSize;
|
||||||
rowWidth = newFontSize * 2;
|
// rowWidth = newFontSize * 2;
|
||||||
}
|
//}
|
||||||
self.selectedElement.css("font-size", newFontSize+"px");
|
let th = Number(d.textHeight) || 0;
|
||||||
let html = self.renderLiveList(left, d);
|
let span = Number(d.textSpan) || 0;
|
||||||
|
let h = Number(d.height);
|
||||||
|
let w = Number(d.width);
|
||||||
|
|
||||||
|
let namesPerCol = Math.floor((h + span) / (th + span));
|
||||||
|
if (namesPerCol < 1) namesPerCol = 1;
|
||||||
|
|
||||||
|
// 2. 計算總共會產生幾列 (cols),並推算出每個名字能分配到的最大欄寬
|
||||||
|
let cols = Math.ceil(left.length / namesPerCol);
|
||||||
|
if (cols < 1) cols = 1;
|
||||||
|
let colWidth = Math.floor(w / cols);
|
||||||
|
self.selectedElement.css("font-size", d.fontSize + "px");
|
||||||
|
console.log("B d:",d)
|
||||||
|
let html = self.renderLiveList(left, d,colWidth);
|
||||||
$(self.selectedElement).append(html);
|
$(self.selectedElement).append(html);
|
||||||
} else if ($(self.selectedElement).children().first().hasClass("lefttitle") ||
|
} else if ($(self.selectedElement).children().first().hasClass("lefttitle") ||
|
||||||
$(self.selectedElement).children().first().hasClass("righttitle") ||
|
$(self.selectedElement).children().first().hasClass("righttitle") ||
|
||||||
@@ -1365,21 +1389,24 @@
|
|||||||
$(self.selectedElement).empty();
|
$(self.selectedElement).empty();
|
||||||
let d = details.find(y => y.elementID == "title1");
|
let d = details.find(y => y.elementID == "title1");
|
||||||
let newfontSize = self.scaleFontSize(mid, d.fontSize, d.textWidth)
|
let newfontSize = self.scaleFontSize(mid, d.fontSize, d.textWidth)
|
||||||
let perRow = Math.floor(Number(d.height) / Number(d.textHeight));
|
// 1. 依據 textHeight 與 textSpan 計算一行(垂直列)最多能放幾個名字
|
||||||
let rows = Math.ceil(Number(mid.length) / Number(perRow));//總行數
|
|
||||||
let rowWidth = Math.floor(Number(d.width) / rows);
|
//let th = Number(d.textHeight) || 0;
|
||||||
newfontSize = Math.floor(rowWidth / 2);
|
//let span = Number(d.textSpan) || 0;
|
||||||
if (newfontSize > d.fontSize) {
|
//let h = Number(d.height);
|
||||||
newfontSize = d.fontSize;
|
//let w = Number(d.width);
|
||||||
rowWidth = newfontSize * 2;
|
|
||||||
}
|
//let namesPerCol = Math.floor((h + span) / (th + span));
|
||||||
if (newfontSize < 10) {
|
//if (namesPerCol < 1) namesPerCol = 1;
|
||||||
newfontSize = 10;
|
|
||||||
}
|
//// 2. 計算總共會產生幾列 (cols),並推算出每個名字能分配到的最大欄寬
|
||||||
|
//let cols = Math.ceil(mid.length / namesPerCol);
|
||||||
|
//if (cols < 1) cols = 1;
|
||||||
|
//let colWidth = Math.floor(w / cols);
|
||||||
//console.log(self.selectedElement,perRow, rows, rowWidth, newfontSize)
|
//console.log(self.selectedElement,perRow, rows, rowWidth, newfontSize)
|
||||||
|
|
||||||
self.selectedElement.css("font-size", newfontSize+"px");
|
self.selectedElement.css("font-size", newfontSize+"px");
|
||||||
let html = self.renderNameList(mid, d, style.fontSize, style,rowWidth);
|
let html = self.renderNameList(mid, d, style.fontSize, style,0);
|
||||||
$(self.selectedElement).append(html);
|
$(self.selectedElement).append(html);
|
||||||
} else if ($(self.selectedElement).children().first().hasClass("rosterList")) {
|
} else if ($(self.selectedElement).children().first().hasClass("rosterList")) {
|
||||||
$(self.selectedElement).empty();
|
$(self.selectedElement).empty();
|
||||||
@@ -1404,6 +1431,35 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
calcIndividualFontSize(name, el, maxW) {
|
||||||
|
let s = Number(el.style ? el.style.fontSize : (el.fontSize ? el.fontSize : 18));
|
||||||
|
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 === 1) ? s_px : cols * (s_px * 1.1); // 1.1 為緊密行高
|
||||||
|
|
||||||
|
// 如果折疊後的總寬度不超過分配到的橫向欄寬,就是最佳字體
|
||||||
|
if (neededWidth <= maxW && (cols > 1 || l * s_px <= maxH)) {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
s -= 1; // 否則繼續縮小 1pt
|
||||||
|
}
|
||||||
|
return 12; // 極限最小字體
|
||||||
|
},
|
||||||
async itemAppend(e) {
|
async itemAppend(e) {
|
||||||
//console.log(e);
|
//console.log(e);
|
||||||
},
|
},
|
||||||
@@ -1456,49 +1512,190 @@
|
|||||||
});
|
});
|
||||||
return txt;
|
return txt;
|
||||||
},
|
},
|
||||||
renderNameList(mid, d, newFontSize, style,rowWidth) {
|
renderNameList(names, d, newFontSize, style, colWidth) {
|
||||||
let self = this;
|
let self = this;
|
||||||
|
let h = Number(d.height);
|
||||||
|
let w = Number(d.width);
|
||||||
|
let th = Number(d.textHeight) || h;
|
||||||
|
let gap = 5; // 對應 span 的 margin-left
|
||||||
|
|
||||||
|
let s = Number(d.fontSize);
|
||||||
|
let sizes = [];
|
||||||
|
|
||||||
|
// 1. 模擬排版:找出能讓全體塞入的最佳字體組合
|
||||||
|
while (s >= 12) {
|
||||||
|
let short_s_px = s * 1.333;
|
||||||
|
let hasShort = names.some(n => (n.length * short_s_px) <= th);
|
||||||
|
|
||||||
|
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 currentColHeight = 0;
|
||||||
|
let totalWidth = 0;
|
||||||
|
let tempSizes = [];
|
||||||
|
let anyWrapped = false;
|
||||||
|
for (let i = 0; i < names.length; i++) {
|
||||||
|
let name = names[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 (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;
|
||||||
|
|
||||||
|
// 總寬度未爆框,確定最佳組合
|
||||||
|
if (totalWidth <= w) {
|
||||||
|
if (hasShort) {
|
||||||
|
sizes = tempSizes;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if (!anyWrapped || s === 12) {
|
||||||
|
sizes = tempSizes;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
s -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 處理極端情況
|
||||||
|
if (sizes.length === 0) {
|
||||||
|
sizes = names.map(name => {
|
||||||
|
return { name: name, size: 12, isMulti: (name.length * 12 * 1.333) > th };
|
||||||
|
});
|
||||||
|
}
|
||||||
let $namelist = $(`<div class='nameList'></div>`).css({
|
let $namelist = $(`<div class='nameList'></div>`).css({
|
||||||
"writing-mode": "vertical rl",
|
"writing-mode": "vertical-rl",
|
||||||
display: "flex",
|
display: "flex",
|
||||||
"flex-direction": "row",
|
"flex-direction": "row",
|
||||||
"flex-wrap": "wrap",
|
"flex-wrap": "wrap",
|
||||||
|
"align-content": "center",
|
||||||
|
"align-items": "center", // 確保元素靠上對齊
|
||||||
margin: "auto",
|
margin: "auto",
|
||||||
width: `${d.width}px`,
|
width: `${d.width}px`,
|
||||||
height: `${d.height}px`,
|
height: `${d.height}px`,
|
||||||
border: "0px solid #ccc",
|
border: "0px solid #ccc",
|
||||||
padding: "1px",
|
padding: "1px",
|
||||||
"font-family": style.fontFamily,
|
|
||||||
//"letter-spacing": "0.1em",
|
|
||||||
"column-gap": `${d.textSpan}px`,
|
"column-gap": `${d.textSpan}px`,
|
||||||
//"row-gap": "1px",
|
"font-family": d.fontFamily
|
||||||
"align-items": "center",
|
|
||||||
"justify-content": "start",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
mid.forEach(z => {
|
sizes.forEach(item => {
|
||||||
let info = self.getTextInfo(z, newFontSize);
|
let th = Number(d.textHeight) || Number(d.height)
|
||||||
let spanWidth = mid.length > 1 ? newFontSize : d.width
|
//let minH = item.isMulti ? `${d.height}px` : `${d.textHeight}px`;
|
||||||
let height = d.textHeight;
|
let minH = item.isShort ? `${th}px` : `${d.height}px`
|
||||||
if (info.width >= d.textHeight) {
|
;
|
||||||
height = d.height;
|
let alignStyle = item.isMulti ? "start" : "justify";
|
||||||
}
|
|
||||||
let $span = $(`<span class="nameSpan">${z}</span>`).css({
|
let $span= $(`<span style="font-size: ${item.size}pt;">${item.name}</span>`).css({
|
||||||
display: "block",
|
display: "block",
|
||||||
"min-height": `${height}px`,
|
"min-height": minH, // 強制多行長名撐滿高度,避免其他名字墊底
|
||||||
"max-height": `${d.height}px`,
|
"max-height": `${d.height}px`,
|
||||||
"max-width": `${rowWidth}px`,
|
width: "auto",
|
||||||
//width: `${newFontSize}px`,
|
"line-height": "1.1",
|
||||||
"text-align": "justify",
|
"text-align": alignStyle,
|
||||||
"text-align-last": "justify",
|
"text-align-last": alignStyle,
|
||||||
//"margin-bottom": "20px",
|
|
||||||
"margin-left": "5px",
|
"margin-left": "5px",
|
||||||
"text-justify": "inter-character",
|
"text-justify": "inter-character",
|
||||||
"white-space": "pre-line",
|
"word-break": "break-all"
|
||||||
//"justify-content":"center"
|
|
||||||
});
|
});
|
||||||
$namelist.append($span);
|
$namelist.append($span);
|
||||||
});
|
})
|
||||||
|
//let $namelist = $(`<div class='nameList'></div>`).css({
|
||||||
|
// "writing-mode": "vertical rl",
|
||||||
|
// display: "flex",
|
||||||
|
// "flex-direction": "row",
|
||||||
|
// "flex-wrap": "wrap",
|
||||||
|
// margin: "auto",
|
||||||
|
// width: `${d.width}px`,
|
||||||
|
// height: `${d.height}px`,
|
||||||
|
// border: "0px solid #ccc",
|
||||||
|
// padding: "1px",
|
||||||
|
// "font-family": style.fontFamily,
|
||||||
|
// //"letter-spacing": "0.1em",
|
||||||
|
// "column-gap": `${d.textSpan}px`,
|
||||||
|
// //"row-gap": "1px",
|
||||||
|
// "align-items": "center",
|
||||||
|
// "justify-content": "start",
|
||||||
|
//});
|
||||||
|
|
||||||
|
//mid.forEach(z => {
|
||||||
|
// //let info = self.getTextInfo(z, newFontSize);
|
||||||
|
// //let spanWidth = mid.length > 1 ? newFontSize : d.width
|
||||||
|
// //let height = d.textHeight;
|
||||||
|
// //if (info.width >= d.textHeight) {
|
||||||
|
// // height = d.height;
|
||||||
|
// //}
|
||||||
|
// //let $span = $(`<span class="nameSpan">${z}</span>`).css({
|
||||||
|
// // display: "block",
|
||||||
|
// // "min-height": `${height}px`,
|
||||||
|
// // "max-height": `${d.height}px`,
|
||||||
|
// // "max-width": `${rowWidth}px`,
|
||||||
|
// // //width: `${newFontSize}px`,
|
||||||
|
// // "text-align": "justify",
|
||||||
|
// // "text-align-last": "justify",
|
||||||
|
// // //"margin-bottom": "20px",
|
||||||
|
// // "margin-left": "5px",
|
||||||
|
// // "text-justify": "inter-character",
|
||||||
|
// // "white-space": "pre-line",
|
||||||
|
// // //"justify-content":"center"
|
||||||
|
// //});
|
||||||
|
// // 為「這個名字」獨立計算出專屬的最完美字體大小
|
||||||
|
// let indSize = this.calcIndividualFontSize(z, d, colWidth);
|
||||||
|
// // 2. 判斷是否發生了折行 (名字長度 * 單字像素高度 > 分配到的最大高度)
|
||||||
|
// let s_px = indSize * 1.333;
|
||||||
|
// let isMultiLine = (z.length * s_px) > Number(d.textHeight);
|
||||||
|
|
||||||
|
// // 3. 根據是否折行動態決定對齊方式
|
||||||
|
// // 單行:分散對齊 (justify) / 多行:置中對齊 (center) 或是改為 靠上對齊 (start)
|
||||||
|
// let alignStyle = isMultiLine ? "start" : "justify";
|
||||||
|
// let $span = $(`<span style="font-size: ${indSize}pt;">${z}</span>`).css({
|
||||||
|
// display: "block",
|
||||||
|
// "min-height": `${d.textHeight}px`,
|
||||||
|
// "max-height": `${d.height}px`,
|
||||||
|
// width: "auto",
|
||||||
|
// "line-height": "1.1",
|
||||||
|
// "text-align": alignStyle, // ★ 動態套用對齊方式
|
||||||
|
// "text-align-last": alignStyle, // ★ 動態套用最後一行對齊方式
|
||||||
|
// "margin-left": "5px",
|
||||||
|
// "text-justify": "inter-character",
|
||||||
|
// "word-break": "break-all"
|
||||||
|
// });
|
||||||
|
// $namelist.append($span);
|
||||||
|
//});
|
||||||
return $namelist;
|
return $namelist;
|
||||||
},
|
},
|
||||||
renderLiveList(names, el,rowWidth) {
|
renderLiveList(names, el,rowWidth) {
|
||||||
@@ -1524,19 +1721,41 @@
|
|||||||
})
|
})
|
||||||
return $namelist;
|
return $namelist;
|
||||||
},
|
},
|
||||||
renderLiveSpan(name, el,rowWidth) {
|
renderLiveSpan(name, el, colWidth) {
|
||||||
return $(`<span class="liveSpan">${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`,
|
"min-height": `${el.textHeight}px`,
|
||||||
"max-height": `${el.height}px`,
|
"max-height": `${el.height}px`,
|
||||||
width: `${rowWidth}px`,
|
width: "auto",
|
||||||
height: `${el.textHeight}px`,
|
"line-height": "1.1",
|
||||||
"text-align": "justify",
|
"text-align": alignStyle, // ★ 動態套用對齊方式
|
||||||
"text-align-last": "justify",
|
"text-align-last": alignStyle, // ★ 動態套用最後一行對齊方式
|
||||||
//"margin-bottom": "10px",
|
"margin-left": "5px",
|
||||||
"text-justify": "inter-character",
|
"text-justify": "inter-character",
|
||||||
"white-space": "pre-line"
|
"word-break": "break-all"
|
||||||
});
|
});
|
||||||
|
//return $(`<span class="liveSpan">${name}</span>`).css({
|
||||||
|
// display: "block",
|
||||||
|
// "min-height": `${el.textHeight}px`,
|
||||||
|
// "max-height": `${el.height}px`,
|
||||||
|
// width: `${rowWidth}px`,
|
||||||
|
// height: `${el.textHeight}px`,
|
||||||
|
// "text-align": "justify",
|
||||||
|
// "text-align-last": "justify",
|
||||||
|
// //"margin-bottom": "10px",
|
||||||
|
// "text-justify": "inter-character",
|
||||||
|
// "white-space": "pre-line"
|
||||||
|
//});
|
||||||
},
|
},
|
||||||
// 品字佈局邏輯:一上二下
|
// 品字佈局邏輯:一上二下
|
||||||
renderRoster(names, el) {
|
renderRoster(names, el) {
|
||||||
|
|||||||
Reference in New Issue
Block a user