gpt4 book ai didi

javascript - JS、Vue : how to split text based on window height?

转载 作者:搜寻专家 更新时间:2023-10-30 22:55:18 26 4
gpt4 key购买 nike

我想在特定点拆分文本,这样您就不需要向下滚动。

这意味着我想知道文本何时变得比窗口的可用高度长。在我显示文本之前需要知道这一点。这样做的问题是我需要在渲染之前知道布局的外观,因为整个布局都应该响应宽度和高度。

我还计划稍微调整字体大小。因此,考虑到所有这些因素,你们中有人知道如何在正确的位置拆分文本吗?

提前谢谢你。

PS:文本实际上是一个数组,看起来像这样例如:

text = [{content: Hello, wordID: ..., offsetBegin: 0, offsetEnd: 5,
...},{content: World!, wordID: ..., offsetBeding: 7, offsetEnd: 12,...}]

所以我唯一需要知道的是关于在何处拆分文本的索引,这样主窗口上就没有滚动条了。拆分文本也可能发生不止一次。

整个事情将开始在 mounted() Hook 中显示和计算,并且将在每次触发 for window 的“调整大小”事件时重新计算。

最佳答案

这题好像有XY problem .您可能需要重新考虑这是否真的是您想要解决问题的方式。

但是,如果你真的想在JS中获取分界点:

文本的高度取决于多种因素,例如元素的宽度、字体大小和字重、字距调整等等。有很多变量需要考虑,您不太可能在不渲染任何东西的情况下进行计算。

相反,您应该要求浏览器呈现您的元素,然后在呈现给用户之前将其移除。这将由 forcing a reflow 完成插入文本后,测量文本的结束位置,然后在删除文本后强制进行新的重排。

棘手的部分是衡量文本应该在哪里结束。我个人会通过在每个我希望可以 chop 的位置(例如在每个单词之后)插入元素来解决这个问题,然后遍历它们以查看哪些元素溢出了容器。


下面是这个想法的普通 JS 实现。您应该能够在 Vue 中相当轻松地实现它。

const DEBUG = true;

const $textInp = document.getElementById("text-inp");
const $target = document.getElementById("target");
const $outp = document.getElementById("outp");

document.getElementById("calc-btn").addEventListener("click", () => {
const text = $textInp.value;
const data = getTextCutoff(text, $target);
$outp.textContent = JSON.stringify(data);
if (!DEBUG) { $target.textContent = text.substr(0, data.end); }
});

/**
* Returns an object of format { end: <Number> }
* Where `end` is the last index which can be displayed inside $elm without overflow
*/
function getTextCutoff(text, $elm) {
$elm.innerHTML = ""; // empty the element
const prevOverflow = $elm.style.overflow;
const prevPosition = $elm.style.position;
$elm.style.overflow = "visible";
$elm.style.position = "relative"; // to make sure offsetHeight gives relative to parent
const $indicators = [];
const $nodes = [];
// turn our text into an array of text nodes, with an indicator node after each
let currentIndex = 0;
const words = text.split(" ");
words.forEach(
(word, i) => {
if (i > 0) {
word = " "+word;
}
currentIndex += word.length;
const $wordNode = document.createTextNode(word);
$nodes.push($wordNode);
const $indicatorNode = document.createElement("span");
$indicatorNode.strIndex = currentIndex;
if (DEBUG) { $indicatorNode.classList.add("text-cutoff-indicator"); }
$indicators.push($indicatorNode);
$nodes.push($indicatorNode);
}
);

// insert our elements
$nodes.forEach($node => $elm.appendChild($node));

// then find the first indicator that is overflown
const maxHeight = $elm.offsetHeight;
let $lastIndicator = $indicators[$indicators.length - 1];
for (let i = 0; i < $indicators.length; ++i) {
const $indicator = $indicators[i];
const bottomPos = $indicator.offsetTop + $indicator.offsetHeight;
if (bottomPos > maxHeight) {
break;
} else { $lastIndicator = $indicator; }
}

if (DEBUG) {
$lastIndicator.style.borderColor = "green";
$lastIndicator.classList.add("overflown");
}

// then reset everything - this also forces reflow
if (!DEBUG) { $elm.innerHTML = ""; }
$elm.style.overflow = prevOverflow;
$elm.style.position = prevPosition;

// then return
return {
end: $lastIndicator.strIndex
};
}
#target {
height: 128px;
background: #ddd;
}

.text-cutoff-indicator {
margin-left: -2px;
border-left: 2px solid red;
}

.text-cutoff-indicator.overflown ~ .text-cutoff-indicator {
opacity: 0.5;
}
<div>
<textarea id="text-inp" placeholder="Enter text here"></textarea>
<button id="calc-btn">Apply text</button>
<pre id="outp"></pre>
</div>
<div id="target"></div>

关于javascript - JS、Vue : how to split text based on window height?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48830032/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com