【问题标题】:how to keep text orientation unchanged during rotation in SVG如何在SVG旋转期间保持文本方向不变
【发布时间】:2014-09-25 04:40:47
【问题描述】:

我在 svg 中使用 <g transform = "rotate(45, 10, 30)"> 同时围绕一个点旋转 som 圆圈和文本,但是,我想保持每个单独字体的方向相同(例如,始终面向一个方向,而文本被移动/旋转)。

例如,如何在旋转后更改右侧图像中的“A”等标签以正确方向?

我该怎么做?

谢谢!

【问题讨论】:

  • 旋转但保持相同的方向?这有点矛盾:“改变它,但不要改变它”。
  • 使用文本元素上的旋转属性以相反方向旋转每个字形。

标签: html svg rotation


【解决方案1】:

纯 SVG

  1. 旋转整个元素组:三角形、螺旋形和带有字母的彩色圆圈
<g id = "common"`>
 ....
</g> 
<animateTransform xlink:href="#common"
  attributeName="transform"
  type="rotate"
  begin="svg1.click"
  restart="whenNotActive"
  repeatCount="indefinite"
  dur="10s"
  values="
       0, 75.74, 74.91;
      -360, 75.74, 74.91"
  additive="sum" />   
  1. 里面是圆圈和字母旋转的第二个动画。
<animateTransform  attributeName="transform" type="rotate" begin="svg1.click" restart="whenNotActive"
repeatCount="indefinite" dur="10s"  
values="
    0, 56.13, 106.87;
    360, 56.13, 106.87"
additive="sum" /> 
  1. 我们使用getBBox() JS方法找到字母旋转中心的坐标
<script> 
  //Find the center of rotation of the letter A
  let bb = a1.getBBox();
console.log(bb.x+bb.width/2); 
console.log(bb.y+bb.height/2);
</script> 

点击后动画会开始

text {
  font-family:sans-serif;
  font-size:14px;
  font-weight:bold;
  fill:#6E6E6E;
  }
<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink" width="190px" height="190px" viewBox="0 0 150 150" version="1.1">
 <defs> 
  </defs>
  <g id="common">
  <g transform="translate(-27.970238,-63.089294)">
    <circle cx="102.9" cy="138.0" r="75" fill="#faa"/> 
    <path   d="m163.7 175.2-121.5 0 60.8-105.2z" fill="#fea"/>
   
   
          <!-- Spiral -->
    <path  d="m101.3 136.5c1.1 2-2.1 2.5-3.3 1.9-3.2-1.7-2.6-6.2-0.5-8.4 3.7-4.1 10.2-2.9 13.6 0.9 5 5.6 3.3 14.3-2.3 18.8-7.4 6-18.4 3.7-23.9-3.6-7-9.2-4.1-22.5 5-29.1 11-8 26.6-4.4 34.3 6.4 9 12.8 4.8 30.7-7.8 39.4-14.6 10-34.8 5.2-44.6-9.2-11.1-16.4-5.6-39 10.6-49.7 18.2-12.1 43.1-6 54.9 11.9 13.1 19.9 6.4 47.2-13.3 60.1" style="fill:none;stroke-width:1;stroke:#6E6E6E">
      
    </path>
    <g id="La">
    <circle cx="55.9" cy="108.0" r="12.9" fill="#efa"/>
        <text id="a1"  x="51" y="112">
          A  
        </text> 
           <!-- Animation of the rotation of the letter `A` -->
         <animateTransform  attributeName="transform" type="rotate" begin="svg1.click" restart="whenNotActive" repeatCount="indefinite" dur="10s"  
        values="0, 56.13, 106.87;360, 56.13, 106.87" additive="sum" /> 
    </g>
    <g>
    <circle cx="153.7" cy="110.3" r="12.9" fill="#efa"/>
    <text id="b1" xml:space="preserve" x="114" y="116" >
        B
    </text> 
        <!-- Animation of the rotation of the letter `B` -->
       <animateTransform  attributeName="transform" type="rotate" begin="svg1.click" restart="whenNotActive" repeatCount="indefinite" dur="10s"  
        values="0, 153.7, 110.3;360, 153.7, 110.3" additive="sum" /> 
  </g> 
  <g>
  <circle cx="105.2" cy="192.5" r="12.9" fill="#efa"   />
    <text id="c1" x="100" y="198"  >
    C
  </text> 
       <!-- Animation of the rotation of the letter `C`   -->
       <animateTransform  attributeName="transform" type="rotate" begin="svg1.click" restart="whenNotActive" repeatCount="indefinite" dur="10s"  
        values="0, 104.93, 193.46;360, 104.93, 193.46" additive="sum" /> 
    </g>
   </g>  
  </g>  
      <!-- Animating the rotation of the entire shape   -->
   <animateTransform xlink:href="#common" attributeName="transform" type="rotate" begin="svg1.click" restart="whenNotActive" repeatCount="indefinite" dur="10s"  
        values="0, 75.74, 74.91;-360, 75.74, 74.91" additive="sum" />   
</svg> 
<script> 
  //Find the center of rotation of the letter A
  let bb = a1.getBBox();
console.log(bb.x+bb.width/2); 
console.log(bb.y+bb.height/2);
</script> 

以螺旋方式添加球运动动画的示例

text {
  font-family:sans-serif;
  font-size:14px;
  font-weight:bold;
  fill:#6E6E6E;
  }
<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink" width="190px" height="190px" viewBox="0 0 150 150" version="1.1">
 <defs> 
  </defs>
  <g id="common">
  <g transform="translate(-27.970238,-63.089294)">
    <circle cx="102.9" cy="138.0" r="75" fill="#faa"/> 
    <path   d="m163.7 175.2-121.5 0 60.8-105.2z" fill="#fea"/>
   
       
   <path   d="m163.7 175.2-121.5 0 60.8-105.2z" fill="#fea"/>
      <!-- Spiral track (pink) -->
    <path id="track"  d="m101.3 136.5c1.1 2-2.1 2.5-3.3 1.9-3.2-1.7-2.6-6.2-0.5-8.4 3.7-4.1 10.2-2.9 13.6 0.9 5 5.6 3.3 14.3-2.3 18.8-7.4 6-18.4 3.7-23.9-3.6-7-9.2-4.1-22.5 5-29.1 11-8 26.6-4.4 34.3 6.4 9 12.8 4.8 30.7-7.8 39.4-14.6 10-34.8 5.2-44.6-9.2-11.1-16.4-5.6-39 10.6-49.7 18.2-12.1 43.1-6 54.9 11.9 13.1 19.9 6.4 47.2-13.3 60.1" style="fill:none;stroke-width:3;stroke:#FFAAAA"/>
          <!-- Spiral -->
    <path  stroke-dasharray="0,432" d="m101.3 136.5c1.1 2-2.1 2.5-3.3 1.9-3.2-1.7-2.6-6.2-0.5-8.4 3.7-4.1 10.2-2.9 13.6 0.9 5 5.6 3.3 14.3-2.3 18.8-7.4 6-18.4 3.7-23.9-3.6-7-9.2-4.1-22.5 5-29.1 11-8 26.6-4.4 34.3 6.4 9 12.8 4.8 30.7-7.8 39.4-14.6 10-34.8 5.2-44.6-9.2-11.1-16.4-5.6-39 10.6-49.7 18.2-12.1 43.1-6 54.9 11.9 13.1 19.9 6.4 47.2-13.3 60.1" style="fill:none;stroke-width:2;stroke:#6E6E6E">
       <!-- Spiral animation -->
     <animate attributeName="stroke-dasharray" begin="svg1.click" repeatCount="indefinite" restart="whenNotActive" dur="10s" values="0,432;432,0;0,432" fill="freeze" />
    </path> 
    <circle cx="0" cy="0" r="6" fill="#6E6E6E">
       <!-- Ball movement in a spiral clockwise -->
    <animateMotion id="forwards"
      begin="svg1.click;back.end"
      dur="5s" >
      <mpath xlink:href="#track" />
    </animateMotion> 
       <!-- Ball movement in a spiral counterclockwise -->
      <animateMotion
           id="back"
           dur="5s"
           begin="forwards.end"
           repeatCount="1"
           keyPoints="1;0"
           keyTimes="0;1"
           calcMode="linear"
           rotate="auto"
           fill="freeze" > 
    <mpath xlink:href="#track" />
    </animateMotion> 
   </circle>    
    
    <g id="La">
    <circle cx="55.9" cy="108.0" r="12.9" fill="#efa"/>
        <text  x="51" y="112"> A  </text> 
         <animateTransform  attributeName="transform" type="rotate" begin="svg1.click" restart="whenNotActive" repeatCount="indefinite" dur="10s"  
        values="0, 55.9, 108;360, 55.9, 108" additive="sum" /> 
    </g>
    <g>
    <circle cx="153.7" cy="110.3" r="12.9" fill="#efa"/>
    <text xml:space="preserve" x="114" y="116" >
        B
    </text> 
       <animateTransform  attributeName="transform" type="rotate" begin="svg1.click" restart="whenNotActive" repeatCount="indefinite" dur="10s"  
        values="0, 153.7, 110.3;360, 153.7, 110.3" additive="sum" /> 
  </g> 
  <g>
  <circle cx="105.2" cy="192.5" r="12.9" fill="#efa"   />
    <text x="100" y="198"  > C
</text> 
       <!-- Animation of the rotation of the letter `C`   -->
       <animateTransform  attributeName="transform" type="rotate" begin="svg1.click" restart="whenNotActive" repeatCount="indefinite" dur="10s"  
        values="0, 105.2, 192.5;360, 105.2, 192.5" additive="sum" /> 
    </g>
   </g>  
  </g>  
      <!-- Animating the rotation of the entire shape   -->
   <animateTransform xlink:href="#common" attributeName="transform" type="rotate" begin="svg1.click" restart="whenNotActive" repeatCount="indefinite" dur="10s"  
        values="0, 75.38, 75;-360, 75.38, 75" additive="sum" />   
</svg>

【讨论】:

    【解决方案2】:

    不要旋转&lt;g&gt;roup 并反向旋转其中的文本,试试这个备用分组。将&lt;g&gt; 居中在origin(0,0) 周围,带有负的x=y= 值并在circle_group 上使用rotate(degree, 0, 0),然后在main_group 上使用translate(x,y)

    编辑:这是一个动画示例,从 source 修改而来。诀窍是使用 sin() 和 cos() 三角函数围绕原点移动它。

        <!DOCTYPE html>
        <html>
    
        <head>  
        <title>JavaScript SVG Animation</title>
        <meta http-equiv="X-UA-Compatible" content="IE=Edge"/> <!-- Remove this line in production. -->
        </head>
    
        <body>
        <svg width="800px" height="800px" viewBox="0 0 800 800">
        <g transform="translate(400, 400)"> <!-- Create a Cartesian coordinate system (with the y-axis flipped) for the animated square. That is, place the origin at the center of the 800 x 800 SVG viewport: -->
    
            <!-- A 200 x 200 square with the upper left-hand corner at (-100, -100). This places the center of the square 
            at the origin (0, 0): -->  
            <rect id="mySquare" x="-100" y="-100" width="200" height="200" rx="5" ry="5" 
                style=" fill: yellow; stroke: yellow; stroke-width: 1; stroke-dasharray: 10, 5;" />
                
            <!-- Represents the x-axis: -->
            <line x1="-400" y1="0" x2="400" y2="0" style="stroke: blue;" /> 
    
            <!-- Represents the y-axis (although up is negative and down is positive): -->  
            <line x1="0" y1="-400" x2="0" y2="400" style="stroke: blue;" /> 
            <circle cx="0" cy="0" r="141" fill="none" stroke="yellow"/>           
            <g id="circle_a">
              <circle cx="0" cy="0" r="10" fill="none" stroke="blue"/>
              <text x="-5" y="5" width="20" height="20">A</text>
            </g>
            <g id="circle_b">
               <circle cx="0" cy="0" r="10" fill="none" stroke="red"/>
                <text x="-5" y="5" width="20" height="20">B</text>
            </g>
        </g>
    
        </svg>
        <script>
        "use strict";
    
        /* CONSTANTS */
        var initialTheta = 0; // The initial rotation angle, in degrees.
        var thetaDelta = 0.3; // The amount to rotate the square about every 16.7 milliseconds, in degrees.
        var angularLimit = 180; // The maximum number of degrees to rotate the square.
        var theSquare = document.getElementById("mySquare");
        var circleA = document.getElementById("circle_a");
        var circleB = document.getElementById("circle_b");
    
        theSquare.currentTheta = initialTheta; // The initial rotation angle to use when the animation starts, stored in a custom property.
    
        var requestAnimationFrameID = requestAnimationFrame(doAnim); // Start the loop.
        function doAnim() {
          if (theSquare.currentTheta > angularLimit) {
            cancelAnimationFrame(requestAnimationFrameID); // The square has rotated enough, instruct the browser to stop calling the doAnim() function.
            return; // No point in continuing, bail now.
          }
    
          theSquare.setAttribute("transform", "rotate(" + theSquare.currentTheta + ")"); // Rotate the square by a small amount.
          circleA.setAttribute("transform", "translate(" +Math.cos((theSquare.currentTheta-45)*Math.PI/180)*141 + "," + Math.sin((theSquare.currentTheta-45)*Math.PI/180)*141+")"); // Move the circle A
          circleB.setAttribute("transform", "translate(" +Math.cos((theSquare.currentTheta+45)*Math.PI/180)*141 + "," + Math.sin((theSquare.currentTheta+45)*Math.PI/180)*141+")"); // move the circle B
          theSquare.currentTheta += thetaDelta;  // Increase the angle that the square will be rotated to, by a small amount.
          requestAnimationFrameID = requestAnimationFrame(doAnim); // Call the doAnim() function about 60 times per second (60 FPS), or about once every 16.7 milliseconds until cancelAnimationFrame() is called.
        }
        </script>

    【讨论】:

    • 注意:此动画在最新的 Chrome、FF 和 IE11(2014 年 7 月)上进行了测试。不适用于 IE9。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-11
    • 1970-01-01
    相关资源
    最近更新 更多