vue3溢出文本tooltip或title展示解决方案—如何获取文本宽度
vue3溢出文本tooltip或title展示解决方案—如何获取文本宽度
Author:zhoulujun Date:2023-03-06 Hits:5
解决文本溢出,鼠标悬浮展示tooltips,要解决2大难题。第一个是解决文本宽度的问题。毕竟 若果text-overflow: ellipsis生效,那么其父容
解决文本溢出,鼠标悬浮展示tooltips,要解决2大难题。
第一个是解决文本宽度的问题。毕竟 若果 text-overflow: ellipsis生效,那么其父容器就是文本,是无法直接获取宽度的。比如span元素是无法直接获取clienWidth。
第二个,就是文本编辑更改搞,需要重新计算。
文本宽度获取总结:
网上总结的足够多,比如:
面试官:你是如何获取文本宽度的? https://juejin.cn/post/7091990279565082655
通过canvas方法计算任意字符串所占的实际宽度 https://blog.csdn.net/qiao_qiao_happy/article/details/115560550
这个总结大体如下:
直接按照当前字体大小 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
vue3溢出文本tooltip或title展示解决方案—如何获取文本宽度的更多相关文章
- JS中通过id或者class获取文本内容
一.JS通过id获取文本内容 二.JS通过class获取文本内容
- 【NLP】Python NLTK获取文本语料和词汇资源
Python NLTK 获取文本语料和词汇资源 作者:白宁超 2016年11月7日13:15:24 摘要:NLTK是由宾夕法尼亚大学计算机和信息科学使用python语言实现的一种自然语言工具包,其收集 ...
- js/jquery获取文本框的值与改变文本框的值
我们就用它来学习获取文本框的值及改变文本框的值. 代码如下 复制代码 <script>function get1(){ document.getElementById("txtb ...
- jquery设置文本框值 与获取文本框的值
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...
- python开发_tkinter_获取文本框内容_给文本框添加键盘输入事件
在之前的blog中有提到python的tkinter中的菜单操作 python开发_tkinter_窗口控件_自己制作的Python IDEL_博主推荐 python开发_tkinter_窗口控件_自 ...
- DOM节点中获取文本易混淆的属性
DOM 节点中对于获取文本易混淆的属性,innerText, innerHTML, outerHTML, textContent, nodeValue. 一个实例: <!DOCTYPE html ...
- JavaWeb后台从input表单获取文本值的两种方式
JavaWeb后台从input表单获取文本值的两种方式 #### index.html <!DOCTYPE html> <html lang="en"> & ...
- 每天一个JavaScript实例-展示设置和获取CSS样式设置
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...
- 获取元素节点的子节点 & 获取文本节点
1. 获取元素节点的子节点(**只有元素节点才有子节点): ①. childNodes 属性获取全部的子节点, 但该方法不实用. 因为如果要获取指定的节点 ...
- jquery获取文本框的内容
使用jquery获取文本框的内容有以下几种: 1.根据ID取值(id属性): // javascript <script type="text/javascript"> ...
随机推荐
- GIT协作流程规范
分支模型 集中式的分支模型 目前团队使用的模式属于老旧的集中式分支模型,简单的总结就是: 开发时: 团队的所有成员都在dev分支上开发(也支持少部分的特性分支feature-xxx). 测试时: 当功 ...
- HTML5学习内容-3
(一)行高 line-height,一行文字的高度 例子 <!DOCTYPE html> <html lang="en"> <head> < ...
- logback java动态配置【动态修改日志级别,动态修改appender】(转)
logback 动态配置 写在前面在做java日志之前,强烈建议大家读一下这篇java日志的前世今生,对理清java日志框架很有帮助!1奉上地址: 一个著名的日志系统是怎么设计出来的 然后说一下,为啥 ...
- 使用 TortoiseGit 在两个项目之间共享代码(cherry-pick)
需求:项目 A 需要新增项目 B 的部分代码,要求不变更 commit message 信息 做法 项目 A 新增上游 Remote,Remote URL 为 项目 B 的 URL 新增方式:依次点击 ...
- Ubuntu环境下C++使用onnxruntime和Opencv进行YOLOv8模型部署
目录 环境配置 系统环境 项目文件路径 文件环境 config.txt CMakeLists.txt type.names 读取config.txt配置文件 修改图片尺寸格式 读取缺陷标志文件 生成缺 ...
- RocketMQ一直打印RocketmqRemoting closeChannel: close the connection to remote address[] result: true
交代一下背景: RocketMQ服务端搭建在ECS上面(问题就出在这里) SpringBoot应用根据官网Demo(参考:https://github.com/apache/rocketmq-spri ...
- java中父类方法return this.对象还是变量,子类去调用this.这个方法的问题
这个问题很简单 public class this_test01 { public static void main(String[] args) { zi j=new zi(); j.pri(); ...
- Helm Chart 部署 Redis 的完美指南
目录 一.Helm介绍 二.安装Helm 三.配置Helm的repository 四.部署chart(以部署redis为例) 1. 搜索chart 2. 拉取chart 3. 修改values.yam ...
- 用JS实现简单的屏幕录像机
本文将介绍如何用JS实现简单的屏幕录像机. 一.录制准备 创建一个按钮 <button id="recording-toggle">Start recording< ...
- pinia持久化存储插件-pinia-plugin-persistedstate
pinia-plugin-persistedstate 丰富的功能可以使 Pinia Store 的持久化更易配置: 与 vuex-persistedstate 相似的 API 所有 Store 均可 ...