feat:web text maxLines

This commit is contained in:
钱泽虹 2023-09-13 19:08:28 +08:00 committed by osborn
parent afb3de1fbc
commit d71e55e673
3 changed files with 56 additions and 42 deletions

View File

@ -7204,7 +7204,6 @@ var doric_web = (function (exports, axios, sandbox) {
const div = document.createElement('div'); const div = document.createElement('div');
div.style.display = "flex"; div.style.display = "flex";
div.style.overflow = "hidden"; div.style.overflow = "hidden";
div.style.lineHeight = `${this.lineHeight()}em`;
this.textElement = document.createElement('span'); this.textElement = document.createElement('span');
div.appendChild(this.textElement); div.appendChild(this.textElement);
div.style.justifyContent = "center"; div.style.justifyContent = "center";
@ -7300,46 +7299,53 @@ var doric_web = (function (exports, axios, sandbox) {
configSize() { configSize() {
if (this.maxLines > 0) { if (this.maxLines > 0) {
const computedStyle = window.getComputedStyle(this.view); const computedStyle = window.getComputedStyle(this.view);
const currentContentHeight = this.view.clientHeight - pixelString2Number(computedStyle.paddingTop) - pixelString2Number(computedStyle.paddingBottom); const lineHeight = this.lineHeight(computedStyle);
let maxHeight = Math.ceil(parseFloat(computedStyle.getPropertyValue('font-size')) * this.lineHeight() * this.maxLines); let allowedMaxLines = this.maxLines;
if (currentContentHeight > 0) { const contentHeight = this.view.clientHeight - pixelString2Number(computedStyle.paddingTop) - pixelString2Number(computedStyle.paddingBottom);
maxHeight = Math.min(maxHeight, Math.ceil(currentContentHeight)); if (contentHeight > 0) {
const contentAllowedLines = Math.floor(contentHeight / lineHeight);
allowedMaxLines = Math.min(this.maxLines, contentAllowedLines);
} }
if (this.computedHeight(computedStyle) > maxHeight) { const originalLines = Math.floor(this.originalHeight(computedStyle) / lineHeight);
this.textElement.innerText = this.truncationText(computedStyle, maxHeight); if (originalLines > allowedMaxLines) {
this.textElement.innerText = this.truncationText(computedStyle, lineHeight, allowedMaxLines);
} }
} }
} }
lineHeight() { lineHeight(style) {
return 1.3; const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
ctx.font = style.font;
const pureText = this.textElement.innerText.replace(/\n/g, '');
const metrics = ctx.measureText(pureText);
return metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent;
} }
computedHeight(style) { originalHeight(style) {
const tempEle = document.createElement('div'); const tempEle = document.createElement('div');
tempEle.style.font = style.font; tempEle.style.font = style.font;
tempEle.textContent = this.textElement.innerText; tempEle.textContent = this.textElement.innerText;
tempEle.style.whiteSpace = 'normal'; tempEle.style.whiteSpace = style.whiteSpace;
this.view.style.overflow = 'hidden'; this.view.style.overflow = style.overflow;
tempEle.style.lineHeight = `${this.lineHeight()}em`; tempEle.style.width = style.width;
tempEle.style.width = this.view.style.width;
document.body.appendChild(tempEle); document.body.appendChild(tempEle);
const height = tempEle.offsetHeight; const height = tempEle.offsetHeight;
document.body.removeChild(tempEle); document.body.removeChild(tempEle);
return height; return height;
} }
truncationText(style, maxHeight) { truncationText(style, lineHeight, maxLines) {
const originalText = this.textElement.innerText; const originalText = this.textElement.innerText;
let start = 0, end = originalText.length; let start = 0, end = originalText.length;
const tempEle = document.createElement('div'); const tempEle = document.createElement('div');
tempEle.style.font = style.font; tempEle.style.font = style.font;
tempEle.style.whiteSpace = 'normal'; tempEle.style.whiteSpace = style.whiteSpace;
this.view.style.overflow = 'hidden'; this.view.style.overflow = style.overflow;
tempEle.style.lineHeight = `${this.lineHeight()}em`; tempEle.style.width = style.width;
tempEle.style.width = this.view.style.width;
document.body.appendChild(tempEle); document.body.appendChild(tempEle);
while (start <= end) { while (start <= end) {
const mid = Math.floor((start + end) / 2); const mid = Math.floor((start + end) / 2);
tempEle.textContent = originalText.slice(0, mid) + '...'; tempEle.textContent = originalText.slice(0, mid) + '...';
if (tempEle.offsetHeight > maxHeight) { const lines = Math.floor(tempEle.offsetHeight / lineHeight);
if (lines > maxLines) {
end = mid - 1; end = mid - 1;
} }
else { else {

File diff suppressed because one or more lines are too long

View File

@ -8,7 +8,6 @@ export class DoricTextNode extends DoricViewNode {
const div = document.createElement('div') const div = document.createElement('div')
div.style.display = "flex" div.style.display = "flex"
div.style.overflow = "hidden" div.style.overflow = "hidden"
div.style.lineHeight = `${this.lineHeight()}em`
this.textElement = document.createElement('span') this.textElement = document.createElement('span')
div.appendChild(this.textElement) div.appendChild(this.textElement)
div.style.justifyContent = "center" div.style.justifyContent = "center"
@ -100,30 +99,39 @@ export class DoricTextNode extends DoricViewNode {
configSize() { configSize() {
if (this.maxLines > 0) { if (this.maxLines > 0) {
const computedStyle = window.getComputedStyle(this.view) const computedStyle = window.getComputedStyle(this.view)
const currentContentHeight = this.view.clientHeight - pixelString2Number(computedStyle.paddingTop) - pixelString2Number(computedStyle.paddingBottom) const lineHeight = this.lineHeight(computedStyle)
let maxHeight = Math.ceil(parseFloat(computedStyle.getPropertyValue('font-size')) * this.lineHeight() * this.maxLines) let allowedMaxLines = this.maxLines
if (currentContentHeight > 0) {
maxHeight = Math.min(maxHeight, Math.ceil(currentContentHeight)) const contentHeight = this.view.clientHeight - pixelString2Number(computedStyle.paddingTop) - pixelString2Number(computedStyle.paddingBottom)
if (contentHeight > 0) {
const contentAllowedLines = Math.floor(contentHeight / lineHeight)
allowedMaxLines = Math.min(this.maxLines, contentAllowedLines)
} }
if (this.computedHeight(computedStyle) > maxHeight) {
this.textElement.innerText = this.truncationText(computedStyle, maxHeight) const originalLines = Math.floor(this.originalHeight(computedStyle) / lineHeight)
if (originalLines > allowedMaxLines) {
this.textElement.innerText = this.truncationText(computedStyle, lineHeight, allowedMaxLines)
} }
} }
} }
lineHeight() { lineHeight(style: CSSStyleDeclaration) {
return 1.3 const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
ctx!.font = style.font
const pureText = this.textElement.innerText.replace(/\n/g, '')
const metrics = ctx!.measureText(pureText)
return metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent
} }
computedHeight(style:CSSStyleDeclaration) { originalHeight(style:CSSStyleDeclaration) {
const tempEle = document.createElement('div') const tempEle = document.createElement('div')
tempEle.style.font = style.font tempEle.style.font = style.font
tempEle.textContent = this.textElement.innerText tempEle.textContent = this.textElement.innerText
tempEle.style.whiteSpace = 'normal' tempEle.style.whiteSpace = style.whiteSpace
this.view.style.overflow = 'hidden' this.view.style.overflow = style.overflow
tempEle.style.lineHeight = `${this.lineHeight()}em` tempEle.style.width = style.width
tempEle.style.width = this.view.style.width
document.body.appendChild(tempEle) document.body.appendChild(tempEle)
const height = tempEle.offsetHeight const height = tempEle.offsetHeight
@ -131,22 +139,22 @@ export class DoricTextNode extends DoricViewNode {
return height return height
} }
truncationText(style:CSSStyleDeclaration, maxHeight:number) { truncationText(style:CSSStyleDeclaration, lineHeight:number, maxLines:number) {
const originalText = this.textElement.innerText const originalText = this.textElement.innerText
let start = 0, end = originalText.length let start = 0, end = originalText.length
const tempEle = document.createElement('div') const tempEle = document.createElement('div')
tempEle.style.font = style.font tempEle.style.font = style.font
tempEle.style.whiteSpace = 'normal' tempEle.style.whiteSpace = style.whiteSpace
this.view.style.overflow = 'hidden' this.view.style.overflow = style.overflow
tempEle.style.lineHeight = `${this.lineHeight()}em` tempEle.style.width = style.width
tempEle.style.width = this.view.style.width
document.body.appendChild(tempEle); document.body.appendChild(tempEle);
while(start <= end) { while(start <= end) {
const mid = Math.floor((start + end) / 2) const mid = Math.floor((start + end) / 2)
tempEle.textContent = originalText.slice(0,mid) + '...' tempEle.textContent = originalText.slice(0,mid) + '...'
if (tempEle.offsetHeight > maxHeight) { const lines = Math.floor(tempEle.offsetHeight / lineHeight)
if (lines > maxLines) {
end = mid - 1 end = mid - 1
} else { } else {
start = mid + 1 start = mid + 1