关于文本溢出显示省略号

众所周知,我们可以使用-webkit-line-clamp属性来实现多行文本溢出省略号。

由于溢出的文本是不可见的,所以一般情况会对可能有溢出文本的段落添加一些显示完整段落的交互,比如鼠标移到段落上时,显示完整的文本。

<style>
  .text {
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
  }
</style>
<div
  class="text"
  title="Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus, aliquam consequatur consequuntur doloremque
  doloribus exercitationem laudantium molestias nemo non odio recusandae reiciendis repellat suscipit totam, unde vero
  voluptatem, voluptatibus voluptatum?"
>
  Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus, aliquam consequatur consequuntur doloremque
  doloribus exercitationem laudantium molestias nemo non odio recusandae reiciendis repellat suscipit totam, unde vero
  voluptatem, voluptatibus voluptatum?
</div>

虽说是简单粗暴了点,目的是实现了。这里使用的是系统默认的 tooltip 效果,如果想定制 tooltip 效果,也可以借助于 antd 的 tooltip

上面的实现有一个问题,就是无论段落内容有没有溢出,鼠标在移入时 tooltip 始终会显示,有没有办法控制在出现溢出…的时候,鼠标移入会显示 tooltip,当不存在溢出…的时候,则不显示。

理一下思路,怎么判断段落内容有没有溢出?

可以通过判断段落文本的行高 * 行数是否大于当前正在显示段落的高度,大于就说明溢出了。

行高可以通过getComputedStyle来获取,大致实现代码如下。

// 超过2行显示省略号
const rows = 2;

const wrapperRef = useRef<HTMLDivElement>(null);

useEffect(() => {
  if (wrapperRef.current) {
    const lineHeight = parseFloat(getComputedStyle(wrapperRef.current, null).lineHeight);
    if (lineHeight * rows > wrapperRef.current.clientHeight) {
      // 此时溢出了,配合antd的tooltip,主动控制tooltip的显示时机。
    }
  }
}, []);

return (
  <div className="text" ref={wrapperRef}>
    Lorem ipsum dolor sit amet, consectetur adipisicing elit. Cupiditate illo, mollitia officia provident quidem sed
    velit. Aut consequatur, corporis doloremque eveniet laborum, neque numquam officia provident quas suscipit tempore
    veniam.
  </div>
);

不过,上述实现的代码还有一个问题,它不能根据段落的实时显示宽度来控制 tooltip 的显隐藏。因为浏览器是可以拖动的,用户主动拖大或拖小浏览器窗口可能会影响到文本段落的显示宽度。由于.text段落在一开始就被设置 css 样式控制最多显示的行,所以,在之后的浏览器宽度变化时并不能够通过lineHeight * rows > wrapperRef.current.clientHeight来判断段落溢出。

经过不断尝试,我发现还可以通过scrollHeight来实现个功能。当文本出现溢出时,scrollHeight > clientHeight,反之则相等,那么上面的逻辑可以做一些调整。

const isOverflowRef = useRef(false);

const calc = useCallback(() => {
  if (wrapperRef.current) {
    isOverflowRef.current = wrapperRef.current.clientHeight < wrapperRef.current.scrollHeight;
  }
}, []);

useEffect(() => {
  calc();

  const resizeFn = debounce(calc, 100);
  window.addEventListener('resize', resizeFn, false);

  return () => {
    window.removeEventListener('resize', resizeFn, false);
  };
}, [calc]);

最终实现的效果如下,你可以尝试拖动到不同宽度下查看效果:

如果您觉得本文对您有用,欢迎捐赠或留言~
微信支付
支付宝

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注