From 7f1e7dd419405910809614dfe7b3ece60d8daa9a Mon Sep 17 00:00:00 2001 From: minom Date: Fri, 31 Jul 2026 14:45:08 +0800 Subject: [PATCH] =?UTF-8?q?=E7=89=8C=E4=BD=8D=E7=89=88=E5=9E=8B=E8=AA=BF?= =?UTF-8?q?=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/admin/print/TabletDesign.aspx | 176 ++++++++++++------ web/admin/print/print_multi_new.aspx | 145 ++++++++++----- web/admin/print/tablet_edit/editorNewOne.html | 166 ++++++++++------- 3 files changed, 319 insertions(+), 168 deletions(-) diff --git a/web/admin/print/TabletDesign.aspx b/web/admin/print/TabletDesign.aspx index a9f72c1..f85686f 100644 --- a/web/admin/print/TabletDesign.aspx +++ b/web/admin/print/TabletDesign.aspx @@ -1393,19 +1393,19 @@ html, body, * { // fontSize = el.style.fontSize; // rowWidth = fontSize * 2; //} - let th = Number(el.textHeight) || 0; - let span = Number(el.textSpan) || 0; - let h = Number(el.height); - let w = Number(el.width); + //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; + //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); + //// 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); } else { let normal = [] @@ -1723,56 +1723,120 @@ html, body, * { // "text-justify": "inter-character", //});// "margin-bottom": `${el.textSpan}px`, }, - renderLiveList(names, el, rowWidth) { + renderLiveList(names, el) { //console.log("renderLiveList:", names); //$("#imp-text").updateActive("text",names) + //let $namelist = $(`
`).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": "BiauKai", + // //"letter-spacing": `${el.textSpan}px`, + // "column-gap": `${el.textSpan}px`, + // "align-items": "center", + //}); + //// "column-gap": `${el.textSpan}px`, + ////"row-gap": "1px", + //let self = this; + //names.forEach(n => { + // $namelist.append(self.renderLiveSpan(n, el, rowWidth)) + //}) + let h = Number(el.height); + let w = Number(el.width); + let th = Number(el.textHeight) || h; + + // 1. 單純計算總共有幾行 (列) + let namesPerCol = Math.floor(h / th); + if (namesPerCol < 1) namesPerCol = 1; + + let cols = Math.ceil(names.length / namesPerCol); // 總行數 + + // 2. 根據行數,縮小字體直到總寬度放得下 + let s = Number(el.style.fontSize); + while (s >= 4) { + let s_px = s * (4 / 3); // pt 轉 px + let lh = 1.1; // 行高 + let gap = 0; // 對應 span 的 margin-left + + // 總寬度 = 總行數 * (單行像素寬度 + 間距) + let totalWidth = cols * (s_px * lh + gap); + + // 放得下就停止縮小 + if (totalWidth <= w) { + break; + } + s -= 1; + } + + if (s < 4) s = 4; + + // 3. 建立外層 Flexbox 容器 let $namelist = $(`
`).css({ - "writing-mode": "vertical rl", + "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": "BiauKai", - //"letter-spacing": `${el.textSpan}px`, - "column-gap": `${el.textSpan}px`, + "align-content": "center", "align-items": "center", + margin: "auto", + width: `${w}px`, + height: `${h}px`, + border: "0px solid #ccc", + padding: "0px", + "font-family": el.fontFamily, + "column-gap": `${el.textSpan}px`, }); - // "column-gap": `${el.textSpan}px`, - //"row-gap": "1px", + let self = this; - names.forEach(n => { - $namelist.append(self.renderLiveSpan(n, el, rowWidth)) - }) + names.forEach(name => { + $namelist.append(self.renderLiveSpan(name, el, s)); + }); return $namelist; }, - renderLiveSpan(name, el, colWidth) { + renderLiveSpan(name, el, fontSize) { + let th = Number(el.textHeight) || Number(el.height); - // 為「這個名字」獨立計算出專屬的最完美字體大小 - 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 $(`${name}`).css({ + return $(`${name}`).css({ display: "block", - "min-height": `${el.textHeight}px`, + "min-height": `${th}px`, // ★ 固定分配高度,交給 Flexbox 自動排版 "max-height": `${el.height}px`, - width: "auto", - "line-height": "1.1", - "text-align": alignStyle, // ★ 動態套用對齊方式 - "text-align-last": alignStyle, // ★ 動態套用最後一行對齊方式 - "margin-left": "5px", + width: `${fontSize * 1.33}`, + //"line-height": "1.1", + "text-align": "justify", // 統一分散對齊 + "text-align-last": "justify", + //"margin-left": "5px", "text-justify": "inter-character", - "word-break": "break-all" + "word-break": "break-all", + "white-space": "pre-line" }); + //// 為「這個名字」獨立計算出專屬的最完美字體大小 + //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 $(`${name}`).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" + //}); //console.log("renderLiveSpan:", name, el ); //return $(`${name}`).css({ // display: "block", @@ -1955,19 +2019,19 @@ html, body, * { // fontSize = el.style.fontSize; // rowWidth = fontSize * 2; //} - let th = Number(el.textHeight) || 0; - let span = Number(el.textSpan) || 0; - let h = Number(el.height); - let w = Number(el.width); + //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; + //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); + //// 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); $(`.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); diff --git a/web/admin/print/print_multi_new.aspx b/web/admin/print/print_multi_new.aspx index d2d31a0..82180d6 100644 --- a/web/admin/print/print_multi_new.aspx +++ b/web/admin/print/print_multi_new.aspx @@ -588,20 +588,21 @@ // 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 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; + //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); + //// 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); + html = self.renderLiveList(left, d); //newFontSize = d.fontSize; } else if (d.elementID === "titletriangle") { @@ -986,6 +987,21 @@ fix2(val) { return Number.parseFloat(val).toFixed(2); }, + countFontSize(name, el, fontSize, rows) { + if (Number(name.length) * 2 * Number(fontSize) > el.height) { + fontSize = Number(fontSize) - 2; + rows = rows + 1; + let rowWidth = Math.floor(Number(el.width) / rows); + fontSize = Math.floor(rowWidth / 2); + + // 取得遞迴後最終適合的字體大小 + let finalSize = this.countFontSize(name, el, fontSize, rows); + + // 若遞迴底層回傳 0 (代表沒再超過高度),則回傳當下計算出的 fontSize + return finalSize === 0 ? fontSize : finalSize; + } + return 0; // 若原本就沒超過高度,回傳 0 表示不需要縮放 + }, calcIndividualFontSize(name, el, maxW) { let s = Number(el.style ? el.style.fontSize : (el.fontSize ? el.fontSize : 18)); let maxH = Number(el.textHeight); // 限制在單一名字預設的區塊高度內 @@ -1015,51 +1031,94 @@ } return 12; // 極限最小字體 }, - renderLiveList(names, el,rowWidth) { + renderLiveList(names, el) { + //let $namelist = $(`
`).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": "0.1em", + // "column-gap": `${el.textSpan}px`, + // //"row-gap": "1px", + // "align-items": "center", + //}); + //let self = this; + //names.forEach(n => { + // $namelist.append(self.renderLiveSpan(n, el,rowWidth)) + //}) + let h = Number(el.height); + let w = Number(el.width); + let th = Number(el.textHeight) || h; + + // 1. 單純計算總共有幾行 (列) + let namesPerCol = Math.floor(h / th); + if (namesPerCol < 1) namesPerCol = 1; + + let cols = Math.ceil(names.length / namesPerCol); // 總行數 + + // 2. 根據行數,縮小字體直到總寬度放得下 + let s = Number(el.fontSize); + while (s >= 4) { + let s_px = s * (4 / 3); // pt 轉 px + let lh = 1.1; // 行高 + let gap = 0; // 對應 span 的 margin-left + + // 總寬度 = 總行數 * (單行像素寬度 + 間距) + let totalWidth = cols * (s_px * lh + gap); + + // 放得下就停止縮小 + if (totalWidth <= w) { + break; + } + s -= 1; + } + + if (s < 4) s = 4; + + // 3. 建立外層 Flexbox 容器 let $namelist = $(`
`).css({ - "writing-mode": "vertical rl", + "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": "0.1em", - "column-gap": `${el.textSpan}px`, - //"row-gap": "1px", + "align-content": "center", "align-items": "center", + margin: "auto", + width: `${w}px`, + height: `${h}px`, + border: "0px solid #ccc", + padding: "0px", + "font-family": el.fontFamily, + "column-gap": `${el.textSpan}px`, }); + let self = this; - names.forEach(n => { - $namelist.append(self.renderLiveSpan(n, el,rowWidth)) - }) + names.forEach(name => { + $namelist.append(self.renderLiveSpan(name, el, s)); + }); return $namelist; }, - renderLiveSpan(name, el, colWidth) { - // 為「這個名字」獨立計算出專屬的最完美字體大小 - let indSize = this.calcIndividualFontSize(name, el, colWidth); - // 2. 判斷是否發生了折行 (名字長度 * 單字像素高度 > 分配到的最大高度) - let s_px = indSize * 1.333; - let isMultiLine = (name.length * s_px) > Number(el.textHeight); + renderLiveSpan(name, el, fontSize) { + let th = Number(el.textHeight) || Number(el.height); - // 3. 根據是否折行動態決定對齊方式 - // 單行:分散對齊 (justify) / 多行:置中對齊 (center) 或是改為 靠上對齊 (start) - let alignStyle = isMultiLine ? "start" : "justify"; - - return $(`${name}`).css({ + return $(`${name}`).css({ display: "block", - "min-height": `${el.textHeight}px`, + "min-height": `${th}px`, // ★ 固定分配高度,交給 Flexbox 自動排版 "max-height": `${el.height}px`, - width: "auto", - "line-height": "1.1", - "text-align": alignStyle, // ★ 動態套用對齊方式 - "text-align-last": alignStyle, // ★ 動態套用最後一行對齊方式 - "margin-left": "5px", + width: `${fontSize*1.33}`, + //"line-height": "1.1", + "text-align": "justify", // 統一分散對齊 + "text-align-last": "justify", + //"margin-left": "5px", "text-justify": "inter-character", - "word-break": "break-all" + "word-break": "break-all", + "white-space": "pre-line" }); //return $(`${name}`).css({ // display: "block", diff --git a/web/admin/print/tablet_edit/editorNewOne.html b/web/admin/print/tablet_edit/editorNewOne.html index b6cc538..1c7f511 100644 --- a/web/admin/print/tablet_edit/editorNewOne.html +++ b/web/admin/print/tablet_edit/editorNewOne.html @@ -523,21 +523,9 @@ left.push("請選擇"); } newFontSize =d.fontSize //self.scaleFontSize(left, d.fontSize, d.Width); - 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(left.length / namesPerCol); - if (cols < 1) cols = 1; - let colWidth = Math.floor(w / cols); - //console.log(perRow, rows, rowWidth, newFontSize) - //newFontSize = d.fontSize; - html = self.renderLiveList(left, d, colWidth); + //html = self.renderLiveList(left, d, rowWidth); + html = this.renderLiveList(left, d); } else if (d.elementID === "titletriangle") { if (mid.length == 0) { @@ -1331,29 +1319,11 @@ Object.assign(left, self.alive); //this.printData.forEach(x => { let d = details.find(y => y.elementID == "alive"); - //let perRow = Math.floor(Number(d.height) / Number(d.textHeight)); - //let rows = Math.ceil(Number(left.length) / Number(perRow));//總行數 - //let rowWidth = Math.floor(Number(d.width) / rows); - //let 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(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); + let html = this.renderLiveList(left, d); + //self.selectedElement.css("font-size", fontSize + "px"); + + //let html = self.renderLiveList(left, d, rowWidth); $(self.selectedElement).append(html); } else if ($(self.selectedElement).children().first().hasClass("lefttitle") || $(self.selectedElement).children().first().hasClass("righttitle") || @@ -1431,6 +1401,21 @@ } } }, + countFontSize(name, el, fontSize, rows) { + if (Number(name.length) * 2 * Number(fontSize) > el.height) { + fontSize = Number(fontSize) - 2; + rows = rows + 1; + let rowWidth = Math.floor(Number(el.width) / rows); + fontSize = Math.floor(rowWidth / 2); + + // 取得遞迴後最終適合的字體大小 + let finalSize = this.countFontSize(name, el, fontSize, rows); + + // 若遞迴底層回傳 0 (代表沒再超過高度),則回傳當下計算出的 fontSize + return finalSize === 0 ? fontSize : finalSize; + } + return 0; // 若原本就沒超過高度,回傳 0 表示不需要縮放 + }, calcIndividualFontSize(name, el, maxW) { let s = Number(el.style ? el.style.fontSize : (el.fontSize ? el.fontSize : 18)); let maxH = Number(el.textHeight); // 限制在單一名字預設的區塊高度內 @@ -1698,57 +1683,100 @@ //}); return $namelist; }, - renderLiveList(names, el,rowWidth) { + renderLiveList(names, el) { + let h = Number(el.height); + let w = Number(el.width); + let th = Number(el.textHeight) || h; + + // 1. 單純計算總共有幾行 (列) + let namesPerCol = Math.floor(h / th); + if (namesPerCol < 1) namesPerCol = 1; + + let cols = Math.ceil(names.length / namesPerCol); // 總行數 + + // 2. 根據行數,縮小字體直到總寬度放得下 + let s = Number(el.fontSize); + while (s >= 4) { + let s_px = s * (4 / 3); // pt 轉 px + let lh = 1.1; // 行高 + let gap = 0; // 對應 span 的 margin-left + + // 總寬度 = 總行數 * (單行像素寬度 + 間距) + let totalWidth = cols * (s_px * lh + gap); + + // 放得下就停止縮小 + if (totalWidth <= w) { + break; + } + s -= 1; + } + + if (s < 4) s = 4; + + // 3. 建立外層 Flexbox 容器 let $namelist = $(`
`).css({ - "writing-mode": "vertical rl", + "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": "0.1em", - "column-gap": `${el.textSpan}px`, - //"row-gap": "1px", + "align-content": "center", "align-items": "center", + margin: "auto", + width: `${w}px`, + height: `${h}px`, + border: "0px solid #ccc", + padding: "0px", + "font-family": el.fontFamily, + "column-gap": `${el.textSpan}px`, }); + let self = this; - names.forEach(n => { - $namelist.append(self.renderLiveSpan(n, el,rowWidth)) - }) + names.forEach(name => { + $namelist.append(self.renderLiveSpan(name, el, s)); + }); + //let $namelist = $(`
`).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": "0.1em", + // "column-gap": `${el.textSpan}px`, + // //"row-gap": "1px", + // "align-items": "center", + //}); + //let self = this; + //names.forEach(n => { + // $namelist.append(self.renderLiveSpan(n, el,rowWidth)) + //}) return $namelist; }, - renderLiveSpan(name, el, colWidth) { - // 為「這個名字」獨立計算出專屬的最完美字體大小 - let indSize = this.calcIndividualFontSize(name, el, colWidth); - // 2. 判斷是否發生了折行 (名字長度 * 單字像素高度 > 分配到的最大高度) - let s_px = indSize * 1.333; - let isMultiLine = (name.length * s_px) > Number(el.textHeight); + renderLiveSpan(name, el, fontSize) { + let th = Number(el.textHeight) || Number(el.height); - // 3. 根據是否折行動態決定對齊方式 - // 單行:分散對齊 (justify) / 多行:置中對齊 (center) 或是改為 靠上對齊 (start) - let alignStyle = isMultiLine ? "start" : "justify"; - - return $(`${name}`).css({ + return $(`${name}`).css({ display: "block", - "min-height": `${el.textHeight}px`, + "min-height": `${th}px`, // ★ 固定分配高度,交給 Flexbox 自動排版 "max-height": `${el.height}px`, - width: "auto", - "line-height": "1.1", - "text-align": alignStyle, // ★ 動態套用對齊方式 - "text-align-last": alignStyle, // ★ 動態套用最後一行對齊方式 - "margin-left": "5px", + width: `${fontSize * 1.33}`, + //"line-height": "1.1", + "text-align": "justify", // 統一分散對齊 + "text-align-last": "justify", + //"margin-left": "5px", "text-justify": "inter-character", - "word-break": "break-all" + "word-break": "break-all", + "white-space": "pre-line" }); //return $(`${name}`).css({ // display: "block", // "min-height": `${el.textHeight}px`, // "max-height": `${el.height}px`, - // width: `${rowWidth}px`, + // width: `${colWidth}px`, // height: `${el.textHeight}px`, // "text-align": "justify", // "text-align-last": "justify",