• contenteditable格式化html文本转svg


    一、问题描述

    我们知道,在一个div里加上contenteditable="true"之后,它就变成了一个可编辑的框,而且是能满足基本需求的富文本编辑框。例如下面的文字:

     

    它的源HTML如下所示:

    <div contenteditable="true">这是<font size="1">第一font>行。<div>This is the <u>secondu> line.div><div>这是<font color="#ff0000">第四font><b>行。b>div><div><b>Thisb> is the <font face="微软雅黑">fourthfont> line.div>div>
    如果要将上述HTML转成svg文本,而且看起来跟HTML效果一模一样,有两个难点需要解决:
    1. 理清HTML源代码的结构。

    2. 处理换行的问题。例如This is the second line.这行文字,在HTML里是自动换行了,但SVG没有自动换行的功能,必须计算出原文本在哪个地方换行。

    二、样式解析

    本文的讲述中,文本所使用的样式包括:水平对齐、垂直对齐、字体、字体大小、字体颜色、加粗和下划线。

    其中,水平对齐和垂直对齐只能对整个文本进行设置,而其他样式可以对部分文本进行设置。

    2.1 水平对齐

    水平对齐设置的属性是比较简单的,就是text-align,可以赋值left、center和right。

    2.2 垂直对齐

    垂直对齐不能通过简单的CSS属性解决,因为文本高度是未知的,随着用户输入而变化,需要通过JS控制。通过getBoundingClientRect方法获取文本实际高度。以绝对定位为例,有以下伪代码:

    顶部对齐时,top=文本框.y
    居中对齐时,top=(文本框.height-文本.height)/2
    底部对齐时,top=文本框.height-文本.height

    2.3 字体

    字体、字体颜色、字体大小,在HTML里使用把文字包住,字体对应face属性,字体颜色对应color属性,字体大小对应size属性。需要注意的是,size属性只有7个值,也就是1-7,其跟实际的像素对应关系是:

    size值对应像素值
    110px
    212px
    316px
    418px
    524px
    632px
    748px

    文字粗体使用包住文字,文字下划线使用包住文字。

    三、SVG文字特性

    在SVG里面,文字跟HTML有相似的地方,也有特别之处。在此列出几点特别之处:

    1. SVG的文字使用包住,如果需要分行或者分成几段,在里面使用

    2. SVG的文字不会自动换行,设定的宽度也不会。

    3. SVG文字在垂直对齐上,有多种对齐基线,默认对应于HTML的是alphabetic基线。

    4. SVG文字颜色使用fill属性,而不是color。其他样式跟CSS一致。

    5. 一个tspan接着一个tspan,如果没有重新设定x、y,它们是横向连在一起的。

    6. 调节换行,需要计算tspan的y值。

    7. 单倍的行高接近字体大小的1.3倍。

    四、转换算法

    4.1 HTML文本分行

    HTML文本是一个树状结构,使用深度优先算法遍历所有结点。算法思想大致如下:

    1. 从根DIV结点开始遍历。

    2. 用一个数组存储每一行的结点。

    3. 如果是#text结点,添加到数组中。

    4. 如果是DIV结点,则一行完成,再新建一行。

    5. 如果是BR结点,结束上一行,添加新的一行,只有BR结点这个元素,再新建一行。

    为了后续构建文本字体样式,可以在结点中同时保存文本的格式。例如默认fontColor是#000000,fontWeight是normal,当遇到font color=#ff0000结点时,fontColor修改为#ff0000。当再遇到b结点时,fontWeight修改为bold。

    4.2 处理自动换行问题

    上文中已经说过,HTML里的文本是会自动换行的,但SVG里的文本不会。那么,原来在HTML里的一行,可能在SVG里需要变成多行。

    算法的思想是:一个字一个字的选取,获取选择部分的位置,当选择部分的y值比第一个字的y值大(而且超过了某个阈值),则从这个字符开始换行了。

    具体来说,使用document.createRange()创建一个选择区域,使用range.setStart和range.setEnd进行单字符选择。使用range.getBoundingClientRect()获取选择区域的位置。

    4.3 组建SVG文本

    完成了上面的工作之后,这一步相对就比较简单了。生成的步骤如下:

    1. 在text里面,为每一行新建一个tspan。

    2. 一行里面也会有很多格式,每种格式都新建一个tspan。

    3. 根据遍历时记录的字体样式,设置tspan里的style。

    4. 根据单字符选择时记录的y值,设置tspan的y值。

    经过上面的步骤,就可以生成跟HTML所见一模一样的SVG文本了。本文的源代码:格式化html文本转svg文本源代码-Typescript文档类资源-CSDN文库

  • 相关阅读:
    docker使用
    金仓数据库KingbaseES GIN 索引
    【PowerShell】PowerShell 7.1 之后版本的安装
    加权自动机:在 Semirings 上建模
    计算机毕业设计springboot+vue基本微信小程序的汽车俱乐部系统
    【Linux】Linux中安装Redis(详细步骤)
    Spring Boot的魔法:构建高性能Java应用
    MinIO使用
    --端口--
    k8s集群中ETCD备份和恢复
  • 原文地址:https://blog.csdn.net/lweiyue/article/details/126040007