How to align a group (instead of text) along a path in svg?

前端 未结 3 758
半阙折子戏
半阙折子戏 2021-01-07 10:06

Lets assume I have programmatically created a circle and some text, that I want to align along the circle. I am able to do so usin

相关标签:
3条回答
  • 2021-01-07 11:06

    As a starting point here is the workaround I mentioned. It uses some invisible placeholder text and extracts the transformation information with

    placeHolder.getBoundingClientRect();
    

    and

    placeHolder.getRotationOfChar(0);
    

    The result is only an approximation that depends on the font size and on the character of the placeholder.

    var svg = document.getElementById('svg');
    var text = document.createElement('text');
    text.setAttribute('fill','black');
    svg.appendChild(text);
    
    var placeHolder = document.getElementById('placeholder');
    var placeHolderBounds = placeHolder.getBoundingClientRect();
    var angle = placeHolder.getRotationOfChar(0);
    
    var group = document.getElementById('my-group');
    var groupBounds = group.getBoundingClientRect();
    var dx = 0; //groupBounds.width/2;   
    var dy = -groupBounds.height;   
    var x = placeHolderBounds.x;
    var y = placeHolderBounds.y;
    
    var transform = 'translate(' + x +','+ y +') '+ 
                     'rotate('+ angle +') '+ 
                     'translate('+ dx +','+ dy +')';
    group.setAttribute('transform', transform);
    <svg id='svg' width="400" height="400" viewBox="0 0 400 400">
    
    
    <path id="my-path"  d="M87 199C87 114 141 64 200 64 258 64 310 122 313 199 315 273 258 335 200 335 141 335 87 279 87 199Z" style="fill:#089421;"/> 
    <g id="my-group">
      <rect  width="30" height="20" style="fill:red"/>
    </g>
    
    
    <text font-size="12px" >
        <textPath startOffset="10%" xlink:href="#my-path">
          <tspan>Hello World</tspan><tspan id='placeholder' visibility="hidden" >-</tspan>
        </textPath>
      </text>
    </svg>

    0 讨论(0)
  • 2021-01-07 11:10

    In addition I have a rectangular image (or any svg group ), that I also would like to align to the circle (see red rectangle in the example image below).

    However, textPath only seems to work for text elements.

    You can use the rectangle unicode character &#9646;

    In this case you will be able to include it in one textPath command along with other words

    <svg width="400" height="400" viewBox="0 0 400 400">
    
     <path id="pathChain"  d="M87 199C87 114 141 64 200 64 258 64 310 122 313 199 315 273 258 335 200 335 141 335 87 279 87 199Z" style="fill:#089421;"/> 
    
    <text font-size="36"  font-family="Times New Roman" fill="grey" >
    <textPath id="result"  startOffset="7%"   xlink:href="#pathChain">
    <tspan dx="0" dy="-5" fill="black" font-size="48px"> Hello World </tspan> <tspan dx="-20" dy="-10" fill="red" font-size="72px">  &#9646;</tspan>
    </textPath>
    </text>             
    </svg>

    You can use any unicode character that suits you

    <svg width="400" height="400" viewBox="0 0 400 400">
    
     <path id="pathChain"  d="M87 199C87 114 141 64 200 64 258 64 310 122 313 199 315 273 258 335 200 335 141 335 87 279 87 199Z" style="fill:#089421;"/> 
    
    <text font-size="36"  font-family="Times New Roman" fill="grey" >
    <textPath id="result"  startOffset="7%"   xlink:href="#pathChain">
    <tspan dx="0" dy="-5" fill="black" font-size="48px"> Hello World </tspan> <tspan dx="-5" fill="red" font-size="72px">  &#11156;</tspan>
    
    </textPath>
    </text>             
    </svg>

    If necessary, you can make the animation of the letters

    <svg width="400" height="400" viewBox="0 0 400 400">
    
     <path id="pathChain"  d="M87 199C87 114 141 64 200 64 258 64 310 122 313 199 315 273 258 335 200 335 141 335 87 279 87 199Z" style="fill:#089421;"/> 
    
    <text font-size="36"  font-family="Times New Roman" fill="grey" >
    <textPath id="result"    xlink:href="#pathChain">
    <tspan dx="0" dy="-5" fill="black" font-size="48px"> Hello World </tspan> <tspan dx="-5" fill="red" font-size="72px">  &#11156;</tspan>
     <animate  dur="10s" repeatCount="5" attributeName="startOffset" values="5%;50%;50%;5%;5%"/>  
    </textPath>
    </text>             
    </svg>

    0 讨论(0)
  • 2021-01-07 11:13

    As @Paul LeBeau commented:

    No there is no automatic way to do that. You have to position it yourself

    Consider adding svg images to text using absolute positioning

    Since any text in SVG is a vector object, it has absolute coordinates x, y, as the first character of the word and the last.

    Using this you can position an icon or any other vector image to the beginning or end of the text.

    I put the icon in the <symbol> tag and position it at the end of the word using the <use> tag

    <use xlink:href="#speaker" x="245" y="35" />

    <svg width="400" height="400" viewBox="0 0 400 400">
    <symbol>
    <g id="speaker" style="transform-origin:center;transform-box: fill-box;transform:rotate(15deg);" >
        <path fill="#089421" d="M28,7.1v2c7.3,1,13,7.3,13,14.9s-5.7,13.9-13,14.9v2c8.4-1,15-8.2,15-16.9S36.4,8.1,28,7.1z"/>
        <path fill="#546E7A" d="M14,32H7c-1.1,0-2-0.9-2-2V18c0-1.1,0.9-2,2-2h7V32z"/>
        <polygon fill="#78909C" points="26,42 14,32 14,16 26,6"/>
        <path fill="#089421" d="M28,17.3v2.1c1.8,0.8,3,2.5,3,4.6s-1.2,3.8-3,4.6v2.1c2.9-0.9,5-3.5,5-6.7S30.9,18.2,28,17.3z"/>
        <path fill="#089421" d="M28,12.2v2c4.6,0.9,8,5,8,9.8s-3.4,8.9-8,9.8v2c5.7-1,10-5.9,10-11.8S33.7,13.1,28,12.2z"/>
    </g>
    </symbol>
     <path id="pathChain"  d="M87 199C87 114 141 64 200 64 258 64 310 122 313 199 315 273 258 335 200 335 141 335 87 279 87 199Z" style="fill:#089421;"/> 
    
    <text font-size="36"  font-family="Times New Roman" fill="grey" >
      <textPath id="result"    xlink:href="#pathChain">
        <tspan dx="0" dy="-5" fill="black" font-size="48px"> Hello Wordl </tspan> 
      </textPath>
    </text> 
    <use xlink:href="#speaker"  x="245" y="35" />  
              
    </svg>   

    An example with a growing line on which text and an icon are located

    <svg xmlns="http://www.w3.org/2000/svg"  xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="400" viewBox="0 0 400 400" version="1">
    <symbol id="grow">
      <g>
        <circle fill="#FF9800" cx="28" cy="9" r="5"/>
    </g>
    <path fill="#00796B" d="M29,27.3l-9.2-4.1c-1-0.5-1.5,1-2,2c-0.5,1-4.1,7.2-3.8,8.3c0.3,0.9,1.1,1.4,1.9,1.4c0.2,0,0.4,0,0.6-0.1  L28.8,31c0.8-0.2,1.4-1,1.4-1.8C30.2,28.4,29.7,27.6,29,27.3z"/>
    <path fill="#009688" d="M26.8,15.2l-2.2-1c-1.3-0.6-2.9,0-3.5,1.3L9.2,41.1c-0.5,1,0,2.2,1,2.7c0.3,0.1,0.6,0.2,0.9,0.2  c0.8,0,1.5-0.4,1.8-1.1c0,0,9.6-13.3,10.4-14.9s4.9-9.3,4.9-9.3C28.7,17.4,28.2,15.8,26.8,15.2z"/>
    <path fill="#FF9800" d="M40.5,15.7c-0.7-0.8-2-1-2.8-0.3l-5,4.2l-6.4-3.5c-1.1-0.6-2.6-0.4-3.3,0.9c-0.8,1.3-0.4,2.9,0.8,3.4  l8.3,3.4c0.3,0.1,0.6,0.2,0.9,0.2c0.5,0,0.9-0.2,1.3-0.5l6-5C41.1,17.8,41.2,16.6,40.5,15.7z"/>
    <path fill="#FF9800" d="M11.7,23.1l3.4-5.1l4.6,0.6l1.5-3.1c0.4-0.9,1.2-1.4,2.1-1.5c-0.1,0-0.2,0-0.2,0h-9c-0.7,0-1.3,0.3-1.7,0.9  l-4,6c-0.6,0.9-0.4,2.2,0.6,2.8C9.2,23.9,9.6,24,10,24C10.6,24,11.3,23.7,11.7,23.1z"/>
    </symbol>  
      
      <path id="txtPath" d="m22 366c0 0 59-24 74-50C132 253 129 213 128 161 125 33 200 2 200 2" style="fill:none;stroke:#00796B;stroke-width:3"/> 
      
      <use xlink:href="#grow" x="123" y="10" /> 
      <text dx="0" dy="-10px" font-size="20"  font-family="Times New Roman" fill="#414141" >
        <textPath id="result"  startOffset="5%"    xlink:href="#txtPath"> Stock growth in the first half of the year </textPath>
      </text>
    </svg>

    One more example

    <svg xmlns="http://www.w3.org/2000/svg"  xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="400" viewBox="0 0 400 400" version="1">
     <symbol id="Cactus" style="transform-origin:center;transform-box: fill-box;transform:rotate(15deg);">
      <path fill="#7CB342" d="M35.3,9.6c-1.6-0.2-1.3,0.9-1.9,2.7l-1,4.3c-0.3,1-0.7,1.4-2,1.3L25,17.3c-1.6-0.2-3.1,1-3.2,2.6  c-0.2,1.6,1,3.1,2.6,3.2l6.3,0.7c3,0.3,5.5-0.9,6-5.4c0,0,0.6-4.7,0.3-6.6C36.7,10.2,36.6,9.7,35.3,9.6z"/>
    <path fill="#7CB342" d="M12.2,13.6c1.6-0.1,1.3,0.9,1.9,2.8l1.3,6.3c0.3,1,0.7,1.4,2,1.3l5.4-0.4c1.6-0.1,3,1.1,3.2,2.7  c0.1,1.6-1.1,3-2.7,3.2l-6.3,0.5c-3,0.2-5.5-1-5.9-5.5c0,0-0.8-6.7-0.5-8.5C10.7,14.2,10.8,13.7,12.2,13.6z"/>
    <path fill="#8BC34A" d="M24,5c-2.4,0-4,0.6-4.5,3.2c0,0-2.1,16.9,0,32.1c0.3,3.2,2,1.2,4.4,1.2s3.8,2.7,4.4-0.8  c2.5-15.1,0-32.6,0-32.6C27.7,5.2,26.4,5,24,5z"/>
    <path fill="#FFB74D" d="M38.8,43H9.2c0,0,4.9-2.3,14.8-2.3S38.8,43,38.8,43z"/>
     </symbol>
      <path id="txtPath" d="m200 2c0 0 36 31 57 42 15 8 34 6 47 16 15 11 26 27 33 43 8 18 2 41 11 58 9 17 41 40 41 40" fill="none" stroke="green" stroke-width="2"/> 
     
     <use xlink:href="#Cactus" x="355" y="150" /> 
      
      <text font-size="20"  font-family="Times New Roman" fill="grey" >
      <textPath id="result" startOffset="7%"   xlink:href="#txtPath">
        <tspan dx="0" dy="-5"  fill="black" >Decrease in stocks per year </tspan> 
      </textPath>
    </text> 
    </svg>

    0 讨论(0)
提交回复
热议问题