zoukankan      html  css  js  c++  java
  • SVG坐标系统

    一、SVG的世界、视野(viewBox)、视窗(viewPort)

      1、基本概念

    • SVG的世界是无限大的。
    • SVG的视野viewBox是观察世界的矩形区域

      

      2、控制方法

    • 使用<svg>标签的width,height 属性用来控制视窗。
    • 使用<svg>其他代码用来定义svg世界
    • 使用<svg>的viewBox,preserveAspectRatio属性来控制视野。
    • <svg xmlns="http://www.w3.org/2000/svg" version="1.1"
          width="800" height="500"
          viewBox="0 0 400 300"
          preservAspectRatio="xMidYMid meet">
              <!--SVG Content-->
      </svg>

      3、viewBox演示

    • viewBox写法:
      viewBox="x y width height"
    • preserveAspectRatio包含两个值:第一个值为viewBox和viewPort的对齐方式,第二个值为维持高宽比的方式:
      preservAspectRatio="align meetOrSlice"

      align又由两个值组合而成:

      x和y值自由组合即可。

    • 上面每种组合都会有不同的效果,不必死记硬背,为了方便理解,这里给出一个演示代码:
       1 <!DOCTYPE html>
       2 <html>
       3     <head>
       4         <title>ViewBox Show</title>
       5         <style>
       6             body {
       7                 background: #eee;
       8             }
       9             svg {
      10                 position: absolute;
      11                 border: 1px solid green;
      12                 width: 300px;
      13                 height: 200px;
      14                 left: 50%;
      15                 top: 50%;
      16                 margin-top: -100px;
      17                 margin-left: -150px;
      18                 background: white;
      19             }
      20             input[type=number] {
      21                 width: 50px;
      22             }
      23         </style>
      24     </head
      25 <body>
      26     <h1>ViewBox Show</h1>
      27         <form id="form">
      28             <!--fieldset控件-->
      29             <fieldset>
      30                 <legend>viewBox</legend>
      31                 <label>x: <input id="vx" type="number" value="0"></label>
      32                 <label>y: <input id="vy" type="number" value="0"></label>
      33                 <label> <input id="vw" type="number" value="300"></label>
      34                 <label>height: <input id="vh" type="number" value="200"></label>
      35             </fieldset>
      36             <fieldset>
      37                 <legend>preserveAspectRatio</legend>
      38                 <label>align: <select id="align">
      39                     <option value="none">none</option>
      40                     <option value="xMinYMin">xMinYMin</option>
      41                     <option value="xMidYMin">xMidYMin</option>
      42                     <option value="xMaxYMin">xMaxYMin</option>
      43                     <option value="xMinYMid">xMinYMid</option>
      44                     <option value="xMidYMid" selected>xMidYMid</option>
      45                     <option value="xMaxYMid">xMaxYMid</option>
      46                     <option value="xMinYMax">xMinYMax</option>
      47                     <option value="xMidYMax">xMidYMax</option>
      48                     <option value="xMaxYMax">xMaxYMax</option>
      49                 </select></label>
      50                 <label>meetOrSlice: <select id="meetOrSlice">
      51                     <option value="meet">meet</option>
      52                     <option value="slice">slice</option>
      53                     <option value="none">none</option>
      54                 </select></label>
      55             </fieldset>
      56         </form>
      57     <p>
      58         <svg id="svg" xmlns="http://www.w3.org/2000/svg">
      59             <!--face-->
      60             <circle cx="100" cy="100" r="90" style="fill: #f8dc0ee6;" />
      61             <!--eyes-->
      62             <ellipse style="fill: white;stroke: #b4b40180;stroke-5;" cy="50" rx="40" cx="55" ry="7" />
      63             <ellipse style="fill: white;stroke: #b4b40180;stroke-5;" cy="50" rx="40" cx="140" ry="7" />
      64             <circle fill="black" cx="30" cy="50" r="6" />
      65             <circle cx="125" fill="black" cy="50" r="6" />
      66             <ellipse style="fill: #f2863880;" cy="70" rx="30" cx="40" ry="7" />
      67             <ellipse style="fill: #f2863880;" cy="70" cx="160" rx="25" ry="7" />
      68             <!--smile-->
      69             <path fill="none" stroke="black" d="M 25 110 A 80 85 0 0 0 175 110" stroke-width="5"></path>
      70             <rect id="viewBoxIndicator" stroke="red" stroke-width="3.5" fill="none" />
      71         </svg>
      72     </p>
      73     <script>
      74         function update() {
      75             var viewBox =  [vx.value, vy.value, vw.value, vh.value].join(' ');
      76             var preserveAspectRatio = [align.value, meetOrSlice.value].join(' ');
      77             svg.setAttribute('viewBox', viewBox);
      78             svg.setAttribute('preserveAspectRatio', preserveAspectRatio);
      79 
      80             var rect = viewBoxIndicator;
      81             rect.setAttribute('x', vx.value);
      82             rect.setAttribute('y', vy.value);
      83             rect.setAttribute('width', vw.value);
      84             rect.setAttribute('height', vh.value);
      85         }
      86         form.addEventListener('input', update);
      87         update();
      88     </script>
      89 </body>
      90 </html>

      调整相应的属性值即可查看变化效果:

    二、SVG坐标系统概述

      我们常见的笛卡尔直角坐标系如下,这是我们经常在数学上使用的直角坐标系:

      

      而在浏览器中,我们这样来使用坐标系:很明显,SVG世界的坐标系中Y轴的正方向是向下的。

      

    三、四种坐标系

      1、用户坐标系(User Coordinate)

      即SVG标签的坐标系。

       

      2、自身坐标系(Current Coordinate)

       即SVG标签中各个标签自身的坐标系,是与生俱来的。

      

      3、前驱坐标系(Previous Coordinate)

      父容器的坐标系,图形进行坐标变换都是基于前驱坐标系的。

       

      看一个自身坐标系和前驱坐标系的例子:

      

      其中,OA、OB、OC、OD四个坐标系分别是标签svg、g、rect、rect的自身坐标系。而OA又是OB的前驱坐标系,OB又是OC和OD的前驱坐标系。

      4、参考坐标系(Reference Coordinate)

       

      5、总结

       

    四、坐标变换

      1、坐标变换

      在SVG中,坐标变换是对一个坐标变化到到另一个坐标的描述。这些变换都是在平面中的,所以我们使用线性变换来满足变换需求,在SVG中使用transform属性来实现具体的变换操作。一般包括平移、旋转、缩放等变换。

      2、线性变换

      线性变换原理:

       

      线性变换之平移:

      

      线性变换之旋转:

      

      线性变换之缩放:

      

      线性变换之变换列表:

      

      3、transform属性

       

    • 平移使用translate()方法
    • 旋转使用rotate()方法
    • 缩放使用scale()方法
    • matrix()方法:所有上面的变形可以表达为一个2*3的变形矩阵。组合一些变形,可以直接用matrix(a, b, c, d, e, f)变形设置结果矩阵,利用下面的矩阵,它把来自上一个坐标系统的坐标映射到新的坐标系统:
    • 下面是transfrom属性的演示代码:可以属于t x y,r d ,s x y ,m a b c d e f来进行演示:
    • <!DOCTYPE html>
      <html>
      <head>
          <meta charset="utf-8">
          <title>Transform演示</title>
          <style type="text/css">
              svg{
                  background:#fcfcfc;
                  display: block;
                  margin:20px auto;
                  border:1px solid #ccc;
              }
              #transform{
                  width:300px;
              }
          </style>
      </head>
      <body>
          <!--控件-->
          <fieldset>
              <legend>设置</legend>
              <label>分组:
                  <select id="group">
                      <option value="a">a</option>
                      <option value="b">└b</option>
                      <option value="c">&nbsp;&nbsp;&nbsp;└c</option>
                      <option value="d">└d</option>
                  </select>
              </label>
              <label>变换:
                  <input id="tc" type="text">
                  <!--提示信息-->
                  <span id="ts"></span>
              </label>
          </fieldset>
          <svg xmlns="http://www.w3.org/2000/svg" width="1000" height="600" viewBox="-200.5 -100.5 1000 600">
              <!--预定义:SVG的<defs>元素用于预定义一个元素使其能够在SVG图像中重复使用。-->
              <defs>
                  <g id="coord">
                      <line x1="0" y1="0" x2="300" y2="0"></line>
                      <line x1="0" y1="0" x2="0" y2="300"></line>
                      <circle cx="0" cy="0" r=2></circle>
                      <circle cx=100"0" cy="0" r=2></circle>
                      <circle cx="200" cy="0" r=2></circle>
                      <circle cx="0" cy="100" r=2></circle>
                      <circle cx="0" cy="200" r=2></circle>
                  </g>
              </defs>
              <!--引用:要显示defs中的内容需要使用<use>元素来引入它们。-->
              <use xlink:href="#coord" stroke="black" fill="black" />
              <text fill="black" x="5" y="20">World</text>
      
              <g id="a" stroke="red" fill="red">
                  <use xlink:href="#coord"/>
                  <text fill="black" x="5" y="20">a</text>
                  <g id="b" stroke="blue" fill="blue">
                      <use xlink:href="#coord"/>
                      <text fill="black" x="5" y="20">b</text>
                      <g id="c" stroke="green" fill="green">
                          <use xlink:href="#coord"/>
                          <text fill="black" x="5" y="20">c</text>
                      </g>
                  </g>
                  <g id="d" stroke="pink" fill="pink">
                      <use xlink:href="#coord"/>
                      <text fill="black" x="5" y="20">d</text>
                  </g>
              </g>
          </svg>
      </body>
          <script type="text/javascript">
              //获得目标
              function target(){
                  return document.getElementById(group.value);//group是id=group的select
              }
              //把变换命令转换为变换字符串
              //‘t 10 10 r 30 s 0.7’ => ‘transform(10,10) rotate(30) scale(0.7)’
              function tc2ts(tc){
                   var arr = (tc || '').split(' ');
                   var ts = '';
                   var elem,lastElemType;
                   var cmd = {
                       't':'translate(',
                       'r':'rotate(',
                       's':'scale(',
                       'm':'matrix(',
                   };
                   //shfit()方法用于删除并返回数组的第一个元素
                  while(elem = arr.shift()){
                      if(cmd[elem]){
                          //判断是否是最后一个元素
                          if(lastElemType == 'number') ts += ')';
                          ts += cmd[elem];
                          lastElemType = 'command';
                      }else{
                          if(lastElemType == 'number') ts += ', ';
                          ts += elem;
                          lastElemType = 'number';
                      }
                  }
                  if(ts.length) ts += ')';
                  return ts;             
              }
      
              //oninput事件:当用户进行表单输入时触发
              group.oninput = function(){
                  //tc.value = target().tc || '';
                  ts.innerHTML = tc2ts(tc.value);
              };
      
              tc.oninput = function(){
                  //target().tc = tc.value;
                  target().setAttribute('transform',ts.innerHTML = tc2ts(tc.value));
              };
          </script>
      </html>

       

  • 相关阅读:
    分布式文件存储服务器之Minio对象存储技术参考指南
    httpClient4请求工具类实现
    xmake v2.5.9 发布,改进 C++20 模块,并支持 Nim, Keil MDK 和 Unity Build
    聊一聊Jmeter多用户token使用问题
    聊一聊Jmeter用IF控制器处理接口依赖
    SONiC架构分析
    SpringBoot
    微搭低代码能力月报:全新控制台/编辑器、集成企业微信、应用构建提速等
    微搭低代码已集成企业微信
    云开发CloudBase | 基本配置&用户邮箱登录开发
  • 原文地址:https://www.cnblogs.com/fzz9/p/9144696.html
Copyright © 2011-2022 走看看