o'Reill的SVG精髓(第二版)学习笔记——第九章

第九章:文本

9.1

字符:在XML文档中,字符是指带有一个数字值的一个或多个字节,数字只与Unicode标准对应。

符号:符号(glyph)是指字符的视觉呈现。每个字符都可以用很多不同的符号来呈现。

一个符号可能由多个字符构成。一些字体为特定的字母组合准备了单独的符号,以使他们更好看,这种特性叫做(连字)。有时候,一个字符也可能由几个符合组合而成。

字体:字体是指代表某个字符集合的一组读好。

一套字体中的所有符号一般都有以下特性:

基线、上坡线、下坡线:字体中所有符号以基线对齐。

大写字母高度、x高度:大写字母高度是指基线上的大写字母的高度;x高度是指基线到小写字母x顶部的高度。x高度通常能比em高度更好地衡量一个字母的尺寸和可读性。

 

9.2 <text>元素的基本属性

使用<text>元素最简单的情况是只给定x和y属性的值,用来指定元素内容的第一个字符的基线位置。默认样式是黑色填充、没有轮廓。

<!-- 文本的位置和轮廓 -->
    <svg width="400px" height="400px" viewBox="0 0 400 400">
        <!-- 参考线 -->
        <path d="M 20 10, 20 120 M 10 30 100 30 M 10 70 100 70 M 10 110 100 110" style="stroke: gray;" />

        <text x="20" y="30">Simplest Text</text>
        <text x="20" y="70" style="stroke: black;">Outlined/filled</text>
        <text x="20" y="110" style="stroke:black;stroke-width:0.5;fill:none;">Outlined only</text>
    </svg>

效果图:

还要很多可以应用到文本上的属性和css标准中是一样的。以下使用大部分(不是所有)阅读器。

①font-family:值为由空格分隔的一系列字体名称或者通用字体名称。这些字体并不会全部生效,而是会按顺序依次回退,即SVG阅读器会按从前往后的顺序使用它识别出的第一个字体。通用字体必须放在最后。SVG阅读器被要求必须能识别出通用字体名称,并且拥有可用字体。通用字体包括serif、sans-serif、monospace、fantasy、cursive。

②font-size:如果有多行文本的话,font-size的值为相邻的两条基线的距离。如果指定了单位,比如style=“font-size:12pt”,则在渲染钱字体大小会被转换为用户坐标,所以它可能会受变换和SVG viewbox影响。如果你使用相对单位(em、ex或者百分比),这些单位会相对于继承的字体大小进行计算。

③font-weight:最常用的两个值为bold和normal,当需要将一堆设置了style=”font-wright:bold“的文本中的一部分变为非粗体时,就需要设置值为normal

④font-style:最常用的两个值为italic(斜体)和normal。

⑤text-decoration:可能的值为none、underline(下划线)、overline(上划线)、line-through(删除线)

⑥word-spacing:该属性的值为一个长度,可以显式带上单位(如pt),也可以使用用户坐标。正值将增大单词之间的间距,normal将保持正常间距,负值会减小单词之间的间距。指定的值将与正常间距相加。

⑦letter-spacing:该属性的值为一个偿付,可以显式带上单位(如pt),也可以使用用户坐标。正值将增大字母之间的间距,normal将保持正常间距,负值将会减小字母之间的间距。指定的值将与正常间距相加。

<!-- 文本样式 -->
    <svg width="400px" height="400px" viewBox="0 0 400 400">
        <g style="font-size:18pt">
            <text x="20" y="20" style="font-weight: bold;">bold</text>
            <text x="120" y="20" style="font-style: italic;">italic</text>
            <text x="20" y="60" style="text-decoration: underline;">under</text>
            <text x="120" y="60" style="text-decoration: overline;">over</text>
        </g>
    </svg>

效果图:

 

9.3文本对齐

<text>指定了起始点,但是并不能事先知道它的终点。这使得让文本居中对齐或者右对齐很困难。我们可以用text-anchor属性来指定文本坐标生效的位置,它的值可以是start、middle或者end。如果文字是从左向右书写的,这三个值分别表示左对齐、居中对齐和右对齐。如果文字的书写方向不是从左向右,则会有不同的效果。

text-anchor的使用:http://oreillymedia.github.io/svg-essentials-examples/ch09/text_alignment.html

<!-- text-anchor的使用 -->
    <svg width="400px" height="400px" viewBox="0 0 400 400">
        <g style="font-size:14pt">
            <path d="M 100 10 100 100" style="stroke:gray;fill:none;" />
            <text x="100" y="30" style="text-anchor: start">Start</text>
            <text x="100" y="60" style="text-anchor: middle">Middle</text>
            <text x="100" y="90" style="text-anchor: end">End</text>
        </g>
    </svg>

效果图:

9.4 <tspan>元素

无法提前预知文本元素的长度带来的另一个问题是,很难为一个字符串应用不同的文本属性,比如一个句子中穿插着斜体、正常字体和粗体、如果只使用<text>元素,则需要反复试验以确定将这些不同格式的字符串放在什么位置。为了解决这个问题,SVG提供了<tspan>元素,与(X)HTML中的<span>元素类似,<tspan>元素可以嵌套在文本内容中,并可以改变其中文本的样式,<tspan>元素知道文本的位置。

<!-- 使用<tspan>改变文本样式 -->
    <svg width="400px" height="400px" viewBox="0 0 400 400">
        <text x="10" y="30" style="font-size:12pt;">
            Switch among
            <tspan style="font-style:italic">
                italic
            </tspan>,normal,and<tspan style="font-weight:bold">bold</tspan>text.
        </text>
    </svg>

效果图:

<tspan>上可以应用一些属性来改变某个字母或者某些字母的位置。比如上标和夏标样式,可以使用dy属性来改变字母的偏移量。这个属性值会被加到当前字符的垂直位置上,并持续生效。即使在<tspan>元素关闭后依然有效。这个属性值允许设置负值。另一个相似的是dx,会改变字母在水平方向上的偏移量。

<!-- 用dy改变文本的垂直位置 -->
    <svg width="400px" height="400px" viewBox="0 0 400 400">
        <text x="10" y="30" style="font-size:12pt;">
            F
            <tspan dy="4">a</tspan>
            <tspan dy="8">l</tspan>
            <tspan dy="12">l</tspan>
        </text>
    </svg>

如果想要使用绝对位置来设定偏移量,而不是相对元素本身的偏移量来设置,要使用x和y属性。在处理多行文本时使用这两个属性很方便。

SVG不会处理换行符,不会自动断行,所以需要手动为每一行设置x属性值,并使用y或者dy来垂直定位。应该始终在<text>元素中使用<tspan>,以便将相关联的行进行分组,这样不仅可以将他们作为一个单位一起选中,也会使文档更加结构化。

<!-- 用<tspan>进行绝对定位 -->
    <svg width="400px" height="400px" viewBox="0 0 400 400">
        <text x="10" y="30" style="font-size:12pt;">
            they dined on mince,and slices of quince,
            <tspan x="20" y="50">which they ate with a runcible spoon;</tspan>
            <tspan x="10" y="70">and hand in hand,on the edge of the sand,</tspan>
            <tspan x="20" dy="20">they danced by the light of the moon</tspan>
        </text>
    </svg>

也可以使用rotate属性对<tspan>中的单个字母或者一些字母进行旋转,它的值是以度为单位的角度值。

如果需要一次修改多个字母的位置,可以为x、y、dx、dy和rotate属性一次设置一系列的值。你指定的值将会按顺序一个一个的应用到<tspan>中的字母上

<!-- 在<tspan>中为dx、dy、rotate设置多个值 -->
    <svg width="400px" height="400px" viewBox="0 0 400 400">
        <text x="30" y="30" style="font-size:14px;">it's
            <tspan dx="0 4 -3 5 -4 6" dy="0 -3 7 3 -2 -8" rotate="5 10 -5 -20 0 15">shaken</tspan>,not stirred.
        </text>
    </svg>

尽管可以使用dy属性来产生上标和下标,但使用baselin-shift属性会更简单。这个属性的值可以为sub和super,也可以指定一个长度值,如0.5em。或者相对字体尺寸进行计算的百分比。baseline-shift的影响范围仅限于它所在的<tspan>元素。

<!-- baseline-shift的使用 -->
    <svg width="400px" height="400px" viewBox="0 0 400 400">
        <text x="20" y="25" style="font-size:14pt;">
            C<tspan style="baseline-shift:sub;">12</tspan>
            H<tspan style="baseline-shift:sub;">22</tspan>
            O<tspan style="baseline-shift:sub;">11</tspan>(suger)
        </text>
        <text x="20" y="70" style="font-size:12pt;">
            6.02 x 10<tspan baseline-shift="super">23</tspan>
            (Avogadro's number)
        </text>
    </svg>

我们无法知道一段文本的结束位置,但是可以用textLength属性显式的设置文本的长度。SVG会将文本调整到指定的长度,在调整的时候,可以只调整字符之间的间距,保持字符本身大小不变,也可以同时调整字符的间距和字符本身的大小。

调整字符的间距:设置lengthAdjust的属性值为spacing(默认值)

同时调整字符间距和字符本身的大小,设置lengthAdjust的属性值为spacingAndGlyphs。

textLength和lengthAdjust的使用:http://oreillymedia.github.io/svg-essentials-examples/ch09/text_length.html

<!-- textLength和lengthAdjust的使用 -->
    <svg width="400px" height="400px" viewBox="0 0 400 400">
        <g style="font-size:14pt;">
            <path d="M 20 10 20 70 M 220 70" style="stroke:gray;" />
            <text x="20" y="30" textLength="200" lengthAdjust="spacing">Two words</text>
            <text x="20" y="60" textLength="200" lengthAdjust="spacingAndGlyphs">Two words</text>
            <text x="20" y="90">Two words<tspan style="font-size:10pt;">(normal length)</tspan></text>
            <path d="M 20 100 20 170 M 100 100 100 170" style="stroke:gray;" />
            <text x="20" y="120" textLength="80" lengthAdjust="spacing">Two words</text>
            <text x="20" y="160" textLength="80" lengthAdjust="spacingAndGlyphs">Two words</text>
        </g>
    </svg>

9.6纵向文本

实现文本沿着垂直坐标轴排列的效果,一种方法是使用变换(transform)将文本旋转90°。另一种方法是将writing-mode属性值设置tb(top to bottom ,从上到下)

有时候,也会希望文本垂直排列时字母本身仍然是横向显示。

下例通过将glyph-orientation-vertical属性值设置为0实现这样的效果(默认值为90,即将纵向排列的文本旋转90°)

<!-- 纵向文本 -->
    <svg width="400px" height="400px" viewBox="0 0 400 400">
        <text x="10" y="20" transform="rotate(90,10,20)">Rotated 90</text>
        <text x="50" y="20" style="writing-mode:tb;">Writing mode tb</text>
        <text x="90" y="20" style="writing-mode:tb;glyph-orientation-vertical: 0;">Vertical zero</text>
    </svg>

最后一列并没有文本垂直排列字母仍然横向显示==。

9.7国际化和文本

SVG对Unicode的支持和在一个文档中显示各种语言的能力,能让你免去为每门语言创建一个文档的麻烦。

9.7.1Unicode和双向语言。

XML是基于Unicode标准的。这使得文本可以以阅读器软件支持的任何语言来显示。重设文本的方向,将direction属性设置为rtl,表示从右到左。将direction设置ltr,表示从左到右(left to tight),你还需要将unicode-bidi属性值设置为bidi-override,来显示重设底层的Unicode双向文本算法。

<!-- 使用Unicode的国际化文本 -->
    <svg width="400px" height="400px" viewBox="0 0 400 400">
        <text x="10" y="130">this is <tspan style="direction: rtl;unicode-bidi:bidi-override;font-weight:bold;">right-to-left</tspan>writing</text>
    </svg>

9.7.2<switch>元素

在统一文本中显示多种语言。

SVG通过<switch>元素提供了这种能力。这个元素会搜索所有的子节点,直到发现systemLanguage属性值与用户正在使用的软件的语言设置相符的节点。systemLanguage属性的值是一个语言名称或者使用都好分隔的语言名称列表。语言名称要么是两个字母的语言代码,比如ru代表俄语,要么是语言代码加上国家代码,用于指定某个亚种语言,比如fr-CA代表加拿大法语,而fr-CH代表瑞士法语。

一旦找到匹配的子节点,则这个节点所有的子节点都会被显示出来。<switch>元素其他的子节点则会被忽略。

9.7.3使用自定义字体

SVG字体目前不被IE浏览器支持(包括IE11),也不被Firefox浏览器支持(版本30)。在这些浏览器中,你可以再包含一个<font-face-src>元素,指定一个不同格式的字体URL。或者你可以使用只有一个name属性的<font-face-name>元素,来指定系统字体。这些元素与等价的CSS font-face属性有相同的写法。

如果你指定的字体全部不能使用。浏览器会尝试在系统字体中寻找一个能够显示文本中使用字符的字体。

9.8文本路径

文本并不一定要沿垂直或者水平的直线排列。它可以沿任何抽象路径排列,只需要简单地将文本放在<textPath>元素中,然后使用xlink:href属性引用一个之前已经定义好的<path>元素,字母会被旋转到与曲线垂直的方向“站立”(即基线是曲线的切线)。沿光滑连续曲线排列的文本比沿含有锐角或者不连续的路径排列的文本更易读。

在<textPath>元素中指定<path>并不会自动将路径显示出来。下例中,<path>在<defs>中定义,他们通常不会被显示出来,实例中使用了<use>元素来显示这些线。

textPath示例:http://oreillymedia.github.io/svg-essemtials-examples/ch09/text_path.html

<!-- textPath示例 -->
         <svg width="400px" height="400px" viewBox="0 0 400 400">
             <defs>
                 <path id="curvepath" d="M30 40 C 50 10,70 10 ,120 40 S 150 0 ,200 40" style="stroke: gray;fill:none;" />
                 <path id="round-corner" d="M250 30 L 300 30 A 30 30 0 0 1 330 60 L 330 110" style="stroke: gray;fill:none;" />
                 <path id="sharp-corner" d="M 30 110 100 110 100 160" style="stroke: gray;fill:none;" />
                 <path id="discontinuous" d="M 150 110 A 40 30 0 1 0 230 110 M 250 110 270 140" style="stroke: gray;fill:none;" />
             </defs>
             <g style="font-family: 'Liberation Sans';font-size:10pt;">
                 <use xlink:hred="#curvepath" />
                 <text>
                     <textPath xlink:href="#curvepath">
                         Following a cubic Bezier curve.
                     </textPath>
                 </text>

                 <use xlink:href="#round-corner" />
                 <text>
                     <textPath xlink:href="#round-corner">
                         Going 'round the bend'
                     </textPath>
                 </text>

                 <use xlink:href="#sharp-corner" />
                 <text>
                     <textPath xlink:href="#sharp-corner">
                     Making a quick turn
                     </textPath>
                 </text>

                 <use xlink:href="#discontinuous" />
                 <text>
                     <textPath xlink:href="#discontinuous">
                         Text along a broken path
                     </textPath>
                 </text>
             </g>
         </svg>

可以通过设置startOffset属性(百分比或长度)来调整文本在路径上开始的位置。比如startOffset=“25%”表示文本起始位置在路径的四分之一处,startOffset=“30”表示文本起始位置在路径开始30个用户单位后。如果你希望文本相对路径居中,只需要在<text>元素上设置textanchor=“middle”并在<textPath>元素上设置startOffset=“50%”即可。超出路径结尾处的文本会被截断,只会显示左边的部分。

http://oreillymedia.github.io/svg-essentials-examples/ch09/start_offset.html

<!-- 文本的长度和起始位置 -->
         <svg width="400px" height="400px" viewBox="0 0 400 400">
             <defs>
                 <path id="short-corner" transform="translate(40,40)" d="M0 0 L 30 0 A 30 30 0 0 1 60 30 L 60 60" style="stroke: gray;fill:none;" />
                 <path id="long-corner" transform="translate(140 40)" d="M0 0 L 50 0 A 30 30 0 0 1 80 30 L 80 80" style="stroke: gray;fill:none;" />
             </defs>

             <g style="font-family: 'Liberation Sans';font-size:12pt;">
                 <use xlink:href="#short-corner" />
                 <text>
                     <textPath xlink:href="#short-corner">
                         this text is too long for the path
                     </textPath>
                 </text>

                 <use xlink:href="#long-corner"/>
                 <text style="text-anchor:middle;">
                     <textPath xlink:href="#long-corner" startOffset="50%">
                         centered
                     </textPath>
                 </text>
             </g>
         </svg>

9.9 空白和文本

你可以通过改变xml:space属性的值来改变SVG处理文本中空白字符(空格、制表符、换行符)的方式,如果指定值为default(默认值),则SVG会按如下规则处理空白字符。

①删除所有换行符

②将所有制表符转换为空格。

③删除首尾空格

④将任意数量的连续空格换位一个空格。

如果使用\t表示制表符,\n表示换行符,下划线便是空格,则下面的字符串:

\n\n___abc_\t\t_def_\n\n__ghi

会渲染成:abc_def_ghi

xml:space的另一个值为preserve,使用该值时,SVG只会简单地将所有换行符和制表符换位空格(保留首尾空格)然后显示出来。同样的文本:

\n\n___abc_\t\t_def_\n\n__ghi

会渲染成:____abc____def___ghi

SVG对空白字符的处理与HTML不完全一样。SVG的默认处理方式会去掉所有的换行符,而HTML会将文本内容的换行符转换为空格,SVG的preserve值将所有换行符转换为空格,而HTML的<pre>元素并不这么处理。

在SVG1.0中无法产生新行,这使得人们感到困惑,但是SVG毕竟是面向图像显示的,而不是像HTML那样面向文本内容

9.10案例:为图形添加文本

<svg width="400px" height="400px" viewBox="0 0 400 400">
             <defs>
                 <font-face font-family="bakbatn">
                     <font-face-src>
                         <font-face-url xlink:href="kfont.svg#kfont-defn">
                             <font-face-format string="svg" />
                         </font-face-url>
                     </font-face-src>
                 </font-face>

                 <path id="upper-curve" d="M -8 154 A 162 130 0 1 1 316 154" />
                 <path id="lower-curve" d="M -21 154 A 175 140 0 1 0 329 154" />
             </defs>

             <ellipse cx="154" cy="154" rx="150" ry="120" style="fill:#999;" />
             <ellipse cx="152" cy="152" rx="150" ry="120" style="fill:#cceeff;" />

             <!-- 浅红色大半圆填充符号的上半部分,其下方“浸入”符号左下方的浅红色小半圆 -->
             <path d="M 302 152 A 150 120, 0 ,1 ,0 ,2 152 A 75 60 ,0,1,0,152 152" style="fill:#ffcccc;" />
             <!-- 浅蓝色小半圆,填充符号右上方 -->
             <path d="M 152 152 A 75 60,0,1,1,302 152" style="fill:#cceeff;" />

             <text font-family="bakbatn,serif" style="font-size:24pt;text-anchor:middle;">
                 <textPath xlink:href="#upper-curve" startOffset="50%">
                     buzhidoshisha
                 </textPath>
            </text>
            <text style="font-size:14pt;text-anchor:middle;">
                <textPath xlink:href="#lower-curve" startOffset="50%">
                    Seoul - Republic of Korea
                </textPath>
            </text>
         </svg>

 

posted @ 2017-12-05 16:15  风雨飘飘飘啊飘  阅读(335)  评论(0编辑  收藏  举报