Home > front end >  How to position an SVG's <text> element relatively to its parent <g> element?
How to position an SVG's <text> element relatively to its parent <g> element?

Time:10-21

I'm working on a booking tool and as part of the process, users have to select a desk on the map by clicking on it.

Each desk is in a <g> with its own <title>, <path> and <text> elements. It seems every <text> aligns to the SVG itself, not to their parent <g>. We have like ~200 desks, so positioning every desk number is a bit too much work, plus, the floor map can change from time to time. Did I miss anything?

My example is a simplified version:

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 453.16 313.93">
    <defs>
        <style>
        .cls-1 {
            fill: none;
            stroke: #231f20;
            stroke-miterlimit: 10;
        }
        .cls-2 {
            font-size: 30px;
            text-anchor: middle;
        }
        </style>
    </defs>
    <g>
        <path  d="M122.05,61.28H.5V.5H122.05V61.28Z"/>
        <text  x="63" y="34">001</text>
    </g>
    <g>
        <path  d="M122.05,145.33H.5v-60.78H122.05v60.78Z"/>
        <text  x="63" y="116">002</text>
    </g>
    <g>
        <path  d="M122.05,229.38H.5v-60.78H122.05v60.78Z"/>
        <text  x="63" y="200">003</text>
    </g>
    </svg>

CodePudding user response:

Use a transform attribute (or a CSS transform if you like) to change the g co-ordinate system. All co-ordinates of children will use that transformed co-ordinate system.

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 453.16 313.93">
    <defs>
        <style>
        .cls-1 {
            fill: none;
            stroke: #231f20;
            stroke-miterlimit: 10;
        }
        .cls-2 {
            font-size: 30px;
            text-anchor: middle;
        }
        </style>
    </defs>
    <g>
        <path  d="M122.05,61.28H.5V.5H122.05V61.28Z"/>
        <text  x="63" y="34">001</text>
    </g>
    <g transform="translate(0, 30)">
        <path  d="M122.05,145.33H.5v-60.78H122.05v60.78Z"/>
        <text  x="63" y="116">002</text>
    </g>
    <g transform="translate(0, 60)">
        <path  d="M122.05,229.38H.5v-60.78H122.05v60.78Z"/>
        <text  x="63" y="200">003</text>
    </g>
    </svg>

CodePudding user response:

Yes, you can just use the <g> element to move around the boxes. Here you can see that all boxes are the same, except the number and the transform attribute. Both <path> and <text> are placed relative to the <g> (an imaginary box that is 120x60). The <path> just have the width and height of the box (all d attributes have the same value/path!) and the <text> is placed in the middle of the box using text-anchor and dominant-baseline.

<svg width="600" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 300">
  <defs>
    <style>
      .cls-1 {
        fill: none;
        stroke: #231f20;
        stroke-miterlimit: 10;
        stroke-width: 2;
      }
      .cls-2 {
        font-size: 30px;
        text-anchor: middle;
        dominant-baseline: middle;
      }
    </style>
  </defs>
  <g transform="translate(5 5)">
    <path  d="M 0 0 H 120 V 60 H 0 Z"/>
    <text  x="60" y="30">001</text>
  </g>
  <g transform="translate(5 75)">
    <path  d="M 0 0 H 120 V 60 H 0 Z"/>
    <text  x="60" y="30">002</text>
  </g>
  <g transform="translate(5 145)">
    <path  d="M 0 0 H 120 V 60 H 0 Z"/>
    <text  x="60" y="30">003</text>
  </g>
</svg>

CodePudding user response:

Add position: absolute; to the child and position: relative; to the parent.

  • Related