在不算多功能需求中,我们会遇到需要用JS来计算字宽高的情况,比如

  • canvas根据渲染文字计算换行、块的大小等

  • IE8及以下双行并且有省略符…

  • 文字少的时候居中,文字超出的时候出省略符…

通常,我们采用建立伪节点来计算 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 参数配置的形式

function getTextSize (text, style = {}, container = document.body) {
  let dom = document.createElement('div')
  // dom.id = 'YOUR_SCOPE_measure'
  for (let attr in style) {
    dom.style[attr] = style[attr]
  }
  dom.style.opacity = 0
  dom.style.display = 'inline-block'
  dom.innerText = text
  container.appendChild(dom)
  let rst = {
   width: dom.clientWidth,
   height: dom.clientHeight
  }
  container.removeChild(dom)
  return rst
}
getTextSize('Hello Aloea', {fontSize: '18px', padding: '2px'})

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 样式名(ClassName)形式

function getTextSize (text, className, container = document.body) {
  let dom = document.createElement('div')
  // dom.id = 'YOUR_SCOPE_measure'
  dom.className = className
  dom.style.opacity = 0
  dom.style.display = 'inline-block'
  dom.innerText = text
  container.appendChild(dom)
  let rst = {
   width: dom.clientWidth,
   height: dom.clientHeight
  }
  container.removeChild(dom)
  return rst
}

getTextSize('Hello Aloea', 'CLASSNAME')

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 拷贝某节点的形式

function getTextSize (text, node) {
  if (!node) {throw {message: 'function [getTextSize] must send params [node]'}}
  let dom = node.cloneNode()
  dom.id = 'YOUR_SCOPE_measure'
  dom.style.opacity = 0
  dom.style.display = 'inline-block'
  dom.innerText = text
  node.parentNode.appendChild(dom)
  let rst = {
   width: dom.clientWidth,
   height: dom.clientHeight
  }
  node.parentNode.removeChild(dom)
  return rst
}

getTextSize('Hello Aloea', document.querySelector('#lb'))

 
 

上述的实现方式,考虑如果是大量的数据,如此频繁操作dom肯定是不好的,需要根据项目情况做进一步优化:

  • 只在初始化时算一次各种字符类型,利用 str.charCodeAt 比如数字段、标点及符号段、英文字母段、中文段等,这样遍历一遍文本就可以得到尺寸数据

(以上只是我的一种思路,实际实现预计有坑,小心使用..)

参考: Unicode代码图表