美文网首页
浏览器JS计算字符宽高

浏览器JS计算字符宽高

作者: 爱和圣殿 | 来源:发表于2018-05-04 19:55 被阅读0次

在开发中遇到了需要获取一段文字的长度的技术性需求,这篇文章将会讲述我是如何解决这样的问题的

浏览器环境下

解决方法一: SPAN标签

我最开始的解决方法是创建一个span元素,然后innerHTML设置文本在设置好样式后插入到body中,读取宽高

function getCharSize(char, style = {}){
    let {
        fontSize = "12px",
        fontFamily = "SimSun"
    } = style

    let span = document.createElement("span")
    span.style.font = `${fontSize} ${fontSize}`
    span.style.lineHeight = fontSize
    span.innerHTML = str
    document.body.appendChild(span)
    let rect = span.getBoundingClientRect()
    let width = rect.width
    let height = rect.height
    document.body.removeChild(span)
    return {
        width,
        height
    }
}
image

问题

  1. 不同浏览器的差异

    不同浏览器获取的高度宽高有一些差别

    chrome:

    image

    firefox:

    image

    不知道为何firefox的高总是比chrome高2px,但这个我们可以通过直接获取传入的fontSize作为高,这样就可以统一了

    function getCharSize(char, style = {}){
        let {
            fontSize = 14,
            fontFamily = "SimSun"
        } = style
        /*其他操作*/
        return {
            width,
            height: fontSize
        }
    }
    
    image
  2. 浏览器对字体大小的限制

    chrome默认最小字体为12px,基本是人尽皆知的

    image

    这里可以使用scale的方式实现

    function getCharSize(char, style = {}){
        let {
            fontSize = 14,
            fontFamily = "SimSun"
        } = style
        
        /*其他操作*/
        let scale = fontSize / 20
        span.style.fontSize = `${20}px`
        span.style.transform = `scale(${scale})`
        span.style.display = "inline-block" //让scale生效
        /*其他操作*/
        return {
            width,
            height: fontSize
        }
    }
    
    image

优点

兼容几乎所有浏览器

缺点

  1. 会受一些潜在的全局样式影响

    image

解决方法二:Canvas measureText函数

除了使用span来获取浏览器表现的大小这样直接的方式以外,还有可以通过使用canvasAPI的CanvasRenderingContext2D.measureText()方式来快速获取

const ctx = document.createElement('canvas').getContext('2d')
function getCharSizeByCanvas(char, style = {}){
    let {
        fontSize = 14,
        fontFamily = "SimSun"
    } = style
    
    ctx.font = `${fontSize}px ${fontFamily}`
    let text = ctx.measureText(char)
    let result = {
        height: fontSize,
        width: text.width
    }

    return result
}

问题

  1. chrome浏览器存在BUG,如果canvas不在DOM树上设置字体大小小于12px时,字体大小会强制设置为12px

    
    //setfont before append
    const canvas1 = document.createElement('canvas')
    canvas1.width = 100
    canvas1.height = 100
    const ctx1 = canvas1.getContext('2d')
    ctx1.font = "8px Arial"
    ctx1.fillText(ctx1.font, 0, 50)
    document.body.appendChild(canvas1)
    
    //set font after append
    const canvas2 = document.createElement('canvas')
    canvas2.width = 100
    canvas2.height = 100
    const ctx2 = canvas2.getContext('2d')
    document.body.appendChild(canvas2)
    ctx2.font = "8px Arial"
    ctx2.fillText(ctx2.font, 0, 50)
    
    
    image

代码整理

下面给出优化后的代码

方法一:span

let span = document.createElement("span")
span.style.positon = "ablsolute"

function getCharSize(char, style = {}){
    let {
        fontSize = 14,
        fontFamily = "SimSun"
    } = style
    
    let scale = fontSize / 20
    span.style.fontSize = "20px"
    span.style.fontFamily = fontFamily
    span.style.lineHeight = "0"
    span.style.transform = `scale(${scale})`
    span.style.display = "inline-block"
    span.innerHTML = char
    document.body.appendChild(span)
    let rect = span.getBoundingClientRect()
    let width = rect.width
    document.body.removeChild(span)
    return {
        width,
        height: fontSize
    }
}

方法二:canvas计算

let canvas = document.createElement('canvas')
canvas.style.positon = "ablsolute"
let ctx = canvas.getContext('2d')

function getCharSizeByCanvas(char, style = {}){
    let {
        fontSize = 14,
        fontFamily = "Arial"
    } = style
    document.body.appendChild(canvas)
    ctx.font = `${fontSize}px ${fontFamily}`
    document.body.removeChild(canvas)
    let text = ctx.measureText(char) // TextMetrics object
    ctx.fillText(char, 50, 50)
    let result = {
        height: fontSize,
        width: text.width
    }
    return result
}

性能比较

数据为进行10000次单字符计算

  1. 都需要插入DOM的情况下(方法二兼容chrome,且字体都为12px以下)

    image image image

    方法二效率比方法一快: 150%左右

  2. 方法二字体都为12px以上

    image image image

    方法二效率比方法一快: 1500%左右

从效率上来讲,canvas效率是极高的,同时canvas还有还在制定的标准,可以提供更加详细的文本信息,chrome只需要去chrome://flags/开启Experimental canvas features就可以提前使用该功能

image

参考资料

CanvasRenderingContext2D.measureText()

TextMetrics

END

2018-03-31 完成

2017-12-13 立项

相关文章

  • 浏览器JS计算字符宽高

    在开发中遇到了需要获取一段文字的长度的技术性需求,这篇文章将会讲述我是如何解决这样的问题的 浏览器环境下 解决方法...

  • 获取屏幕各种宽高的方法

    js 获取屏幕各种宽高的方法(浏览器兼容) 屏幕的有效宽高: window.screen.availHeightw...

  • JS & jQuery的各种宽高

    一、JS宽高计算 参考地址:http://caibaojian.com/js-name.html 名词解释scre...

  • js 中的一些位置方法

    1 , 获取浏览器可视区的宽高 document.documentElement.cl...

  • js中查看浏览器宽度

    js中查看浏览器宽度 1 网页可见区域宽:document.body.clientWidth 2 网页可见区域高:...

  • 文本占用的高度和范围

    1.sizeWithAttributes计算宽、高 size# 这种方式计算的宽度会根据字符串的长度无限的增加 2...

  • 计算字符串的宽高

    1.如果字符串只占一行 2.如果是多行,则需要固定一个宽度比如100最早的写法 后来苹果弃用了这个sizeWith...

  • js获取浏览器宽高

    参考: js获取网页屏幕可见区域高度

  • Swift 计算文本的size

    iOS 11之前限制宽高计算字符串的size用的是UILabel的textRect(forBounds bound...

  • css+js改变滚动条

    CSS3或CSS+JS实现改变滚动条样式(兼容所有浏览器) /*定义滚动条高宽及背景 高宽分别对应横竖滚动条的尺寸...

网友评论

      本文标题:浏览器JS计算字符宽高

      本文链接:https://www.haomeiwen.com/subject/jbrjrftx.html