资讯专栏INFORMATION COLUMN

怎样实现完美两端对齐/齐头尾功能——hyphenjs

DevYK / 2463人阅读

摘要:在日常工作需求中,设计师丢给你一个,发现里面的文本是两端对齐的,然后发现实际开发中,两端对齐这种操作根本是不行的,它会拉开单词空格的距离,十分难看。那么怎么解决呢控制字间距啊祭出这个神器听说报纸排版也是微调字间距实现豆腐块式的排版的。

因为之前代码写得太乱了。最近在重写,忘了开分支。有兴趣查看之前代码的朋友可以重置回c8034eb这个commit之前的代码看。重写完成后会重写一篇文章,抱歉啦。

前言

话不多说,先上图。后者红框里是浏览器默认的文本排版,右侧会有锯齿(至于难不难看就见仁见智啦哈哈)。前者是使用自己开发的hyphenjs后的文本排版,整齐得像一块豆腐块!对于一个处女座来说,简直舒心了很多。去看看这个神奇的hyphenjs

应用场景

不会无缘无故的造轮子。在日常工作需求中,设计师丢给你一个PSD,发现里面的文本是两端对齐的,然后发现实际开发中,两端对齐text-align:justify;这种操作根本是不行的,它会拉开单词空格的距离,十分难看。PSD里之所以好看,是因为设计师里进行了字号或者断行的微调。当然大家都知道,在实际开发中根本行不通的。作为一个还蛮有追求的前端开发,在社区里找不到满意的工具库后,果断开始自己动手,创造幸福。

技术分析

简单来说,开发hyphenjs中(hyphenjs只考虑西文,也就是英文、印尼文等),遇到的三个难点:

断行的时机,哪个字符适合断行?

在每行的末位适不适合加连接符-呢?

如何让其每行长度一致,排版精致风骚呢?

第一点,本来就是为了实现两端对齐,所以,每行的长度要接近文本盒子的宽度才能达到目的。问题来了,盒子的宽度轻轻松松的可以获取:(getComputedStyle(target))["width"],那么行长度如何控制呢?请看以下代码:

    var span = document.createElement("span"), width = 0;
    span.style.fontSize = 18;
    span.innerText = "R";
    target.appendChild(span);
    width= (span.getBoundingClientRect())["width"];

通过这个方法的思想,也就获取了每个字符的真实宽度,需要注意的几个方面,fontSize需要从文本盒子获知,这里只是假设一个字号而已。同时,span只有插入到文本盒子(或者说DOM树)中,才能真正生效,去获取它的所有真实的属性(同时也会继承父级的相关样式,比如font-family等我们关心的属性)。
因此,最后我们可以获取文本盒子里的所有出现过的字符的宽度,把它们的charCode和宽度用hashMap记录下来,方便复用。

怎样计算每行的累积宽度呢?请看下面的函数:

// 计算n到m字符间的累计宽度
function getAccWidth(textData, charArray, from, to) {
    return charArray.slice(from, to).reduce(function(acc, cur) {
        if (!cur) return acc + 0;
        return acc + textData[PREFIX + cur.charCodeAt()].width;
    }, 0);
}

上面计算到的hashMap终于派上用场了,逐个访问文本里的每个字符的charCode,通过hashMap(也就是函数的形参textData)得到了该字符的宽度,累积算出从n到m的总宽度,和盒子宽度作为比较,若盒子宽度介于当前字符与当前的下一个字符各自的累积宽度,即应当为适合断行的时机。举个栗子,比如第一行,那么from为0, to假如到第21个字符,诶哟刚好大于盒子宽度咯,那么20~21就是刚好适合断行的时机。

那么第一个问题得到解决!紧接着来~虽然粗糙的断行了,怎样精致风骚断行?断行适不适合加连接符?我特意去谷歌搜了几张英语报纸观摩了一下,发现几个特点:

单词如果被腰斩了,那么要加!但是最多从第二个字符开始~

特殊字符如"":;,.?()[]{}<>~!@#$%^&*-+=/|1234567890不需要加,为虾米?看着不舒服啊~

逗号句号等标点符号不会呆在每行的开头。

那么在断行的时机里加上以上的判断,就可以实现风骚断行了!

然鹅问题来了,当我风骚地把成品发给公司的前辈看的时候,前辈轻轻的飘来一句,还是没有对齐啊···内心受到了暴击,的确,因为之前的三个条件导致断行发生了一些小小的飘移,所以的确也不能完好对齐了。那么怎么解决呢?控制字间距啊!祭出letter-spacing这个神器!(听说报纸排版也是微调字间距实现豆腐块式的排版的)。
公式也很轻而易举就想出来了:合理字间距 = (盒子宽度 - 行宽度)/ 该行字符数
将字间距应用到每一行的行内样式即可。Duang!完成啦哈哈哈~~

最后稍微提几点有趣的地方和注意的地方:

空格的宽度怎么获取?直接添加到DOM里是被忽略的,哭···这个纠结了一段时间,后来发现x x减掉xx就可以了

多次对同一个文本应用hyphenjs怎么办?这个一开始没考虑到,后来将文本保存到全局对象中window.hyphen_cached,需要使用的时候随时提取~

hyphenjs目前只应用于纯文本~比如说

hyphenjs is absolutely helpful.

里面的strong标签就会忽略,因为hyphenjs获取的是innerText~

这是我第一次写博客,然后自己也是刚毕业两个月的小白,写得不好的地方还请大家多多见谅~当然最重要的是,如果这个hyphenjs对你的工作产生了帮助,还请不吝给个star哦,或者发现了什么问题,也可以提个issue哦~

有个前辈和我说,“凡事都要遵循朴素的实用主义嘛”,感触很深,开发出的任何东西基本上都需要实用,这样才能应用到实际开发中,才能对自己的工作和成长带来帮助。画风一转,嘿嘿嘿···狠狠戳这里hyphenjs

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/84932.html

相关文章

  • 怎样实现完美两端对齐/齐头功能——hyphenjs

    摘要:在日常工作需求中,设计师丢给你一个,发现里面的文本是两端对齐的,然后发现实际开发中,两端对齐这种操作根本是不行的,它会拉开单词空格的距离,十分难看。那么怎么解决呢控制字间距啊祭出这个神器听说报纸排版也是微调字间距实现豆腐块式的排版的。 因为之前代码写得太乱了。最近在重写,忘了开分支。有兴趣查看之前代码的朋友可以重置回c8034eb这个commit之前的代码看。重写完成后会重写一篇文章,...

    blastz 评论0 收藏0
  • 怎样实现完美两端对齐/齐头功能——hyphenjs

    摘要:在日常工作需求中,设计师丢给你一个,发现里面的文本是两端对齐的,然后发现实际开发中,两端对齐这种操作根本是不行的,它会拉开单词空格的距离,十分难看。那么怎么解决呢控制字间距啊祭出这个神器听说报纸排版也是微调字间距实现豆腐块式的排版的。 因为之前代码写得太乱了。最近在重写,忘了开分支。有兴趣查看之前代码的朋友可以重置回c8034eb这个commit之前的代码看。重写完成后会重写一篇文章,...

    wangtdgoodluck 评论0 收藏0
  • 手机端单行文字两端对齐:用css伪类实现

    摘要:今天在做项目的时候碰到这个问题右侧红线内的小标题单行两端对齐。两端对齐的属性我们知道是,但是这个属性有它的局限性只能为或多行文字才能实现两端对齐。也就是说,在现在的情况下,小标题的单行文字仅仅使用是实现不了两端对齐的。 今天在做项目的时候碰到这个问题:右侧红线内的小标题单行两端对齐。 showImg(https://segmentfault.com/img/bVQv1a?w=319&h...

    JasonZhang 评论0 收藏0
  • 如何解决text-align: justify;浏览器、安卓手机不兼容问题

    摘要:下载安装的浏览器等也没有问题。但是用安卓手机再带的浏览器,问题就出现了。经过查询找到一个问题。于是给每个文字之间添加了一个空格,成功解决了各浏览器不兼容手机端不兼容的问题。 今天需要切一个响应式网页,有一行文字,需要实现两端对齐。 代码如下: .h_text{ text-align: justify; width: 200px; } 这一行要两端对齐 根据经验找到t...

    Bamboy 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<