之前有做过一个业务,需要在文本框输入文字的时候动态计算一行文字的宽度。并由此知道当前输入的这段文字会有几行。

如何计算?

  1. 每个文字的个数*宽度?理论上可行,但是有一个问题是不同类型的文字对应的宽度是不一样的,数字,汉字,字母乃至每个标点符号 宽度各不相同。所以实际处理起来,这个肯定会埋坑。

  2. canvas measureText api ? 理论可行,实际问题 :字体,字间距,。。。引起的其他误差。(其实这些误差也是很容易清除的,所以这些问题也就不叫问题了,我没有采用这种方法完全是因为当时没去往这个方向想)。

不卖关子了,最后我采用的方法是这样的: 首先,我们用一个pre元素(characterElement) 将其所有css属性重置为和我们要计算的文本框的属性相一致。然后把他放置到视口之外,最后结合dom方法计算出其宽度,然后除以文本框的宽度:

  1. function calcRows(texaWidth,charWidth ){
  2. return Math.ceil( charWidth / texaWidth )
  3. }

这是最初的想法,但是这里有个问题是对于换行时的误差处理,因为当当前文字不足以全部放进textarea的时候,是会换行的,而换行前和换行后之间是有空隙的,这个空隙累积之后会对后续结果的计算带来比较大的偏差影响。所以我们还需要计算出换行后上一行多出来的空间所占的元素:

  1. function calcOffset(){
  2. let texaWidth = textArea.getBoundingClientRect().width;
  3. let offset = 0;
  4. for( let i = 1, before = i-1,L = textArea.value.length; i <= L; i++ ){
  5. let str = textArea.value.slice( before, i);
  6. characterElement.innerHTML = str;
  7. let verifyWidth = characterElement.getBoundingClientRect().width;
  8. console.log(verifyWidth,texaWidth)
  9. if( verifyWidth >= texaWidth ){
  10. // 记录换行下标
  11. before = i-1;
  12. offset += ( verifyWidth - texaWidth )
  13. }
  14. }
  15. return offset;
  16. }

有了全部的文字宽度和换行带来的误差累积我们可以很容易就计算出当前这段文字到底占了几行,即:

  1. characterElement.innerHTML = textArea.value;
  2. let verifyWidth = characterElement.getBoundingClientRect().width + calcOffset();
  3. let texaWidth = textArea.getBoundingClientRect().width;
  4. let rows = Math.ceil( verifyWidth / texaWidth )

最后一步需要考虑的是,对于calcOffset函数,每一个文字输入都会产生一个巨量的运算时间,并且随着文字输入的增加,其计算量的增长会非常恐怖,因此, 我们需要一个策略去缓存我们已经计算过的文字:

  1. let cache={
  2. lastIndex:0,
  3. offset:0
  4. };
  5. function calcOffset(){
  6. let texaWidth = textArea.getBoundingClientRect().width;
  7. let before = cache.lastIndex;
  8. for( let i = before + 1,L = textArea.value.length; i <= L; i++ ){
  9. let str = textArea.value.slice( before, i);
  10. characterElement.innerHTML = str;
  11. let verifyWidth = characterElement.getBoundingClientRect().width;
  12. if( verifyWidth >= texaWidth ){
  13. // 记录换行下标
  14. cache.lastIndex = i - 1;
  15. before = i-1;
  16. cache.offset += ( verifyWidth - texaWidth )
  17. }
  18. }
  19. return cache.offset;
  20. }

OK了,这样基本不会有太大问题了,在文本框的input回调里调用这些函数就可以得到精确地行数了,当然可以debounce一下得到性能更优的版本。

后记: 以上代码源于实际项目中的一个评论框,大体样子跟下图差不多,因为涉及到自动换行并且他右边的那一部分是跟文字在同一行的 所以需要去精确地计算文字的宽度

如何用js精确计算一行文字的宽度的更多相关文章

  1. js精确计算

    官方文档:http://mikemcl.github.io/big.js/ 使用方法: x = new Big(0.1); y = x.plus(0.2); // '0.3' var a=Big(0. ...

  2. js精确计算(js浮点数精度问题)

    转自:http://talentluke.iteye.com/blog/1767138 大多数语言在处理浮点数的时候都会遇到精度问题,但是在JS里似乎特别严重,来看一个例子 alert(45.6*13 ...

  3. 实现js浮点数加、减、乘、除的精确计算(网上很多文章里的方法是不能解决所有js浮点数计算误差的)

    最近做项目,要用到js的加.减.乘.除的计算,发现js浮点数计算会有一些误差. 网上有很多文章都有js浮点数计算误差的解决方法,说能解决这个问题,But…….比如一个加法函数,如下: function ...

  4. js浮点数相加、减、乘、除精确计算

    js 浮点数计算时 ,无缘无辜 后边冒出一堆 小数点………… 貌似js本身的问题,类型不定?????? 只能自己写函数处理..  http://blog.csdn.net/w4bobo/article ...

  5. js加减乘除精确计算

    Javascript精确计算时的bug JS无法进行精确计算的bug 在做CRM,二代审核需求审核详情页面时.需要按比例(后端传类似0.8的小数)把用户输入的数字显示在不同的地方. 在做dubheIn ...

  6. js 日期计算星座 根据生日的月份和日期,一行代码计算星座的js小函数(转)

    本博客根据 开源中国作者清风徐不来 的文章 根据生日的月份和日期,一行代码计算星座的js小函数(转) 原文出自CSDN 无心的专栏 的文章,知识产权归原文作者所有! 点击查看原文:js 日期计算星座

  7. JS怎么计算html标签里文字的宽度

    方法: 做一个空的html 标签 id为“ruler”,样式为“position:absolute;visibility: hidden; white-space: nowrap;z-index: - ...

  8. css实现一行文字居中,多行文字左对齐

    问题及场景: 当内容能一行显示在盒子内时,文字居中对齐. 当内容过多换行后显示在盒子内时,文字左对齐. 其实这种视觉上的需求还是蛮常见的.比如用于弹出提示框,当提示内容比较少时,内容居中显示在弹出框, ...

  9. js浮点数计算问题 + 金额大写转换

    一 js浮点数计算问题解决方案: 1.使用 NumberObject.toFixed(num) 方法 toFixed() 方法可把 Number 四舍五入为指定小数位数的数字. 2.较精度计算浮点数 ...

  10. 关于js浮点数计算精度不准确问题的解决办法

    今天在计算商品价格的时候再次遇到js浮点数计算出现误差的问题,以前就一直碰到这个问题,都是简单的使用tofixed方法进行处理一下,这对于一个程序员来说是及其不严谨的.因此在网上收集了一些处理浮点数精 ...

随机推荐

  1. Linux 中的内存使用率计算方式

    背景介绍 在工作中处理问题的时候,遇到一个问题,自己根据 top 命令时查看到的 used 和 total 计算出来的内存使用率已经达到 90% 以上了,但是系统自带的监控软件计算出来的使用率往往没有 ...

  2. Qt/C++编写视频监控系统83-自定义悬浮条信息

    一.前言 一般视频控件上会给出个悬浮条,这个悬浮条用于显示分辨率或者一些用户期望看到的信息,一般常用的信息除了分辨率以外,还有帧率.封装格式.视频解码器名称.音频解码器名称.实时码率等,由于实际的场景 ...

  3. Qt/C++音视频开发52-采集本地屏幕桌面的终极设计

    一.前言 最开始设计的时候,只考虑了一个屏幕的情况,这种当然是最理想的情况,实际上双屏或者多屏的用户也不在少数,比如我这两个屏幕,屏幕1是1080P,屏幕2是2K分辨率,打印两个屏幕的区域是 QRec ...

  4. Qt开源作品44-超级曲线图表

    按照国际惯例,先吹吹牛,QCustomPlot这个开源图表组件,作者绝对是全宇宙Qt领域的天花板,设计的极其巧妙和精美,各种情况都考虑到了,将每个功能细分到不同的类,每个类负责管理自己的绘制和各种属性 ...

  5. elementPlus 问题总结

    第一次搞,遇上很多弱智问题,记录一下 安装elementPlus $ npm install element-plus --save 全局引入 import ElementPlus from 'ele ...

  6. python SQLAlchemy ORM——从零开始学习 02简单的增删查改

    02 简单的增删查改 前情提要:承接了01中的engine以及User类 2-1 了解会话机制 个人理解 在SQLAlchemy 增删查改中是依赖会话(Session)这个机制进行操作的,我个人的理解 ...

  7. 转载:大模型所需 GPU 内存笔记

    转载文章:大模型所需 GPU 内存笔记 引言 在运行大型模型时,不仅需要考虑计算能力,还需要关注所用内存和 GPU 的适配情况.这不仅影响 GPU 推理大型模型的能力,还决定了在训练集群中总可用的 G ...

  8. ctfshow--web3 incluede伪协议注入

    这题一看就知道是个伪协议的题 直接用data伪协议 ls 查看目录 data://text/plainy, 再cat 一下就拿到flag了

  9. uniapp-中picker-view用户不触发channge事件也知道用户选择的值

    我们都知道,只用用户触发change事件的时候,我们才知道,用户选择的是哪一个值: 如何用户没有触发change事件,我们压根就不知道用户选择的是哪一个值: 那么什么时候,用户不会触发change事件 ...

  10. HTML布局常用标签——div和span

    HTML布局常用标签--div和span 在HTML的世界里,div和span是两位不可或缺的老朋友,它们虽然看似简单,却在网页布局和样式设计中发挥着举足轻重的作用.今天,我们就来聊聊这两位" ...