• JS如何判断文字是否溢出(被ellipsis)?


    如果想要文本超出宽度后用省略号省略,只需要加上以下的css就行了。

    1. .ellipsis {
    2. overflow: hidden;
    3. text-overflow: ellipsis;
    4. white-space: nowrap;
    5. }

    3行css搞定,但是问题来了:如果我们想要当文本被省略的时候,也就是当文本超出指定的宽度后,鼠标悬浮在文本上面才展示popper,应该怎么实现呢?

    CSS帮我们搞定了省略,但是JS并不知道文本什么时候被省略了,所以我们得通过JS来计算。接下来,我将介绍几种方法来实现JS计算省略。

    createRange


    我发现Element-plus表格组件已经实现了这个功能,所以就先来学习一下它的源码。

    源码地址:https://github.com/element-plus/element-plus/blob/dev/packages/components/table/src/table-body/events-helper.ts

    1. // 仅仅粘贴相关的
    2. const cellChild = (event.target as HTMLElement).querySelector('.cell')
    3. const range = document.createRange()
    4. range.setStart(cellChild, 0)
    5. range.setEnd(cellChild, cellChild.childNodes.length)
    6. let rangeWidth = range.getBoundingClientRect().width
    7. let rangeHeight = range.getBoundingClientRect().height
    8. /** detail: https://github.com/element-plus/element-plus/issues/10790
    9. * What went wrong?
    10. * UI > Browser > Zoom, In Blink/WebKit, getBoundingClientRect() sometimes returns inexact values, probably due to lost
    11. precision during internal calculations. In the example above:
    12. * - Expected: 188
    13. * - Actual: 188.00000762939453
    14. */
    15. const offsetWidth = rangeWidth - Math.floor(rangeWidth)
    16. if (offsetWidth < 0.001) {
    17. rangeWidth = Math.floor(rangeWidth)
    18. }
    19. const offsetHeight = rangeHeight - Math.floor(rangeHeight)
    20. if (offsetHeight < 0.001) {
    21. rangeHeight = Math.floor(rangeHeight)
    22. }
    23. const { top, left, right, bottom } = getPadding(cellChild) // 见下方
    24. const horizontalPadding = left + right
    25. const verticalPadding = top + bottom
    26. if (
    27. rangeWidth + horizontalPadding > cellChild.offsetWidth ||
    28. rangeHeight + verticalPadding > cellChild.offsetHeight ||
    29. cellChild.scrollWidth > cellChild.offsetWidth
    30. ) {
    31. createTablePopper(
    32. parent?.refs.tableWrapper,
    33. cell,
    34. cell.innerText || cell.textContent,
    35. nextZIndex,
    36. tooltipOptions
    37. )
    38. }

    1. // 上面代码17行中的getPadding函数
    2. const getPadding = (el: HTMLElement) => {
    3. const style = window.getComputedStyle(el, null)
    4. const paddingLeft = Number.parseInt(style.paddingLeft, 10) || 0
    5. const paddingRight = Number.parseInt(style.paddingRight, 10) || 0
    6. const paddingTop = Number.parseInt(style.paddingTop, 10) || 0
    7. const paddingBottom = Number.parseInt(style.paddingBottom, 10) || 0
    8. return {
    9. left: paddingLeft,
    10. right: paddingRight,
    11. top: paddingTop,
    12. bottom: paddingBottom,
    13. }
    14. }

    document.createRange() 是 JavaScript 中的一个方法,用于创建一个 Range 对象,表示文档中的一个范围。Range 对象通常用于选择文档中的一部分内容,然后对其进行操作。

    它可以:

    1. 设置选中文本范围:可以使用 document.createRange() 方法创建一个 Range 对象,并使用 setStart() 和 setEnd() 方法设置选中文本的起始和结束位置。
    2. 插入新元素:可以使用 document.createRange() 方法创建一个 Range 对象,并使用 insertNode() 方法将新元素插入到文档中的指定位置。
    3. 获取特定元素的位置:可以使用 document.createRange() 方法创建一个 Range 对象,并使用 getBoundingClientRect() 方法获取元素在文档中的位置和大小信息。

    这边element就是使用range对象的getBoundingClientRect获取到元素的宽高,同时因为得到的宽高值有很多位的小数,所以element-plus做了一个判断,如果小数值小于0.001就舍弃小数部分。


    接下来,就让我们进行一下复刻吧。

    文字的宽度 + 盒子的左右padding  > 盒子的offsetWidth 则存在省略号

    1. <div class="ellipsis box">
    2. Lorem ipsum dolor sit amet consectetur adipisicing elit
    3. div>
    4. <div id="result">div>
    5. <script>
    6. const box = document.querySelector(".box");
    7. const getPadding = (el) => {
    8. const style = window.getComputedStyle(el, null);
    9. const paddingLeft = Number.parseInt(style.paddingLeft, 10) || 0;
    10. const paddingRight = Number.parseInt(style.paddingRight, 10) || 0;
    11. const paddingTop = Number.parseInt(style.paddingTop, 10) || 0;
    12. const paddingBottom = Number.parseInt(style.paddingBottom, 10) || 0;
    13. return {
    14. pLeft: paddingLeft,
    15. pRight: paddingRight,
    16. pTop: paddingTop,
    17. pBottom: paddingBottom,
    18. };
    19. };
    20. box.addEventListener("animationiteration", function () {
    21. const event = new CustomEvent("resize");
    22. box.dispatchEvent(event);
    23. });
    24. const checkEllipsis = () => {
    25. const range = document.createRange();
    26. range.setStart(box, 0);
    27. range.setEnd(box, box.childNodes.length);
    28. window.getSelection().addRange(range);
    29. const rangeWidth = range.getBoundingClientRect().width; // 所有文字的宽度
    30. const rangeHeight = range.getBoundingClientRect().height; // 所有文字的高度
    31. console.log(rangeWidth, rangeHeight);
    32. const { pLeft, pRight, pTop, pBottom } = getPadding(box);
    33. console.log(pLeft, pRight, pTop, pBottom, "--");
    34. const horizontalPadding = pLeft + pRight;
    35. const verticalPadding = pTop + pBottom;
    36. if (
    37. rangeWidth + horizontalPadding > box.offsetWidth ||
    38. rangeHeight + verticalPadding > box.offsetHeight ||
    39. range.scrollWidth > box.offsetWidth
    40. ) {
    41. result.textContent = "计算结果:存在省略号";
    42. } else {
    43. result.textContent = "计算结果:容器宽度足够,没有省略号了";
    44. }
    45. };
    46. checkEllipsis();
    47. box.addEventListener("resize", checkEllipsis);
    48. script>
    49. <style>
    50. .ellipsis {
    51. overflow: hidden;
    52. text-overflow: ellipsis;
    53. white-space: nowrap;
    54. }
    55. .box {
    56. border: 1px solid gray;
    57. padding: 10px;
    58. width: 300px;
    59. resize: both;
    60. /**触发频率**/
    61. animation: resize 0.1s infinite paused forwards;
    62. }
    63. .box:active {
    64. animation-play-state: running;
    65. }
    66. @keyframes resize {
    67. to {
    68. opacity: 1;
    69. }
    70. }
    71. style>

  • 相关阅读:
    【结构设计】案例:为什么第一次安装会把220V电源输入接口装反
    初识CSS
    java基础
    ISP shading和 双线性插值代码
    73页儿童医院项目智能化设计方案2022
    Linux工具篇Vim
    列表与字典—>一维列表
    Flink kafka 数据汇不指定分区器导致的问题
    深入理解MySQL索引底层数据结构
    工具推荐 StartTool
  • 原文地址:https://blog.csdn.net/weixin_45821809/article/details/133753121