nrsmac
nrsmac

Reputation: 105

How to place text on specific position in SVG?

I have an SVG with <path> elements embedded into a website which will work as an image map. The client has told me she wants numbers and embedded on each of the paths, and text on others. Any ideas how to accomplish this?

Maybe if I could access the centre coordinate of every zone, I could use some JS to position the text to there, but I am not sure how to do that. Here is some of the code with example paths to hide client information:

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 916.32 2130.72" style="enable-background:new 0 0 916.32 2130.72;" xml:space="preserve"> 
<g id="Layer_2">
  <image style="overflow:visible;" width="1909" height="4439" id="bg" xlink:href="map.jpg" transform="matrix(0.48 0 0 0.48 0.0681 -1.0503)">
  </image>
</g>
<g id="Layer_1">
  <a xlink:href="#">
    <path id="path1" class="st0" d="M766.56,190.56l78.24-82.08l28.8,4.8l18.24,79.68l-26.88,72.48l-86.4-33.6l-0.48-7.2V213.6
    l-1.92-7.68l-4.32-6.72L766.56,190.56z"></path>
  </a>
  <path id="path2" class="st0" d="M530.88,272.16l64.8-2.88l5.76,74.4l-67.68,1.44L530.88,272.16z"></path>
  <path id="path3" class="st0" d="M407.52,276.96l45.12-0.48l5.28,72.48l-83.52,4.32L407.52,276.96z"></path>    
</g>
</svg>

Website with SVG paths superimposed over an img

Upvotes: 3

Views: 1306

Answers (2)

Alexandr_TT
Alexandr_TT

Reputation: 14545

I have an SVG with elements embedded into a website which will work as an image map. The client has told me she wants numbers and embedded on each of the paths, and text on others.

I want to show you step by step the technique with which this kind of problem is solved.
It is not necessary to draw a map of the region in svg. You can take a screenshot of a fragment of a real map and add any text information to it.

  1. I took a screenshot of the map drawing from the question and uploaded it to the vector editor

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink"
       width="948" height="761" viewBox="0 0 948 761" preserveAspectRatio="xMinYMin meet" >  
<image xlink:href="https://i.sstatic.net/DriVh.jpg" width="100%" height="100%" />  
</svg>

  1. At the second step in the vector editor using the tool Draw Bezier curves and straight lines, lines are created along which the text will be located.

enter image description here

  1. The file is saved in SVG format and the paths of these lines are copied from it.

The required text will be located along these patches.

The beginning of the text on the line can be adjusted with the attribute startOffset ="35%"

Due to the fact that the bitmap and the text are located within the same SVG, the relative positioning will never be violated on any display of the gadget.

Below is the complete application code

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink"
       width="948" height="761" viewBox="0 0 948 761" preserveAspectRatio="xMinYMin meet">  
  <!-- Screenshot of a map fragment -->
<image xlink:href="https://i.sstatic.net/DriVh.jpg" width="100%" height="100%" /> 

    <!-- Paths along which text information will be located -->
<path id="pali" d="m274.8 751.9c0 0-0.5-105.9 4.6-158.5 4.7-49.1 13-97.9 23.9-145.9 9.9-43.6 19.5-87.9 37.6-128.8 15.1-34.1 28.3-97.8 41-147.1 7.8-30.3 21.7-91.2 21.7-91.2" style="fill:none;stroke-width:2;stroke:none"/>
  <path id="south50" d="m228 291.3 94.6-5.7" style="fill:none;"/>
  <path id="south50_2" d="m399 269.7c0 0 101.8-5 152.8-6.8 28.1-1 56.3-1.2 84.4-2.3 24.3-0.9 48.9 0.6 73-3.4 16-2.7 30.7-11.4 46.7-13.7 0.4-0.1 1.1 0 1.1 0" style="fill:none;"/>
  <path id="south120" d="m348.9 516.2c0 0 76-3.4 114-4.6 35.3-1.1 72.7-2.8 106-2.3 25.1 0.4 4.1 101.1 2.3 151.6-1.1 30.9-8 92.3-8 92.3" style="fill:none;"/>
  <path id="south120_2"  d="m600.8 509 209.8-9.1" style="fill:none;"/> 
  
  <text font-family="serif" font-size="22px" font-weight="700">
    <textPath href="#pali" startOffset="35%">Palisades DR street</textPath>
     <textPath href="#south50" >50 south</textPath>   
      <textPath href="#south50_2" startOffset="75%"  >50 south</textPath> 
       <textPath href="#south120" startOffset="15%" >120 south</textPath>
        <textPath href="#south120_2" startOffset="55%" >120 south</textPath>
</text>
</svg>   

As a bonus, the option to animate the route to the office

Please read the comments in the program code.
I hope this will help you understand the principle of the route animation

The animation will start after clicking on the SVG canvas

.container {
width:75vw;
height:75vh
}
<div class="container">
<svg id="svg1" version="1.1" xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink"
        viewBox="0 0 948 761" preserveAspectRatio="xMinYMin meet" >   
<defs>
 <mask id="msk" > 
            <!-- Animation of a mask showing route growth -->
         <path stroke="white" stroke-width="3" stroke-dasharray="1212" stroke-dashoffset="1212" stroke-dash-offset="1212" id="trace" d="m555.2 749.6c0 0 6.6-76 9.1-114 2.8-41.4 25.3-116.9 6.8-124.3-46.7-18.7-133.3 6.7-199.5 0-20.8-2.1-48.8 4.1-61.6-12.5-21.3-27.8 0.8-70.4 6.8-104.9 5.9-33.5 14.9-66.9 28.5-98 4.4-10.2 7.7-22.7 17.1-28.5 34.4-21.2 80.5-7 120.8-9.1 41.4-2.1 82.9-1.5 124.3-3.4 29.7-1.4 59.3-3.6 88.9-5.7 9.9-0.7 20.1 0.3 29.6-2.3 29.8-8.2 83.2-41 83.2-41">
    <animate attributeName="stroke-dashoffset"
     begin="svg1.click"
     dur="10s"
     values="1212;0"
     fill="freeze" />
  </path>
 </mask>  
 <symbol id="marker" width="4%" viewBox="0 0 365 560" > 
  <path id="marker" fill="#00AEEF" d="M182.9,551.7c0,0.1,0.2,0.3,0.2,0.3S358.3,283,358.3,194.6c0-130.1-88.8-186.7-175.4-186.9
        C96.3,7.9,7.5,64.5,7.5,194.6c0,88.4,175.3,357.4,175.3,357.4S182.9,551.7,182.9,551.7z M122.2,187.2c0-33.6,27.2-60.8,60.8-60.8
        c33.6,0,60.8,27.2,60.8,60.8S216.5,248,182.9,248C149.4,248,122.2,220.8,122.2,187.2z"/>
  </symbol>     
</defs>    

     <!-- Fragment of a raster map -->
<image xlink:href="https://i.sstatic.net/DriVh.jpg" width="100%" height="100%" /> 

    <!-- patches along which text information is located -->
<path id="pali" d="m274.8 751.9c0 0-0.5-105.9 4.6-158.5 4.7-49.1 13-97.9 23.9-145.9 9.9-43.6 19.5-87.9 37.6-128.8 15.1-34.1 28.3-97.8 41-147.1 7.8-30.3 21.7-91.2 21.7-91.2" style="fill:none;stroke-width:2;stroke:none"/>
  <path id="south50" d="m228 291.3 94.6-5.7" style="fill:none;"/>
  <path id="south50_2" d="m399 269.7c0 0 101.8-5 152.8-6.8 28.1-1 56.3-1.2 84.4-2.3 24.3-0.9 48.9 0.6 73-3.4 16-2.7 30.7-11.4 46.7-13.7 0.4-0.1 1.1 0 1.1 0" style="fill:none;"/>
  <path id="south120" d="m348.9 516.2c0 0 76-3.4 114-4.6 35.3-1.1 72.7-2.8 106-2.3 25.1 0.4 4.1 101.1 2.3 151.6-1.1 30.9-8 92.3-8 92.3" style="fill:none;"/>
  <path id="south120_2"  d="m600.8 509 209.8-9.1" style="fill:none;"/> 
  
       <!-- Route to the office -->
 <path id="trace_anim" mask="url(#msk)" fill="none" stroke="crimson" stroke-width="4" stroke-dasharray="10 7" d="m555.2 749.6c0 0 6.6-76 9.1-114 2.8-41.4 25.3-116.9 6.8-124.3-46.7-18.7-133.3 6.7-199.5 0-20.8-2.1-48.8 4.1-61.6-12.5-21.3-27.8 0.8-70.4 6.8-104.9 5.9-33.5 14.9-66.9 28.5-98 4.4-10.2 7.7-22.7 17.1-28.5 34.4-21.2 80.5-7 120.8-9.1 41.4-2.1 82.9-1.5 124.3-3.4 29.7-1.4 59.3-3.6 88.9-5.7 9.9-0.7 20.1 0.3 29.6-2.3 29.8-8.2 83.2-41 83.2-41" />
   
  <text font-family="serif" font-size="22px" font-weight="700">
    <textPath href="#pali" startOffset="35%">Palisades DR street</textPath>
     <textPath href="#south50" >50 south</textPath>   
      <textPath href="#south50_2" startOffset="75%"  >50 south</textPath> 
       <textPath href="#south120" startOffset="15%" >120 south</textPath>
        <textPath href="#south120_2" startOffset="55%" >120 south</textPath>   
</text>   
       <!-- Markers on the map -->
   <use xlink:href="#marker" x="800" y="-200" />
    <use xlink:href="#marker" x="550" y="350" />
</svg>   
</div>

Upvotes: 4

Bharata
Bharata

Reputation: 14155

You could use <textPath> SVG element to draw all your textes. For each text you have to use one <textPath> and one <path> element for it. To render text along the shape of a <path>, enclose the text in a <textPath> element that has an href attribute with a reference to the <path> element. All this <path> elements you have to add into <defs> element with unique ID. Read more about this element and his attributes under the link above.

And it is very important: all your <textPath> elements you have to write within <text> element on the end of yor SVG because of the zIndex (the lattest added element is on top).

And here is the demo how it works:

<svg width="400" height="120" viewBox="0 0 1000 300">
<defs>
<path id="MyPath1"
      d="M 100 200 
         C 200 100 300   0 400 100
         C 500 200 600 300 700 200
         C 800 100 900 100 900 100"/>

<path id="MyPath2" d="M300,300L700,50"/>
</defs>

<!-- red line under text. You can delete the following line  -->
<use href="#MyPath1" fill="none" stroke="red"/>

<text font-family="Verdana" font-size="42.5">
    <textPath href="#MyPath1">We go up, then we go down, then up again</textPath>
    <textPath href="#MyPath2" fill="red">And the second text</textPath>
</text>

Unfortunately, we can not use your code, because it is incomplete.

Upvotes: 5

Related Questions