在 SVG 的多个复杂路径上垂直居中和水平居中一些数字

Center vertically et horizontally some numbers on multiple complex paths on SVG

我想在此 SVG 的每个路径上垂直和水平居中放置一些数字。

目前,我可以通过设置任意 X 和 Y 值来实现这一点,例如。 :

<path id="path-44" d="xxxxxxxxxxxx"/>
<text class="numero-dep" text-anchor="middle" xlink:href="#path-44" x="142" y="242">44</text>

它有效,但我必须手动为超过一百条路径执行此操作(在 SVG 示例中,我删除了几乎所有 paths 以简化问题。但它是法国地图我有 100 多个 paths

有没有办法自动水平和垂直居中某些路径上的某些文本?

目前,我尝试使用 css 技术(转换 属性、flexbox、网格)使文本居中,但它不起作用。

我也尝试过使用 textPath 但我无法将此元素居中。我发现 textPath 很有趣,它有一个 href 属性,其中包含对元素的引用。所以作为参考,我希望将文本居中,但似乎不可能。

.map__image path {
  fill: red;
  stroke: #fff;
  stoke-width: 1px;
  transition: color 0.3s;
}
<div class="map__image">

  <svg xmlns="http://www.w3.org/2000/svg" xmlns:amcharts="http://amcharts.com/ammap" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 612 585">
                <g>
                
                
                <a xlink:href="" xlink:title="Loire" id="FR-42">
                    <path class="land" d="M377,302.07L377.43,303.83L376.64,305.75L380.06,306.45L380.92,308.27L380.92,308.27L381.96,308.27L381.96,308.27L385.46,306.68L386.71,307.97L388.59,308.17L389.81,306.94L390.56,307.94L391.75,307.35L391.56,309.09L392.62,309.22L394.79,307.5L396.59,307.53L396.22,306.65L397.29,305.4L397.29,305.4L398.64,305.97L397.65,307.28L399.29,308.96L398.47,310.44L396.99,309.64L394.58,310.79L393.8,314.38L391.56,315.62L394.19,318.23L393.64,319.23L391.34,318.88L395.53,322.74L394.58,324.3L395.42,325.82L397.65,326.92L396.88,331.41L395.67,332.23L396.21,333.33L397.9,333.74L396.37,338.1L399.52,340.88L400.71,343.12L406.74,343.73L407.85,345.62L409.43,344.58L408.22,346.31L408.32,348.92L410.13,349.54L411.21,348.51L412.65,350.82L412.65,350.82L412.6,356.09L412.6,356.09L406.75,359.27L407.07,360.47L405.74,361.51L406.17,362.87L401.23,363.73L401.23,363.73L399.29,361.45L397.38,362.43L397.38,362.43L396.88,362.24L396.88,362.24L395.7,361.45L396.6,359.87L394.97,358.91L396.45,357.78L395.58,356.28L394.01,355.73L392.51,356.54L390.89,354.71L387.81,354.71L387.6,356.14L384.59,356.53L384.17,357.85L383.12,356.68L382.07,357.06L381.97,358.32L380.23,355.51L378.56,355.74L377.4,358.01L376.96,356.59L376.96,356.59L376.72,354.1L379.7,351.96L380.59,348.43L379.6,347.8L378.47,343.57L373.9,340.41L371.96,336.87L372.11,334.88L370.11,333.38L370.06,331.94L368.3,330.96L369.69,329.63L369.4,326.27L371.02,325.33L368.46,322.71L368.46,322.71L369.08,320.13L370.52,320.6L371.04,319.57L372.37,320.14L374.17,318.6L373.1,315.37L373.77,313.27L372.59,311.88L372.44,309.25L373.24,308.83L371.55,304.27L373.05,304.18L373,303.13L375.67,302.88L376.11,302.07L376.11,302.07z"/>
                </a>
                <a xlink:href="#test" xlink:title="Haute-Loire" id="FR-43">
                    <path class="land" d="M344.32,356.93L347.13,356.96L349.48,354.45L351.66,354.07L352.13,352.86L353.23,354.23L354.42,352.75L355.4,354L357.12,354.17L358.87,353.97L360.47,352.39L361.67,354.15L363.35,353.94L365.33,357.72L367.25,356.33L367.5,355.04L369.09,355.56L368.78,356.49L371.87,357.12L372.99,354.58L374.38,355.09L374.45,356.1L376.96,356.59L376.96,356.59L377.4,358.01L378.56,355.74L380.23,355.51L381.97,358.32L382.07,357.06L383.12,356.68L384.17,357.85L384.59,356.53L387.6,356.14L387.81,354.71L390.89,354.71L392.51,356.54L394.01,355.73L395.58,356.28L396.45,357.78L394.97,358.91L396.6,359.87L395.7,361.45L396.88,362.24L396.88,362.24L397.38,362.43L397.38,362.43L399.29,361.45L401.23,363.73L401.23,363.73L401.09,366.41L399.58,369.05L400.18,370.61L399.39,370.4L399.28,371.14L398.75,369.59L396.71,369.15L397.75,371.43L396.09,371.76L395.56,373.6L397.07,375.17L393.5,376.45L393.25,377.78L394.22,379.16L390.53,379.74L387.69,385.01L382.63,385.05L382.37,387.31L381.43,387.05L381.2,388.11L380.47,387.35L380.71,388.6L379.09,387.7L377.49,390.55L378.02,391.1L375.44,392.52L375.44,392.52L374.37,392.31L374.67,390.89L373.28,391.33L371.27,389.22L370.53,387.04L367.34,387.59L367.62,385.96L365.82,384.52L364.31,384.84L364.1,387.74L363.33,387.17L359.51,388.71L356.97,383.52L356.45,380.09L355.89,380.47L354.66,379.27L354.66,379.27L353.96,378.42L355.04,377.33L353.25,377.02L353.66,376.1L352.66,376.48L352.08,375.68L352.62,372.67L351.41,371.52L354.63,371.5L351.66,370.51L350.5,367.4L350.5,367.4L350.5,366.82L350.5,366.82L351,365.35L349.48,364.77L348.91,361.34L346.48,361.83L346.3,360.27L343.08,360.62L344.4,359.4L343.42,358.54L344.34,358.37z"/>


                </a>
                <a xlink:href="" xlink:title="Loire-Atlantique" id="FR-44">
                    <path id="path-44" class="land" d="M128.02,219.89l5.19,-3.85l0.76,1.38l3.94,-2.29l5.75,0.67l1.15,-0.93l1.49,0.17l1.49,-3.29l6.19,-2.43l-0.24,-1.99l3.76,0.44l1.03,1.79l4.84,1.39l0,0l0.51,1.26l-0.83,1.54l2.44,0.57l0.86,1.7l0,0l-0.07,0.61l0,0l-0.23,1.25l0.94,0.17l0.88,2.54l5.48,1.87l-1.52,1.62l-5.4,-0.59l0.66,3.84l7.86,1.08l0.78,4.4l1.08,1.27l-2.22,1.74l-6.98,0.11l-6.09,1.79l-2.61,2.17l2.42,-0.1l2.23,3.81l1.98,-0.52l1.29,4.09l0,0l-0.02,0.26l0,0l-3.08,2.67l0.59,1.1l-1.02,1.2l3.28,0.37l0.58,1.28l1.62,0.56l-0.02,1.22l-1.25,0.86l0,0l-2.25,-0.71l-2.86,-2.72l-1.24,3.08l-1.88,-0.67l-1.35,0.81l0.56,4.51l-4.07,1.85l-0.37,-6.31l-1.3,-0.47l-2.2,1.52l0.55,0.76l-0.59,1.34l1.56,2.36l-0.42,1.08l-0.69,-0.17l1.88,2.72l-1.8,0.39l-0.14,0.83l-4.75,-0.84l-1,-0.97l-1.48,0.38l-0.98,-2.69l-3.18,-0.12l-0.24,-1.39l-2.99,-0.48l-0.65,-1.77l-1.06,-0.18l-1.56,-2.18l0,0l-3.07,-3.98l-8.07,-2.34l3.36,-2.17l-0.21,-5.83l-1.67,-0.36l-3.54,2.18l-3.26,-2.68l-1.74,0.1l-0.6,1.12l-4.7,-1.94l1.5,-1.12l0.12,-1.81l-2.23,-2.2l4.18,-3.01l0.02,-1.49l0,0l1.43,-1.77l0.9,1.27l3.5,-0.29l0.78,-3.38l1.63,0.13l0.59,1.19l2.49,-1.11l-0.17,1.08l1.06,0.32l0.26,-1.95l2.46,-0.69l-0.11,-3.76l0.8,-1.06L128.02,219.89z"/>
                    <text class="numero-dep" text-anchor="middle" xlink:href="#path-44" x="142" y="242">44</text>
                </a>

                <a xlink:href="" xlink:title="Loiret" id="FR-45">
                    <path class="land" d="M297.89,179.38L299.84,179.51L302.49,178.11L304.93,178.63L304.44,177.54L305.67,177.83L306.57,175.79L308.34,176.55L308.32,178.63L309.22,177.59L310.59,177.81L310.59,177.81L311.05,176.75L311.05,176.75L311.81,176.5L313.05,178.05L314.93,177.56L314.93,177.56L315.74,181.04L319.15,182.38L319.86,184.74L319.18,187.44L318.21,186.93L316.57,189.46L319.8,189.44L321.37,188.4L327.44,189.49L329.46,188.13L328.72,186.8L329.82,187.63L331.32,186.68L331.41,188.98L332.17,189.09L334.11,187.46L337.05,187.03L337.05,187.03L340.89,188.88L340.33,189.95L341.15,189.89L341.73,192.6L344.84,195.29L343.79,195.93L344.86,196.72L344.98,198.82L343.63,200.35L343.63,200.35L343.14,200.69L343.14,200.69L341.75,202.64L340.05,202.94L340.2,204.95L339.49,205.34L341.02,206.42L340.21,207.42L340.72,210.3L333.51,212.12L333.35,214.61L334.62,214.4L334.64,215.43L336.6,216.77L336.3,217.59L337.73,219.03L336.86,220.17L337.03,221.87L338.69,223.68L338.69,223.68L337.95,224.44L336.13,223.9L334.39,225.18L333.72,224.72L333.33,225.53L334.45,226.65L334.45,226.65L331.65,228.23L328.52,225.57L328.22,228.27L325.88,228.89L325.4,227.32L323.67,226.46L323.75,225.42L321.52,223.52L318.54,223.75L316.32,221.21L313.59,222.69L310.17,220.02L308.06,220.56L308.06,220.56L308.15,219.29L306.58,217L302.81,217.56L298.51,216.99L296.67,218.31L295.71,218.2L295.53,216.9L292.59,217.21L292.29,216.15L291.81,218.23L289.6,219.56L287.38,218.09L286.27,213.61L282.82,212.07L280.65,214.08L281.58,213.09L279.38,211.39L280.31,209.69L278.48,208.25L281.19,204.65L280.81,203.19L278.35,201.38L279.69,200.08L280.1,197.8L278.28,198.27L278.28,198.27L277.9,195.49L279.41,195.32L279.3,194.44L281.33,195.27L281.53,194.45L282.4,194.54L282.57,192.82L284.01,192.41L284.46,193.26L285.22,192.35L287.55,193.22L289.74,192.39L289.93,191.57L291.04,192.25L293.28,191.09L294.79,188.09L294.14,187.24L294.96,186.38L296.98,186.41L296.03,185.07L296.69,184.63L296.95,185.29L297.28,184.54L296.56,181.91z"/>
                </a>
                
                
                </g>
                </svg>

</div>

正如我评论的那样:您可以将文本置于路径的边界框内的中心。您可以使用 getBBox() 方法获取边界框的位置和大小。然而,根据路径,边界框的中心可能会落在路径之外 - 如 FR-42

的情况

我会这样做:

const SVG_NS = "http://www.w3.org/2000/svg";
const theSvg = document.querySelector("svg")

let a_paths = document.querySelectorAll("a path");

a_paths.forEach(p =>{
  //get the bounding box of the path
  let bb = p.getBBox()
  //Get the text content
  let text_content = p.parentNode.id.split("-")[1];
  // create a new element text and set the x and y attributes and the text content
  let txt = document.createElementNS(SVG_NS, 'text');
  txt.setAttributeNS(null,"x",bb.x + bb.width/2);
  txt.setAttributeNS(null,"y",bb.y + bb.height/2);
  txt.textContent = text_content;
  // append the text to the svg element
  theSvg.appendChild(txt)
  })
.map__image path {
  fill: red;
  stroke: #fff;
  stoke-width: 1px;
  transition: color 0.3s;
}

text{text-anchor:middle;}
<div class="map__image">

  <svg xmlns="http://www.w3.org/2000/svg" xmlns:amcharts="http://amcharts.com/ammap"
    xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 612 585">
    <g>

      <a xlink:href="" xlink:title="Loire" id="FR-42">
        <path class="land"
          d="M377,302.07L377.43,303.83L376.64,305.75L380.06,306.45L380.92,308.27L380.92,308.27L381.96,308.27L381.96,308.27L385.46,306.68L386.71,307.97L388.59,308.17L389.81,306.94L390.56,307.94L391.75,307.35L391.56,309.09L392.62,309.22L394.79,307.5L396.59,307.53L396.22,306.65L397.29,305.4L397.29,305.4L398.64,305.97L397.65,307.28L399.29,308.96L398.47,310.44L396.99,309.64L394.58,310.79L393.8,314.38L391.56,315.62L394.19,318.23L393.64,319.23L391.34,318.88L395.53,322.74L394.58,324.3L395.42,325.82L397.65,326.92L396.88,331.41L395.67,332.23L396.21,333.33L397.9,333.74L396.37,338.1L399.52,340.88L400.71,343.12L406.74,343.73L407.85,345.62L409.43,344.58L408.22,346.31L408.32,348.92L410.13,349.54L411.21,348.51L412.65,350.82L412.65,350.82L412.6,356.09L412.6,356.09L406.75,359.27L407.07,360.47L405.74,361.51L406.17,362.87L401.23,363.73L401.23,363.73L399.29,361.45L397.38,362.43L397.38,362.43L396.88,362.24L396.88,362.24L395.7,361.45L396.6,359.87L394.97,358.91L396.45,357.78L395.58,356.28L394.01,355.73L392.51,356.54L390.89,354.71L387.81,354.71L387.6,356.14L384.59,356.53L384.17,357.85L383.12,356.68L382.07,357.06L381.97,358.32L380.23,355.51L378.56,355.74L377.4,358.01L376.96,356.59L376.96,356.59L376.72,354.1L379.7,351.96L380.59,348.43L379.6,347.8L378.47,343.57L373.9,340.41L371.96,336.87L372.11,334.88L370.11,333.38L370.06,331.94L368.3,330.96L369.69,329.63L369.4,326.27L371.02,325.33L368.46,322.71L368.46,322.71L369.08,320.13L370.52,320.6L371.04,319.57L372.37,320.14L374.17,318.6L373.1,315.37L373.77,313.27L372.59,311.88L372.44,309.25L373.24,308.83L371.55,304.27L373.05,304.18L373,303.13L375.67,302.88L376.11,302.07L376.11,302.07z" />
      </a>
      <a xlink:href="#test" xlink:title="Haute-Loire" id="FR-43">
        <path class="land"
          d="M344.32,356.93L347.13,356.96L349.48,354.45L351.66,354.07L352.13,352.86L353.23,354.23L354.42,352.75L355.4,354L357.12,354.17L358.87,353.97L360.47,352.39L361.67,354.15L363.35,353.94L365.33,357.72L367.25,356.33L367.5,355.04L369.09,355.56L368.78,356.49L371.87,357.12L372.99,354.58L374.38,355.09L374.45,356.1L376.96,356.59L376.96,356.59L377.4,358.01L378.56,355.74L380.23,355.51L381.97,358.32L382.07,357.06L383.12,356.68L384.17,357.85L384.59,356.53L387.6,356.14L387.81,354.71L390.89,354.71L392.51,356.54L394.01,355.73L395.58,356.28L396.45,357.78L394.97,358.91L396.6,359.87L395.7,361.45L396.88,362.24L396.88,362.24L397.38,362.43L397.38,362.43L399.29,361.45L401.23,363.73L401.23,363.73L401.09,366.41L399.58,369.05L400.18,370.61L399.39,370.4L399.28,371.14L398.75,369.59L396.71,369.15L397.75,371.43L396.09,371.76L395.56,373.6L397.07,375.17L393.5,376.45L393.25,377.78L394.22,379.16L390.53,379.74L387.69,385.01L382.63,385.05L382.37,387.31L381.43,387.05L381.2,388.11L380.47,387.35L380.71,388.6L379.09,387.7L377.49,390.55L378.02,391.1L375.44,392.52L375.44,392.52L374.37,392.31L374.67,390.89L373.28,391.33L371.27,389.22L370.53,387.04L367.34,387.59L367.62,385.96L365.82,384.52L364.31,384.84L364.1,387.74L363.33,387.17L359.51,388.71L356.97,383.52L356.45,380.09L355.89,380.47L354.66,379.27L354.66,379.27L353.96,378.42L355.04,377.33L353.25,377.02L353.66,376.1L352.66,376.48L352.08,375.68L352.62,372.67L351.41,371.52L354.63,371.5L351.66,370.51L350.5,367.4L350.5,367.4L350.5,366.82L350.5,366.82L351,365.35L349.48,364.77L348.91,361.34L346.48,361.83L346.3,360.27L343.08,360.62L344.4,359.4L343.42,358.54L344.34,358.37z" />

      </a>
      <a xlink:href="" xlink:title="Loire-Atlantique" id="FR-44">
        <path id="path-44" class="land"
          d="M128.02,219.89l5.19,-3.85l0.76,1.38l3.94,-2.29l5.75,0.67l1.15,-0.93l1.49,0.17l1.49,-3.29l6.19,-2.43l-0.24,-1.99l3.76,0.44l1.03,1.79l4.84,1.39l0,0l0.51,1.26l-0.83,1.54l2.44,0.57l0.86,1.7l0,0l-0.07,0.61l0,0l-0.23,1.25l0.94,0.17l0.88,2.54l5.48,1.87l-1.52,1.62l-5.4,-0.59l0.66,3.84l7.86,1.08l0.78,4.4l1.08,1.27l-2.22,1.74l-6.98,0.11l-6.09,1.79l-2.61,2.17l2.42,-0.1l2.23,3.81l1.98,-0.52l1.29,4.09l0,0l-0.02,0.26l0,0l-3.08,2.67l0.59,1.1l-1.02,1.2l3.28,0.37l0.58,1.28l1.62,0.56l-0.02,1.22l-1.25,0.86l0,0l-2.25,-0.71l-2.86,-2.72l-1.24,3.08l-1.88,-0.67l-1.35,0.81l0.56,4.51l-4.07,1.85l-0.37,-6.31l-1.3,-0.47l-2.2,1.52l0.55,0.76l-0.59,1.34l1.56,2.36l-0.42,1.08l-0.69,-0.17l1.88,2.72l-1.8,0.39l-0.14,0.83l-4.75,-0.84l-1,-0.97l-1.48,0.38l-0.98,-2.69l-3.18,-0.12l-0.24,-1.39l-2.99,-0.48l-0.65,-1.77l-1.06,-0.18l-1.56,-2.18l0,0l-3.07,-3.98l-8.07,-2.34l3.36,-2.17l-0.21,-5.83l-1.67,-0.36l-3.54,2.18l-3.26,-2.68l-1.74,0.1l-0.6,1.12l-4.7,-1.94l1.5,-1.12l0.12,-1.81l-2.23,-2.2l4.18,-3.01l0.02,-1.49l0,0l1.43,-1.77l0.9,1.27l3.5,-0.29l0.78,-3.38l1.63,0.13l0.59,1.19l2.49,-1.11l-0.17,1.08l1.06,0.32l0.26,-1.95l2.46,-0.69l-0.11,-3.76l0.8,-1.06L128.02,219.89z" />
        <!-- <text class="numero-dep" text-anchor="middle" xlink:href="#path-44" x="142" y="242">44</text>-->
      </a>

      <a xlink:href="" xlink:title="Loiret" id="FR-45">
        <path class="land"
          d="M297.89,179.38L299.84,179.51L302.49,178.11L304.93,178.63L304.44,177.54L305.67,177.83L306.57,175.79L308.34,176.55L308.32,178.63L309.22,177.59L310.59,177.81L310.59,177.81L311.05,176.75L311.05,176.75L311.81,176.5L313.05,178.05L314.93,177.56L314.93,177.56L315.74,181.04L319.15,182.38L319.86,184.74L319.18,187.44L318.21,186.93L316.57,189.46L319.8,189.44L321.37,188.4L327.44,189.49L329.46,188.13L328.72,186.8L329.82,187.63L331.32,186.68L331.41,188.98L332.17,189.09L334.11,187.46L337.05,187.03L337.05,187.03L340.89,188.88L340.33,189.95L341.15,189.89L341.73,192.6L344.84,195.29L343.79,195.93L344.86,196.72L344.98,198.82L343.63,200.35L343.63,200.35L343.14,200.69L343.14,200.69L341.75,202.64L340.05,202.94L340.2,204.95L339.49,205.34L341.02,206.42L340.21,207.42L340.72,210.3L333.51,212.12L333.35,214.61L334.62,214.4L334.64,215.43L336.6,216.77L336.3,217.59L337.73,219.03L336.86,220.17L337.03,221.87L338.69,223.68L338.69,223.68L337.95,224.44L336.13,223.9L334.39,225.18L333.72,224.72L333.33,225.53L334.45,226.65L334.45,226.65L331.65,228.23L328.52,225.57L328.22,228.27L325.88,228.89L325.4,227.32L323.67,226.46L323.75,225.42L321.52,223.52L318.54,223.75L316.32,221.21L313.59,222.69L310.17,220.02L308.06,220.56L308.06,220.56L308.15,219.29L306.58,217L302.81,217.56L298.51,216.99L296.67,218.31L295.71,218.2L295.53,216.9L292.59,217.21L292.29,216.15L291.81,218.23L289.6,219.56L287.38,218.09L286.27,213.61L282.82,212.07L280.65,214.08L281.58,213.09L279.38,211.39L280.31,209.69L278.48,208.25L281.19,204.65L280.81,203.19L278.35,201.38L279.69,200.08L280.1,197.8L278.28,198.27L278.28,198.27L277.9,195.49L279.41,195.32L279.3,194.44L281.33,195.27L281.53,194.45L282.4,194.54L282.57,192.82L284.01,192.41L284.46,193.26L285.22,192.35L287.55,193.22L289.74,192.39L289.93,191.57L291.04,192.25L293.28,191.09L294.79,188.09L294.14,187.24L294.96,186.38L296.98,186.41L296.03,185.07L296.69,184.63L296.95,185.29L297.28,184.54L296.56,181.91z" />
      </a>

    </g>
  </svg>

</div>

在示例中,我已将文本附加到 svg 元素,但您可以选择为文本创建不同的组或将其附加到 <a> 父元素。