js实现文本内容过长中间显示...两端正常展示

news2024/9/29 21:31:45

实现思路

  1. 获取标题盒子的真实宽度, 我这里用的是clientWidth;
  2. 获取文本内容所占的实际宽度;
  3. 根据文字的大小计算出每个文字所占的宽度;
  4. 判断文本内容的实际宽度是否超出了标题盒子的宽度;
  5. 通过文字所占的宽度累加之和与标题盒子的宽度做对比,计算出要截取位置的索引;
  6. 同理,文本尾部的内容需要翻转一下,然后计算索引,截取完之后再翻转回来

代码

<div class="title" id="test">开头,这里是中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容中间内容,结尾。</div>

css代码: 设置文本不换行,同时设置overflow:hidden让文本溢出盒子隐藏

.title {
    width: 640px;
    height: 40px;
    line-height: 40px;
    font-size: 14px;
    color: #00b388;
    border: 1px solid #ddd;
    overflow: hidden;
    /* text-overflow: ellipsis; */
    white-space: nowrap;
    /* box-sizing: border-box; */
    padding: 0 10px;
}

javascript代码:获取标题盒子的宽度时要注意,如果在css样式代码中设置了padding, 就需要获取标题盒子的左右padding值。 通过getComputedStyle属性获取到所有的css样式属性对应的值, 由于获取的padding值都是带具体像素单位的,比如: px,可以用parseInt特殊处理一下。

判断文本内容是否超出标题盒子

 // 标题盒子dom
const dom = document.getElementById('test');

// 获取dom元素的padding值
function getPadding(el) {
    const domCss = window.getComputedStyle(el, null);
    const pl = Number.parseInt(domCss.paddingLeft, 10) || 0;
    const pr = Number.parseInt(domCss.paddingRight, 10) || 0;
    console.log('padding-left:', pl, 'padding-right:', pr);
    return {
        left: pl,
        right: pr
    }
}
// 检测dom元素的宽度,
function checkLength(dom) {
     // 创建一个 Range 对象
    const range = document.createRange();
    
    // 设置选中文本的起始和结束位置
    range.setStart(dom, 0),
    range.setEnd(dom, dom.childNodes.length);
    
    // 获取元素在文档中的位置和大小信息,这里直接获取的元素的宽度
    let rangeWidth = range.getBoundingClientRect().width;
    
    // 获取的宽度一般都会有多位小数点,判断如果小于0.001的就直接舍掉
    const offsetWidth = rangeWidth - Math.floor(rangeWidth);
    if (offsetWidth < 0.001) {
        rangeWidth = Math.floor(rangeWidth);
    }
    
    // 获取元素padding值
    const { left, right } = getPadding(dom);
    const paddingWidth = left + right;
    
    // status:文本内容是否超出标题盒子;
    // width: 标题盒子真实能够容纳文本内容的宽度
    return {
        status: paddingWidth + rangeWidth > dom.clientWidth,
        width: dom.clientWidth - paddingWidth
    };
}

通过charCodeAt返回指定位置的字符的Unicode编码, 返回的值对应ASCII码表对应的值,0-127包含了常用的英文、数字、符号等,这些都是占一个字节长度的字符,而大于127的为占两个字节长度的字符。

截取和计算文本长度

// 计算文本长度,当长度之和大于等于dom元素的宽度后,返回当前文字所在的索引,截取时会用到。
function calcTextLength(text, width) {
    let realLength = 0;
    let index = 0;
    for (let i = 0; i < text.length; i++) {
        charCode = text.charCodeAt(i);
        if (charCode >= 0 && charCode <= 128) {
            realLength += 1;
        } else {
            realLength += 2 * 14; // 14是字体大小
        }
        // 判断长度,为true时终止循环,记录索引并返回
        if (realLength >= width) {
            index = i;
            break;
        }
    }
    return index;
}

// 设置文本内容
function setTextContent(text) {
    const { status, width } = checkLength(dom);
    let str = '';
    if (status) {
        // 翻转文本
        let reverseStr = text.split('').reverse().join('');
        
        // 计算左右两边文本要截取的字符索引
        const leftTextIndex = calcTextLength(text, width);
        const rightTextIndex = calcTextLength(reverseStr, width);
        
        // 将右侧字符先截取,后翻转
        reverseStr = reverseStr.substring(0, rightTextIndex);
        reverseStr = reverseStr.split('').reverse().join('');
        
        // 字符拼接
        str = `${text.substring(0, leftTextIndex)}...${reverseStr}`;
    } else {
        str = text;
    }
    dom.innerHTML = str;
}

最终实现效果:
在这里插入图片描述

相关知识

js判断文字被溢出隐藏的几种方法

  1. 通过document.createRange和document.getBoundingClientRect()这两个方法实现的。也就是上面代码中实现的checkLength方法。
  2. 创建一个隐藏的div模拟实际宽度

通过创建一个不会在页面显示出来的dom元素,然后把文本内容设置进去,真实的文本长度与标题盒子比较宽度,判断是否被溢出隐藏了。

function getDomDivWidth(dom) {
    const elementWidth = dom.clientWidth;
    const tempElement = document.createElement('div');
    const style = window.getComputedStyle(dom, null)
    const { left, right } = getPadding(dom); // 这里我写的有点重复了,可以优化
    tempElement.style.cssText = `
        position: absolute;
        top: -9999px;
        left: -9999px;
        white-space: nowrap;
        padding-left:${style.paddingLeft};
        padding-right:${style.paddingRight};
        font-size: ${style.fontSize};
        font-family: ${style.fontFamily};
        font-weight: ${style.fontWeight};
        letter-spacing: ${style.letterSpacing};
    `;
    tempElement.textContent = dom.textContent;
    document.body.appendChild(tempElement);
    const obj = {
        status: tempElement.clientWidth + right + left > elementWidth,
        width: elementWidth - left - right
    }
    document.body.removeChild(tempElement);
    return obj;
}
  1. 创建一个block元素来包裹inline元素

外层套一个块级(block)元素,内部是一个行内(inline)元素。给外层元素设置溢出隐藏的样式属性,不对内层元素做处理,这样内层元素的宽度是不变的。因此,通过获取内层元素的宽度和外层元素的宽度作比较,就可以判断出文本是否被溢出隐藏了。

// html代码
<div class="title" id="test">
    <span class="content">近日,银行纷纷下调大额存单利率,但银行定期存款仍被疯抢。银行理财经理表示:有意向购买定期存款要尽快,不确定利率是否会再降。</span>
</div>

// 创建一个block元素来包裹inline元素
const content = document.querySelector('.content');
function getBlockDomWidth(dom) {
    const { left, right } = getPadding(dom);
    console.log(dom.clientWidth, content.clientWidth)
    const obj = { 
        status: dom.clientWidth < content.clientWidth + left + right,
        width: dom.clientWidth - left - right
    }
    return obj;
}
  1. 使用canvas中的measureText方法和TextMetrics对象来获取元素的高度

通过Canvas 2D渲染上下文(context)可以调用measureText方法,此方法会返回TextMetrics对象,该对象的width属性值就是字符占据的宽度,由此也能获取到文本的真实宽度,此方法有弊端,比如说兼容性,精确度等等。

// 获取文本长度
function getTextWidth(text, font = 14) {
    const canvas = document.createElement("canvas");
    const context = canvas.getContext("2d")
    context.font = font
    const metrics = context.measureText(text);
    return metrics.width
}

JS获取字符串长度的几种常用方法

  1. 通过charCodeAt判断字符编码

通过charCodeAt获取指定位置字符的Unicode编码,返回的值对应ASCII码表对应的值,0-127包含了常用的英文、数字、符号等,这些都是占一个字节长度的字符,而大于127的为占两个字节长度的字符。

function calcTextLength(text) {
    let realLength = 0;
    for (let i = 0; i < text.length; i++) {
        charCode = text.charCodeAt(i);
        if (charCode >= 0 && charCode <= 128) {
            realLength += 1;
        } else {
            realLength += 2;
        }
    }
    return realLength;
}
  1. 采取将双字节字符替换成"aa"的做法,取长度
function getTextWidth(text) {
    return text.replace(/[^\x00-\xff]/g,"aa").length;
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1506264.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

05 排序与分页

排序与分页 1 排序数据 1.1 排序规则 使用 ORDER BY 子句排序 ASC&#xff08;ascend&#xff09;: 升序DESC&#xff08;descend&#xff09;:降序 ORDER BY 子句在SELECT语句的结尾 1.2 单列排序 SELECT last_name, job_id, department_id, hire_date FROM empl…

蓝桥杯备战刷题-滑动窗口

今天给大家带来的是滑动窗口的类型题&#xff0c;都是十分经典的。 1&#xff0c;无重复字符的最长子串 看例三&#xff0c;我们顺便来说一下子串和子序列的含义 子串是从字符串里面抽出来的一部分&#xff0c;不可以有间隔&#xff0c;顺序也不能打乱。 子序列也是从字符串里…

数据分析-Pandas画分布密度图

数据分析-Pandas画分布密度图 数据分析和处理中&#xff0c;难免会遇到各种数据&#xff0c;那么数据呈现怎样的规律呢&#xff1f;不管金融数据&#xff0c;风控数据&#xff0c;营销数据等等&#xff0c;莫不如此。如何通过图示展示数据的规律&#xff1f; 数据表&#xff…

CAE模拟仿真工具CEETRON Envision:大数据可视化助力工业设计与协同

行业&#xff1a; 制造业; 工业设计; 汽车&#xff1b;航天 挑战&#xff1a;工业客户需要有效的方法来处理CAE数据&#xff1b;ESTECO寻求提供CAE可视化功能来帮助客户做出决策&#xff1b;许多可用的可视化工具无法提供对模型中数据的完全访问以进行深入分析 解决方案&…

Linux智能网关结合Node-RED实现实时工业数据采集

工业4.0的发展&#xff0c;物联网技术在制造业中的应用越来越广泛。其中&#xff0c;基于Linux系统的工业物联网智能网关因其开放性、稳定性和安全性而备受青睐。这类智能网关创新性地集成了开源工具Node-RED&#xff0c;为从各种工业设备&#xff08;如PLC&#xff09;中高效收…

前端学习之行内和块级标签

行内标签 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>span</title> </head> <body><!-- 行内标签特点&#xff1a;1、不换行,一行可以放多个2、默认宽度内容撑开代表&#…

Python中eval与exec的使用及区别

最近开发中用到了eval()与exec()这两个函数&#xff0c;不知道在哪种场景下用哪个函数&#xff0c;所以就翻了下Python的文档。这里就来简单说一下这两个函数的区别 1. eval函数 函数的作用&#xff1a; 计算指定表达式的值。也就是说它要执行的Python代码只能是单个运算表达…

虚拟机实验环境配置与使用(计算机系统2)

一、 实验目标&#xff1a; 熟悉Linux上C程序的编译和调试工具&#xff0c;包括以下内容&#xff1a; 1. 了解Linux操作系统及其常用命令 2. 掌握编译工具gcc的基本用法 3. 掌握使用gdb进行程序调试 二、实验环境与工件 1.个人电脑 2. Fedora 13 Linux 操作系统 3. gcc…

YOLOV5 初体验:简单猫和老鼠数据集模型训练

1、前言 前两天&#xff0c;通过OpenCV 对猫和老鼠视频的抽取&#xff0c;提取了48张图片。这里不再介绍&#xff0c;可以参考之前的文章&#xff1a;利用OpenCV 抽取视频的图片&#xff0c;并制作目标检测数据集-CSDN博客 数据的目录如下&#xff1a; 项目的下载见文末 2、制…

Storyboard动画、EventTrigger事件触发器

就是动画&#xff0c;要注意的就是EventTrigger中的SourceName就是想要实现这个功能的按钮 <StackPanel Orientation"Vertical"><Rectanglex:Name"rect"Width"200"Height"40"Fill"Pink" /><StackPanel Orie…

Vue3学习记录(六)--- 组合式API之依赖注入和异步组件

一、依赖注入 1、简介 ​ 在前面的笔记中&#xff0c;我们学习过父组件向子组件传递数据时&#xff0c;需要借助props来实现。但如果父组件想要向孙子组件传递数据&#xff0c;那就要连续使用两层props逐级向下传递&#xff0c;如果要接收数据的是更深层的后代组件&#xff0…

同一交换机下不同网段的终端通信

文章目录 一个有趣的实验 大家都知道不同网段的IP地址要想通信需要通过网关进行路由转发&#xff0c;而一般通过路由器来做默认网关。 一个有趣的实验 一台二层交换机下&#xff0c;连接两个不同网段的PC&#xff0c;实现彼此之间的通信。 一台S3700交换机&#xff0c;两台PC。…

【金三银四】Spring面试题

目录 1、什么是Spring2、说一下Spring的IOC3、Spring的AOP4、连接点&#xff1f;切入点&#xff1f;5、Spring AOP 是通过什么实现的6、Spring Bean的生命周期是怎么样的&#xff1f;7、Spring Bean的初始化过程是怎么样8、Spring的事务传播机制有哪些&#xff1f;9、Autowired…

Qt 中Json文件的操作

Json文件的读取 QFile file("data.json"); //准备好的文件file.open(QIODevice::ReadOnly|QIODevice::Text);QByteArray arr file.readAll();QJsonDocument jsonDoc QJsonDocument::fromJson(arr);QJsonObject jsonObj jsonDoc.object();qint32 id jsonObj["…

网络工程师笔记10 ( RIP / OSPF协议 )

RIP 学习路由信息的时候需要配认证 RIP规定超过15跳认定网络不可达 链路状态路由协议-OSPF 1. 产生lsa 2. 生成LSDB数据库 3. 进行spf算法&#xff0c;生成最有最短路径 4. 得出路由表

Python错题集-8:AttributeError(找不到对应的对象的属性)

1问题描述 AttributeError: AxesSubplot object has no attribute arc 2代码详情 import matplotlib.pyplot as plt# 创建一个新的图形和坐标轴 fig, ax plt.subplots()# 定义弧线的参数 center (0.5, 0.5) # 圆心坐标 (x, y) width 1.0 # 半径 height 0.5 # 半径 ang…

学习笔记。。。

1.字符串的拼接 1.sprintf() 往字符串的前面或中间、后面拼接一个字符串。 2.strncpy()用来复制字符串的前n个字符 //dest为目标数组&#xff0c;src为源数组&#xff0c;n为要复制的字符个数 2.char* My_strncpy(char* dest, const char* src, int n) 3.char *strcat(ch…

【Axure高保真原型】可视化动点素材

今天和粉丝们免费分享可视化动点素材的原型模板&#xff0c;该模板使用简单&#xff0c;复制粘贴&#xff0c;预览时即可实现动点效果&#xff0c;本案例提供红黄蓝绿4中颜色的动点&#xff0c;如果需要其他颜色&#xff0c;可以自行编辑svg里面的代码 【原型效果】 【模板下载…

Leetcode 59.螺旋矩阵Ⅱ

1.题目 2.思路 &#xff08;借用代码随想录的图&#xff09; 1.我们将转一圈看作一个循环&#xff08;1->2->3->4->5->6->7->8 这是一个循环&#xff09; 2.在这个循环里&#xff0c;我们要画四条边&#xff08;上右下左&#xff09; 填充上行从左到右 填…

[天天向上] 学习方法论-事半功倍的问题解决方法

目录 一、尝试独立解决问题1. 关于独立2. 像密室逃脱一样 二、提问的艺术1. 合适的自我介绍1.1 群名片2.2 研究方向/业务内容 2. 详细的问题描述2.1 问题描述要点2.2 描述格式2.3 问题内容描述&#xff0c;尤其是当前进展和问题 3. 如何让更多的人为你解答4. 如何结束提问更优雅…