我知道可以根据字符的长度按字符数来拆分字符串。但是,如何在不切断单词的情况下根据像素分开HTML字符串?
例如:
myString = "Lorem Ipsum has been the industry's standard dummy text ever since the 1500s";
splitThroughPixel(myString, 100) // Shall return something like ["Lorem Ipsum has", "been the industry's", "dummy text", "since the", "1500s"] (not the true splitting, just to give an idea)
splitThroughPixel(myString, 100)
应将 myString
分为 100px
max的字符串块(不切割单词(。
我该如何实现?
我已经能够使用此JavaScript方法获得字符串的完整像素长度(如果可以帮助(:
function getWidth(pText, pFontSize, pStyle) {
var lDiv = document.createElement('div');
document.body.appendChild(lDiv);
if (pStyle != null) {
lDiv.style = pStyle;
}
lDiv.style.fontSize = "" + pFontSize + "px";
lDiv.style.position = "absolute";
lDiv.style.left = -1000;
lDiv.style.top = -1000;
lDiv.innerHTML = pText;
document.body.removeChild(lDiv);
lDiv = null;
return lDiv.clientWidth;
}
例如:getWidth(myString )
返回510
(这是字符串myString
屏幕上的像素数(
感谢您抽出宝贵的时间帮助我。
首先,我对您的getWidth功能进行了一些更正,因为您返回lDiv.clientWidth
,但您以前将lDiv
设置为Null,因此会丢弃错误。因此,我将.clientWidth
存储到一个变量中,然后将其返回:
function getWidth(pText, pFontSize, pStyle) {
var lDiv = document.createElement('div');
document.body.appendChild(lDiv);
if (pStyle != null) {
lDiv.style = pStyle;
}
lDiv.style.fontSize = "" + pFontSize + "px";
lDiv.style.position = "absolute";
lDiv.style.left = -1000;
lDiv.style.top = -1000;
lDiv.innerHTML = pText;
const width = lDiv.clientWidth;
document.body.removeChild(lDiv);
lDiv = null;
return width;
}
接下来,对于您的splitThroughPixel
,您只需要循环遍历每个单词,获取像素,然后检查句子是否大于宽度。如果更大,则将上一个字符串添加到结果中。
function splitThroughPixel(string, width, size, style){
const words = string.split(' ');
const response = [];
let current = '';
for(let i=0; i<words.length; i++){
const word = words[i];
const temp = current + (current == '' ? '' : ' ') + word;
if(getWidth(temp, size, style) > width){
response.push(current.trim());
current = '';
}else{
current = temp;
}
}
return response;
}
示例
const myString = "Lorem Ipsum has been the industry's standard dummy text ever since the 1500s";
console.log(splitThroughPixel(myString, 100, 14));
示例的响应将是这样的数组:
["Lorem Ipsum has", "the industry's", "dummy text ever"]
demo
https://jsfiddle.net/chinleung/rqp1291r/2/
,而不是按照其他答案的建议,而不是创建和删除每个循环的元素,这在性能方面是不好的,您可以根据当前的width
重复使用相同的元素并添加/重置innerHTML
。
function wrapText(text, maxWidth) {
const words = text.split(' ');
var el = document.createElement('div');
document.body.appendChild(el);
el.style.position = "absolute";
let rows = [];
let row = [];
let usedIndex = 0;
// loop through each word and check if clientWidth is surpassing maxWidth
for(let i = 0; i < words.length; i++) {
const word = words[i];
el.innerHTML += word;
if (el.clientWidth > maxWidth) {
rows.push(el.innerHTML);
usedIndex = i;
el.innerHTML = "";
} else {
el.innerHTML += " ";
}
}
// handle remaining words
words.splice(0, usedIndex);
rows = rows.concat(words.join(" "));
document.body.removeChild(el);
return rows;
}
const text = "Lorem Ipsum has been the industry's standard dummy text ever since the 1500s";
console.log(wrapText(text, 100));
p {
position: relative;
}
p::before {
outline: 1px solid red;
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 100px;
content: '';
}
您可以创建一个具有white-space: nowrap
和display: inline
的临时Div并在其上添加单词,然后测试其宽度。
此解决方案将不允许子字符串超出您的像素限制,除非一个单词超出了该像素限制。
let myString = "Ipsum has been the industry's standard dummy text ever since the 1500s";
let split = splitThroughPixel(myString, 100);
console.log(split);
function splitThroughPixel(string, px) {
let words = string.split(' ');
let split = [];
let div = document.createElement('div');
div.style.cssText = 'white-space:nowrap; display:inline;';
document.body.appendChild(div);
for (let i = 0; i < words.length; i++) {
div.innerText = (div.innerText + ' ' + words[i]).trim();
let width = Math.ceil(div.getBoundingClientRect().width);
if (width > px && div.innerText.split(' ').length > 1) {
let currentWords = div.innerText.split(' ');
let lastWord = currentWords.pop();
split.push(currentWords.join(' '));
div.innerText = lastWord;
}
}
if (div.innerText !== '') {
split.push(div.innerText);
}
document.body.removeChild(div);
return split;
}