首页 > 其他分享 >vue3溢出文本tooltip或title展示解决方案—如何获取文本宽度

vue3溢出文本tooltip或title展示解决方案—如何获取文本宽度

时间:2023-03-18 17:33:47浏览次数:44  
标签:el const dom text title tooltip 宽度 文本


vue3溢出文本tooltip或title展示解决方案—如何获取文本宽度

Author:zhoulujun Date:2023-03-06 

解决文本溢出,鼠标悬浮展示tooltips,要解决2大难题。第一个是解决文本宽度的问题。毕竟 若果text-overflow: ellipsis生效,那么其父容

解决文本溢出,鼠标悬浮展示tooltips,要解决2大难题。

第一个是解决文本宽度的问题。毕竟 若果 text-overflow: ellipsis生效,那么其父容器就是文本,是无法直接获取宽度的。比如span元素是无法直接获取clienWidth。

第二个,就是文本编辑更改搞,需要重新计算。

 

 

文本宽度获取总结:

网上总结的足够多,比如:

这个总结大体如下:

直接按照当前字体大小 text.length * fontSize:

这样简单粗暴,但是仔细想下,文字、字母,标点符号,特殊字符等的出现会让计算有特别大的偏差。

隐藏元素计算

创建一个 div 标签,并添加到 body

设置标签 visibility: hidden 或者其他形式

动态修改 div 的 innerText为要计算的文本

offsetWidth、scrollWidth 获取宽度

function getActualWidthOfChars(text: string, options: CSSProperties, dom = document): number {
  const { fontSize, fontFamily } = options;
  const tempDom = document.createElement('div');
  tempDom.style.cssText = `position: absolute;left: -999em;top:-999em;z-index: -1;
    ${fontSize ? 'font-size: ;' : 'fontSize'}
    ${fontFamily  ? 'font-family' : 'fontFamily'}
  `;
  tempDom.textContent = text;
  dom.append(tempDom);
  const { clientWidth } = tempDom;
  dom.removeChild(tempDom);
  return clientWidth;
}

这个频繁创建dom也可以解决,就是缓存dom,比如全局变量或者闭包。但是这种方法在字符串中含有多个空格时,测出来的宽度会一样,当然可以通过pre  code元素避免。其实最好是转义" "呀。

canvas api TextMetrics获取

function getActualWidthOfChars(text: string, options: Record<string, any> = {}): number {
  const { size = 14, family = 'Microsoft YaHei' } = options;
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');
  ctx.font = `${size}px ${family}`;
  const metrics = ctx.measureText(text);
  const actual = Math.abs(metrics.actualBoundingBoxLeft) + Math.abs(metrics.actualBoundingBoxRight);
  return Math.max(metrics.width, actual);
}

这个相比dom操作,无需更改dom结构。

 

网上很推荐的是使用最后一种方法,但是在实际项目中,做通用化的时候,可能是 :

链接是:<a href=" style="font-size:30px;" >test</a>2222

这个TextMetrics不好弄。第二个,我们无论做成组件还是 指令,textContent 更好地获取内容文本。关于textContent,推荐《小tips: JS DOM innerText和textContent的区别 https://www.zhangxinxu.com/wordpress/2019/09/js-dom-innertext-textcontent/

再次通过 getComputedStyle() 后去当前元素的样式属性。二者结合非常好使。

当然,canvas也不是没有解决办法:

综合考量,还是使用Dom方案。

 

如何监听文本变化

首先想到的肯定是ResizeObserverSize,其次是MutationObserver

MutationObserver

看api,MutationObserver是天选之子。

MutationObserver的出现就是为了解决MutationEvent带来的问题。用来观察Node(节点)变化的。具体参看:《了解HTML5中的MutationObserver https://segmentfault.com/a/1190000012787829?utm_source=tag-newest》

https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver

const observer = new MutationObserver((mutationList, observer) => {
  for (const mutation of mutationList) {
    switch (mutation.type) {
      case 'attributes':
        console.log(`The ${mutation.attributeName} attribute was modified.`);
        break;
      case 'childList':
        console.log('A child node has been added or removed.');
        break;
    }
  }
});
const targetNode = document.getElementById('some-id');
observer.observe(targetNode, { attributes: true, childList: true, subtree: true });

这个配置太复杂,而且我们只需观测宽度变化,不需要那么多操作

ResizeObserver

https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver

const observer = new ResizeObserver((entries) => {
  console.log("Size changed");
});
const targetNode = document.getElementById('some-id');
observer.observe(targetNode);

这个用的 多,最终还是选择ResizeObserver。

 

在Vue3如何使用?

其实就是使用上面的方法封装一个组件

import {
  ObjectDirective,
} from 'vue';

import getActualWidthByCanvas from '../utils/getActualWidthByCanvas';
import getActualWidthByDom from '../utils/getActualWidthByDom';

const overflowTitle: ObjectDirective<HTMLElement> = {
  mounted(el, { value = {} }) {
    const { clientWidth } = el.parentElement;
    if (!clientWidth) {
      return;
    }
    const { content, calType = 'dom' } = value;
    const text = content || el.innerText;
    let textWidth = 0;
    if (calType === 'dom') {
      textWidth = getActualWidthByDom(el.textContent, null, el.parentElement);
    } else {
      const { fontSize, fontFamily } = getComputedStyle(el);
      textWidth = getActualWidthByCanvas(text, { fontSize, fontFamily });
    }
    if (textWidth > clientWidth) {
      el.setAttribute('title', text);
    }
  },
};

export default overflowTitle;

这里面可以跟进一步封装。

在mouted 周期里面里面

mounted(el: HTMLElement, binding: DirectiveBinding) {
  createInstance(el, binding);
}

但是,个人觉得还是直接用组件比较好。

具体查看:https://github.com/zhoulujun/textOverflowTitle

 

 


转载本站文章《vue3溢出文本tooltip或title展示解决方案—如何获取文本宽度》,
请注明出处:https://www.zhoulujun.cn/html/webfront/ECMAScript/vue3/8933.html

标签:el,const,dom,text,title,tooltip,宽度,文本
From: https://www.cnblogs.com/zhoulujun/p/17231267.html

相关文章

  • 单行和多行文本溢出隐藏,省略号代替
    /*单行文本溢出隐藏,省略号代替/width:200rpx;display:block;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;/多行文本溢出隐藏,省略号代替/......
  • 2022 年值得推荐的 Vue 库 ,富文本Tiptap
    https://blog.csdn.net/maxue20161025/article/details/127692983 https://github.com/Leecason/element-tiptap/blob/master/README_ZH.md  ---Tiptap  ......
  • 基于keras采用LSTM实现多标签文本分类
    我先抓取博客园知识库的文章标题和分类代码:#coding=utf-8importosimportsysimportrequestsfromlxmlimportetree,htmlimportlxmlimporttimeimportref......
  • 多个文本文件txt合并
    第一步首先将需要合并的txt文本文档放在同一个文件夹中,倘若合并有顺序要求,请将txt文本文档进行重命名,使文档按照顺序排列。接着对文件夹进行重命名,尽量将文件名设置......
  • p标签单行文本溢出和多行文本溢出显示省略号解决方法
    单行p{ overflow:hidden; text-overflow:ellipsis; white-space:nowrap;}多行//多行显示省略号,数字3为超出3行显示,p{ display:-webkit-box; -webkit-box......
  • 文本居中对齐
     如果仅仅是为了文本在元素内居中对齐,可以使用 text-align:center;文本居中对齐实例.center{text-align:center;border:3pxsolidgreen;https://......
  • vue3 + vue-clipboard3 复制文本到剪切板
    1.安装yarnaddvue-clipboard32.引入importuseClipboardfrom'vue-clipboard3';3.html部分<n-buttontertiarytype="primary"ref="copyBtn"@click="copyP......
  • 添加mark-整板添加地孔-调整丝印-添加文本-12
    选择好库:mark点需要在库中,封装需要相关焊盘的psm文件,文本文件,bra文件等等    整板添加地孔:增加层之间连接性,性能更好设置好栅格,执行复制命令调整位号丝印:......
  • sed文本处理工具常见用法
    sed是一个非交互式的文本处理工具,它默认不会修改源文件,它是把文件中的内容逐行copy到缓冲区,然后在缓冲区中进行处理,最后把处理的结果显示到屏幕上并清空缓冲区然后再从文......
  • uni-app webview 安卓机 title显示链接地址问题
    uni-appwebview安卓机title显示链接地址问题 操作步骤:任一外链地址,在安卓机上预期结果: 希望不显示url实际结果: 显示urlbug描述:webview头部title在安卓......