整体思路:
- 先将文本进行拆分
- 中文按照单个字符进行拆分
- 英文和数字按照单词进行拆分
- 空格直接保留
- 使用canvas文本绘制计算总的绘制宽度
( 例如绘制三行,第三行中间省略,如何盒子宽度为100px,则需要绘制的文本长度为 100*2+50=260px)
- 按照第一步拆分的词依次渲染,根据 canvas文本绘制提供的 measureText 依次拿到单词词的绘制宽度
- 宽度大于上面的文本长度时,就是省略前需要绘制的文本啦
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.text {
width: 200px;
font-size: 16px;
font-family: Arial;
height: 100px;
border: 1px solid #00aaff;
}
</style>
</head>
<body>
<input type="text" id="input">
<div class="text"></div>
<script>
const canvas = document.createElement('canvas');
document.body.appendChild(canvas);
const ctx = canvas.getContext('2d');
function splitTextByCharacter(text) {
// 使用正则表达式拆分:匹配每一个中文字符、英文字符、数字、空格
const regex = /[\u4e00-\u9fa5]|[a-zA-Z0-9]+|\s+/g;
return text.match(regex) || [];
}
document.querySelector('#input').addEventListener('input', (event) => {
const inputText = event.target.value;
const text = getCollapsedText(inputText);
console.log(text, '1', inputText)
document.querySelector('.text').innerText = text;
});
function getCollapsedText(text, width = 200, line = 2, fontSize = '16px', fontFamily = 'Arial') {
ctx.font = `${fontSize} ${fontFamily}`; // 设置字体样式
const maxWidth = width * line - (width / 2);
let renderedText = '';
let renderedWidth = 0;
const words = splitTextByCharacter(text);
for (let i = 0; i < words.length; i++) {
const metrics = ctx.measureText(words[i]); // 测量当前行的宽度
renderedWidth += metrics.width; // 当前行的宽度
if (renderedWidth < maxWidth) {
renderedText += words[i]; // 临时拼接的行
} else {
return renderedText.trim() + '...';
}
}
return renderedText;
}
</script>
</body>
</html>