将文本插入SVG路径

时间:2022-11-19 13:34:35

I have an SVG path that draws the outline of a jersey, and I want to center players' last names within that jersey. Also, since I'll be putting names of varying length into the jersey, I wanted to make the size of the text dynamically scale to fit the jersey.

我有一个SVG的路径,它绘制了一个jersey的轮廓,我想要把玩家的姓氏放在那个jersey里面。另外,由于我将把不同长度的名称放入jersey中,所以我想动态地调整文本大小以适应jersey。

I was able to center the text with some math involving getBoundingClientRect(), but I'm struggling with the dynamic sizing of the text. It looks fine at first, but then when I resize the screen, the text size does not remain proportional to the size of jersey.

我能够用一些涉及getBoundingClientRect()的数学方法将文本居中,但我正在努力实现文本的动态大小调整。一开始看起来不错,但当我调整屏幕大小时,文本大小与泽西的大小并不成比例。

I've included a code snippet below to demonstrate. Please help me understand why this sizing issue is occurring, and what I can do to achieve the proper text resizing.

我在下面包含了一个代码片段来演示。请帮助我理解为什么会出现这种大小问题,以及我可以做什么来实现适当的文本大小调整。

EDIT: I now have enough reputation points to add images (woo!), so here are some pictures to demonstrate the resizing problem I'm referring to. The text does not scale proportionally with the jersey size when I zoom in/out. BUT, if I refresh the page after I zoom in/out, i.e. so that I start out with the zoomed-in/out version, the text size readjusts to the current jersey size and fits the jersey as desired.

编辑:我现在有足够的声望点来添加图片(woo!),所以这里有一些图片来展示我所提到的缩放问题。当我放大/输出时,文本不会按比例缩放。但是,如果我在放大/缩小后刷新页面,也就是说,我从缩小/缩小版本开始,文本大小调整到当前的泽西大小,并根据需要适合泽西大小。

将文本插入SVG路径将文本插入SVG路径将文本插入SVG路径

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>Jersey</title>
</head>

<body>
  <svg id="jersey">
    <switch>
      <g>
        <g id="jerseyShape">
          <path id="outline" fill="green" transform="translate(-40,0)" opacity="0.35" fill="none" stroke="#000000" stroke-width="1.5" d="M116.462,113.911V39.01
                           c0,0-18.493-5.977-15.317-30.633c0,0-8.033-2.616-8.78-3.363S91.617,9.311,79.29,9.124h-1.305
                           C65.656,9.311,65.656,4.268,64.909,5.015s-8.778,3.363-8.778,3.363C59.305,33.034,40.813,39.01,40.813,39.01v74.901
                           C40.813,113.911,74.434,126.427,116.462,113.911z" />
        </g>
        <g id="jerseyContent">
          <svg>
            <text id="name" font-family="Verdana" text-anchor="middle" dominant-baseline="central">
              Jordan
            </text>
            <!-- Dynamically re-size name to fit jersey -->
            <script type="application/ecmascript">
              //Get path's bounding rectangle
              var pathNode = document.getElementById("outline");
              var pRect = pathNode.getBoundingClientRect();

              //Get text's bounding rectangle
              var textNode = document.getElementById("name");
              var tRect = textNode.getBBox();

              //Calculate the necessary scale to make the text fit within the jersey width while
              //not exceeding a height of 30
              var widthRatio = (pRect.width * 0.85) / tRect.width;
              var heightRatio = (pRect.height*0.3) / tRect.height;
              var textScale = Math.min(widthRatio, heightRatio);

              //Translate text to center of jersey and scale to fit
              textNode.setAttribute("transform", "translate(" + (1 + pRect.width / 2) + " " + (pRect.top + pRect.height / 2) + ")scale(" + textScale + ")");
            </script>
          </svg>
        </g>
      </g>
    </switch>
  </svg>
</body>

</html>

2 个解决方案

#1


1  

You should also use getBBox() fo get the size of the path as well. That way, the dimensions will be in the same coordinate space even after scaling.

您还应该使用getBBox()来获取路径的大小。这样,即使在缩放之后,维度也会在相同的坐标空间中。

#2


0  

The problem is because you are calculating the scale on the group which contains the textnode.

问题在于,您正在计算包含textnode的组上的比例。

I have solved you problem by giving the scale on the whole g element with id= "full"

我用id= "full"给出了整个g元素的比例

So now you can change the scale value on id="full" and get desired result without the label going out. I have updated the code such that it takes into account the scale value on zoom in zoom out (ctrl +/ ctrl -)

现在,您可以更改id="full"上的标度值,并得到所需的结果,而无需标记。我已经更新了代码,使它考虑缩放的缩放值(ctrl +/ ctrl -)

$(window).on("resize", function(){ 
  var scale = "scale("+window.devicePixelRatio+")"
  $("#full").attr("transform", scale)
  console.log($("#full").attr("transform"));
  
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="utf-8">
      <title>Jersey</title>
    </head>
    
    <body style="width:100%; height:100%">
      <svg style="    height: 602px;    width: 100%;">
          <g id="full" transform="scale(1)">
            <g id="jerseyShape" transform="translate(-40,0)">
              <path id="outline" fill="green" opacity="0.35" fill="none" stroke="#000000" stroke-width="1.5" d="M116.462,113.911V39.01
                               c0,0-18.493-5.977-15.317-30.633c0,0-8.033-2.616-8.78-3.363S91.617,9.311,79.29,9.124h-1.305
                               C65.656,9.311,65.656,4.268,64.909,5.015s-8.778,3.363-8.778,3.363C59.305,33.034,40.813,39.01,40.813,39.01v74.901
                               C40.813,113.911,74.434,126.427,116.462,113.911z" />
                <text id="name" transform="translate(80,80)" font-family="Verdana" text-anchor="middle" dominant-baseline="central">
                  Jordan
                </text>                           
            </g>
          </g>
      </svg>
    </body>
    
    </html>

#1


1  

You should also use getBBox() fo get the size of the path as well. That way, the dimensions will be in the same coordinate space even after scaling.

您还应该使用getBBox()来获取路径的大小。这样,即使在缩放之后,维度也会在相同的坐标空间中。

#2


0  

The problem is because you are calculating the scale on the group which contains the textnode.

问题在于,您正在计算包含textnode的组上的比例。

I have solved you problem by giving the scale on the whole g element with id= "full"

我用id= "full"给出了整个g元素的比例

So now you can change the scale value on id="full" and get desired result without the label going out. I have updated the code such that it takes into account the scale value on zoom in zoom out (ctrl +/ ctrl -)

现在,您可以更改id="full"上的标度值,并得到所需的结果,而无需标记。我已经更新了代码,使它考虑缩放的缩放值(ctrl +/ ctrl -)

$(window).on("resize", function(){ 
  var scale = "scale("+window.devicePixelRatio+")"
  $("#full").attr("transform", scale)
  console.log($("#full").attr("transform"));
  
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="utf-8">
      <title>Jersey</title>
    </head>
    
    <body style="width:100%; height:100%">
      <svg style="    height: 602px;    width: 100%;">
          <g id="full" transform="scale(1)">
            <g id="jerseyShape" transform="translate(-40,0)">
              <path id="outline" fill="green" opacity="0.35" fill="none" stroke="#000000" stroke-width="1.5" d="M116.462,113.911V39.01
                               c0,0-18.493-5.977-15.317-30.633c0,0-8.033-2.616-8.78-3.363S91.617,9.311,79.29,9.124h-1.305
                               C65.656,9.311,65.656,4.268,64.909,5.015s-8.778,3.363-8.778,3.363C59.305,33.034,40.813,39.01,40.813,39.01v74.901
                               C40.813,113.911,74.434,126.427,116.462,113.911z" />
                <text id="name" transform="translate(80,80)" font-family="Verdana" text-anchor="middle" dominant-baseline="central">
                  Jordan
                </text>                           
            </g>
          </g>
      </svg>
    </body>
    
    </html>