SVG之文本

Easter79
• 阅读 776

一、文本标签

  SVG支持直接对文本进行操作,如果我们需要在SVG中使用文本,那么我们需要使用到****标签。直接看一个简单的demo。

  •    1 <!DOCTYPE html>
       2 <html>
       3 <head>
       4     <meta charset="utf-8">
       5     <title>textDemo</title>
       6 </head>
       7 <body>
       8     <svg id="svg" xmlns="http://www.w3.org/2000/svg" version="1.1" width="100%" height="1000">
       9         <defs>
      10             <pattern id="grid" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
      11                 <path d="M0,0H20V20" style="stroke: #0006;fill: none"></path>
      12             </pattern>
      13         </defs>
      14         <!--网格背景-->
      15         <rect fill="url(#grid)" width="1400" height="1000"></rect>
      16         <!--文字-->
      17         <text x="100" y="100" fill="green" style="font-size: 50px;font-family: 'Arial';">你好,Hello SVG</text>
      18         <path d="M100,0V200M0,100H500" stroke="red" />
      19     </svg>
      20 </body>
      21 </html>
    

    SVG之文本

     这个demo中我们使用笔刷绘制了20*20大小的格子背景,方便观察坐标。我们发现属性:fill填充文字颜色;X,Y的值是文本的起始坐标(左下角坐标)。然而,汉字明显突出了界限,而英文字母则很好地位于Y值之上。

  除了X,Y属性,text还有两个重要的属性:

  • dx属性:横向位移字符。
  • dy属性:纵向位移字符。

  我们加入dx,dy属性来直接感受一下字符之间的变化(从第一个字符起生效):

  •   <text x="100" y="100" fill="green" dx="10 20" dy="10 -10 10 -10 10 -10 10 -10 10 -10 10 -10" style="font-size: 50px;font-family: 'Arial';">你好,Hello SVG</text>
    

     一共有12个字符(包含空格),所以dx,dy应当有分别是12个数值,如果不足,默认为0。

    SVG之文本

二、标签的使用

1、小Demo

   标签我们应该都很熟悉,对于内联元素我们一般使用来处理。同样的,在SVG的标签中,我们可以使用****标签进行内联元素处理。

  的使用能更好地处理文本,特别是部分文本。比如上文的“你好,Hello SVG”,如果我们希望中文和英文的颜色不一样,那么我们可以使用将文本“分割”来处理:

  •   <text x="100" y="100">
          <tspan dx="10 10" dy="-10 20" fill="black" stroke="blue" style="font-size: 40px;">你好,</tspan>
          <tspan dx="0 0 0 0 0 0 10 -15 -15" dy="10 -10 10 -10 10 -10 10 -10 10" fill="none" stroke="green" style="font-size: 50px;font-family: 'Arial';">Hello SVG</tspan>
      </text>
    
    SVG之文本
    我们发现,dx和dy在中由于字符串长度变短会变得更好调整。

2、使用dx和dy属性:完成sin(x)文字动画

  利用dx和dy属性可以调整文本字符的横向和纵向位移距离,我们现在利用这个属性将26个字母按照**y = A·sin(ax+b)**这个函数进行排列。

  •    1 <!DOCTYPE html>
       2 <html>
       3 <head>
       4     <meta charset="utf-8">
       5     <title>textDemo</title>
       6 </head>
       7 <body>
       8     <svg id="svg" xmlns="http://www.w3.org/2000/svg" version="1.1" width="100%" height="1000">
       9         <defs>
      10             <pattern id="grid" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
      11                 <path d="M0,0H20V20" style="stroke: #0006;fill: none"></path>
      12             </pattern>
      13         </defs>
      14         <!--网格背景-->
      15         <rect fill="url(#grid)" width="1400" height="1000"></rect>
      16         <!--文字-->
      17         <text id="sinText" x="100" y="200" style="font-size: 18px;font-family: 'Arial';">ABCDEFGHIJKLMNOPQRSTUVWXYZ</text>
      18         <path d="M100,0V200M0,100H200" transform="translate(20,100)" stroke="red" />
      19     </svg>
      20     <script>
      21         //x = [20,20,20,...]
      22         //y = s*sin(w*x+t);
      23         var n = 26;
      24         var x = [];
      25         var y = null;
      26         var i = n;
      27         var s = 100;
      28         var w = 0.02;
      29         var t = 0;
      30 
      31         //横向间隔20
      32         while(i--) x.push(20);
      33         
      34         //纵向按照sin()函数变化
      35         function arrange(t){
      36             y = [];
      37             var ly = 0,cy;
      38             for(i=0;i<n;++i){
      39                 cy = -s* Math.sin(w * i * 20 +t);
      40                 y.push(cy - ly);
      41                 ly = cy;
      42             }
      43         }
      44         //将数组转换成字符串并设置为dx,dy值
      45         function render(){
      46             sinText.setAttribute('dx',x.join(' '));
      47             sinText.setAttribute('dy',y.join(' '));
      48         }
      49 
      50         //执行
      51         arrange(t);
      52         render();
      53         
      54     </script>
      55 </body>
      56 </html>
    

  SVG之文本

  • 现在我们可以动态改变设置t的值,使得这些文本动起来,我们只需要将arrange(t); render();两个方法替换为以下动态方法即可:

    //动态改变t的值
    function frame() {
        t += 0.02;
        arrange(t);
        render();
        window.requestAnimationFrame(frame);//动画效果:递归调用frame方法
    }
    frame();
    

  

  我们还可以稍加修饰,为每个字母即每个增加fill属性,依次来渲染字母的颜色,我们只需要修改while()循环部分:

  •   while(i--){
          x.push(20);
        
          var tspan = document.createElementNS(NS,'tspan');
          tspan.textContent = text[n - i - 1];
          sinText.appendChild(tspan);
          var h = Math.round(360/26 * i);//将颜色均分显示
          tspan.setAttribute('fill','hsl('+ h +',100%,50%)');
      }
    

  

三、文字的水平/垂直居中

  • 水平居中使用text-anchor属性,值包括:start、middle、end
  • 垂直居中使用dominant-baseline属性

  下面是一个演示器:

  •    1 <html>
       2     <head>
       3         <meta charset="utf-8">
       4         <title>SVG文本对齐</title>
       5     </head>
       6     <body>
       7         <br>
       8         <label>水平居中属性:text-anchor=</label>
       9         <select id="ta">
      10             <option value="start">start</option>
      11             <option value="middle">middle</option>
      12             <option value="end">end</option>
      13         </select>
      14         <span>------</span>
      15         <label>垂直居中属性:dominant-baseline=</label>
      16         <select id="select"></select>
      17         <br>
      18         <svg xmlns="http://www.w3.org/2000/svg" width="100%" height="300">
      19             <path stroke="green" d="M0,100 h400 M140,0 v200" />
      20             <text id="text" x="140" y="100" fill="red" font-size="50">SVG</text>
      21             <rect id="rect" stroke="blue" fill="none"></rect>
      22         </svg>
      23 
      24         <script>
      25         var values = "auto | use-script | no-change | reset-size | ideographic | alphabetic | hanging | mathematical | central | middle | text-after-edge | text-before-edge | text-top | text-bottom".split(' | ');
      26     
      27         values.forEach(function(value) {
      28             var opt = document.createElement('option');
      29             opt.value = opt.textContent = value;
      30             select.appendChild(opt);
      31         });
      32     
      33         select.addEventListener('input', function() {
      34             text.setAttribute('dominant-baseline', select.value);
      35             var box = text.getBBox();
      36             rect.setAttribute('x', box.x);
      37             rect.setAttribute('y', box.y);
      38             rect.setAttribute('width', box.width);
      39             rect.setAttribute('height', box.height);
      40         });
      41     
      42         ta.addEventListener('input', function() {
      43             text.setAttribute('text-anchor', ta.value);
      44         });
      45         </script>
      46     </body>
      47 </html>
    
     SVG之文本

四、控制文本路径的标签

1、小栗子

   上面我们使用dx和dy属性对26个字母实现了文本按照sin()函数排列,但这并不是真正地按照路径排列。如果想要文本按照某个路径排列,我们需要使用****标签。直接看一个简单的栗子:

  •    1 <html>
       2 <head>
       3     <meta charset="utf-8">
       4     <title>路径文本</title>
       5 </head>
       6 
       7 <body>
       8     <svg xmlns="http://www.w3.org/2000/svg" width="800" height="600">
       9         <path id="path1" d="M 100 200 Q 200 100 300 200 T 500 200" stroke="green" stroke-width="2" fill="none" />
      10         <g fill="red">
      11             <circle cx="100" cy="200" r="4" />
      12             <circle cx="300" cy="200" r="4" />
      13             <circle cx="500" cy="200" r="4" />
      14         </g>
      15         <text style="font-size: 22px;">
      16             <textpath xlink:href="#path1">投我以木瓜,报之以琼琚,匪报也,永以为好也。</textpath>
      17         </text>
      18     </svg>
      19 </body>
      20 </html>
    
    SVG之文本

  其中,我们先使用定义了一条路径,然后使用来处理文本,并设置 xlink:href 参数来控制文本路径。

2、一个演示器

  当我们使用标签控制文本路径后,的属性:x,y,dx,dy,会产生不一样的效果,下面是一个演示器,我们可以更直观的感受这种变化:

  •    1 <html>    
       2     <head>
       3         <meta charset="utf-8">
       4         <title>路径文本</title>
       5     </head>
       6     
       7     <body>
       8         <br>
       9         <form id="ctrl">
      10             <label>x:</label>
      11             <input id="x" ctrl="x" type="range" value="0" min="-200" max="200" />
      12             <label id="x_value" style="color: red">0</label>
      13             &nbsp;&nbsp;&nbsp;
      14             <label>text-anchor:</label>
      15             <select ctrl="text-anchor">
      16                 <option value="start" selected>start</option>
      17                 <option value="middle">middle</option>
      18                 <option value="end">end</option>
      19             </select>
      20             <br><br>
      21             <label>y:</label>
      22             <input id="y" ctrl="y" type="range" value="0" min="-200" max="200" />
      23             <label id="y_value" style="color: red">0</label>
      24             &nbsp;&nbsp;&nbsp;
      25 
      26             <label>startOffset:</label>
      27             <input id="startOffset" ctrl="startOffset" type="range" value="0" min="-100" max="100" />
      28             <label id="so_value" style="color: red">0</label>
      29 
      30             <br><br>
      31             <button type="reset" style="margin-left: 200px;">重置</button>
      32         </form>
      33         <svg xmlns="http://www.w3.org/2000/svg" width="800" height="600">
      34             <path id="path1" d="M 100 200 Q 200 100 300 200 T 500 200" stroke="green" fill="none" />
      35             <g fill="red">
      36                 <circle cx="100" cy="200" r="4" />
      37                 <circle cx="300" cy="200" r="4" />
      38                 <circle cx="500" cy="200" r="4" />
      39             </g>
      40             <text style="font-size: 20px;">
      41                 <textpath xlink:href="#path1">投我以木瓜,报之以琼琚,匪报也,永以为好也。</textpath>
      42             </text>
      43         </svg>
      44     </body>
      45     <script>
      46         // jshint browser: true
      47         var ctrl= document.getElementById('ctrl');
      48         var text = document.querySelector('text');
      49         var textPath = text.firstElementChild;
      50     
      51         function update(target) {
      52             var attr = target.getAttribute('ctrl');
      53             if(!attr) return;
      54             if(attr == 'startOffset') {
      55                 textPath.setAttribute(attr, target.value + '%');
      56             } else {
      57                 text.setAttribute(attr, target.value);
      58             }
      59         }
      60 
      61         function info(){
      62             var x_value = document.getElementById('x_value');
      63             var y_value = document.getElementById('y_value');
      64             var so_value = document.getElementById('so_value');
      65             x_value.innerText = x.value;
      66             y_value.innerText = y.value;
      67             so_value.innerText = startOffset.value;
      68         }
      69 
      70         ctrl.addEventListener('input', function(e){
      71             update(e.target);
      72             info();
      73         })
      74     
      75         ctrl.addEventListener('reset', function(){
      76             setTimeout(function(){
      77                 var list = document.querySelectorAll('#ctrl *[ctrl]');
      78                 [].slice.call(list).forEach(update);
      79                 info();
      80             })
      81         })
      82     </script>
      83 </html>
    

  SVG之文本

  这里面startOffset的值决定了其实文本偏移位置,和之前的text-anchor类似。上面没有将dx,dy属性添加进去,但是也会影响文本路径。

五、超链接标签的使用

  标签我们都很熟悉,嗯?在SVG中同样提供了同名的标签,可以作为任意图形的超链接。

  • xlink:href属性:规定连接URL。
  • xlink:title属性:显示连接提示信息。
  • target属性:指定在何处打开目标。可选值如下:
    SVG之文本

  下面是一个简单的实例:

  •    1 <!DOCTYPE html>
       2 <html>
       3 <head>
       4     <meta charset="utf-8">
       5     <title>SVG超连接</title>
       6 </head>
       7 <body>
       8     <svg xmlns="http://www.w3.org/2000/svg">
       9         <a xlink:href="http://www.cnblogs.com/fzz9" xlink:title="博客园_fzz" target="_blank">
      10             <rect height="30" width="100" y="0" x="0" rx="15"></rect>
      11             <text fill="white" text-anchor="middle" y="21" x="45">
      12                 <tspan id="feng" style="font-size: 30px;font-family:STXinwei;">风</tspan>
      13                 <tspan>之之</tspan>
      14             </text>
      15         </a>
      16     </svg>
      17     <script type="text/javascript">
      18         var h = 0;
      19 
      20         //动态设置字体颜色
      21         function setColor(h){
      22             var feng = document.getElementById('feng');
      23             feng.setAttribute('stroke','hsl('+ h +',100%,50%)');
      24         }
      25         function frame(){
      26             setColor(h);
      27             h += 0.8;
      28             if(h>=360) h = 0;
      29             window.requestAnimationFrame(frame);//动画效果:递归调用frame方法
      30         }
      31         frame();
      32     </script>
      33 </body>
      34 </html>
    
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Stella981 Stella981
3年前
AndroidStudio封装SDK的那些事
<divclass"markdown\_views"<!flowchart箭头图标勿删<svgxmlns"http://www.w3.org/2000/svg"style"display:none;"<pathstrokelinecap"round"d"M5,00,2.55,5z"id"raphael
Stella981 Stella981
3年前
SVG跟随父级DIV自适应
后台返回过来的是这样的SVG标签<svgwidth"100%"height"100%"version"1.1"xmlns"http://www.w3.org/2000/svg"<gtransform"translate(00)"
Easter79 Easter79
3年前
SVG跟随父级DIV自适应
后台返回过来的是这样的SVG标签<svgwidth"100%"height"100%"version"1.1"xmlns"http://www.w3.org/2000/svg"<gtransform"translate(00)"
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
SVG之文本
一、文本标签<text  SVG支持直接对文本进行操作,如果我们需要在SVG中使用文本,那么我们需要使用到<text标签。直接看一个简单的demo。1<!DOCTYPEhtml2<html3<head4<meta
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
Easter79
Easter79
Lv1
今生可爱与温柔,每一样都不能少。
文章
2.8k
粉丝
5
获赞
1.2k