【问题标题】:SVG: fixed font sizeSVG:固定字体大小
【发布时间】:2020-08-01 01:33:02
【问题描述】:

我有一个内联到 html 代码的 SVG。它被缩放以适应宽度并保持纵横比。有没有办法将字体大小设置为固定到可以通过媒体查询控制的视口?

编辑: 问题是当我在宽度范围内设置固定字体大小时,无论如何都会相对于 svg 大小调整字体大小。

#svg-container {
  width: 100%;
  padding-bottom: 70%;
  overflow: hidden;
  border: 1px solid red;
}

#svg-container svg text tspan {
  font-size: 14px;
}


@media (min-height: 800px) {
  #svg-container svg text tspan {
    font-size: 50px;
  }
}
<div id="svg-container">
<svg
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:cc="http://creativecommons.org/ns#"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:svg="http://www.w3.org/2000/svg"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
   version="1.1"
   viewBox="0 0 500 350"
   data-name="Layer 1"
   id="Layer_1"
   inkscape:version="0.91 r13725"
   sodipodi:docname="Desktop_Enhanced.svg"
   width="100%"
   style="position: absolute; left: 0; top: 0;"   
  >
  <sodipodi:namedview
     pagecolor="#ffffff"
     bordercolor="#666666"
     borderopacity="1"
     objecttolerance="10"
     gridtolerance="10"
     guidetolerance="10"
     inkscape:pageopacity="0"
     inkscape:pageshadow="2"
     inkscape:window-width="1280"
     inkscape:window-height="961"
     id="namedview51"
     showgrid="false"
     inkscape:zoom="1.0054235"
     inkscape:cx="231.42799"
     inkscape:cy="361.93137"
     inkscape:window-x="1272"
     inkscape:window-y="-8"
     inkscape:window-maximized="1"
     inkscape:current-layer="Layer_1"
     fit-margin-bottom="150" />
  <metadata
     id="metadata75">
    <rdf:RDF>
      <cc:Work
         rdf:about="">
        <dc:format>image/svg+xml</dc:format>
        <dc:type
           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
        <dc:title>Desktop</dc:title>
      </cc:Work>
    </rdf:RDF>
  </metadata>
  <defs
     id="defs3">
    <style
       id="style5">.cls-1{fill:#da1f26;}.cls-2{fill:#252e43;}.cls-3{fill:#d1d3d4;}</style>
  </defs>
  <title
     id="title7">Desktop</title>
  <polyline
     id="polyline9"
     points="329.4 62.24 343.54 76.39 329.4 90.53"
     class="cls-1"
     style="fill:#da1f26"
     transform="translate(59.579252,-43.513817)" />
  <polyline
     id="polyline11"
     points="333.56 328.83 347.7 342.97 333.56 357.11"
     class="cls-2"
     style="fill:#252e43"
     transform="translate(59.579252,-43.513817)" />
  <path
     id="path35"
     d="m 394.84925,294.48618 -25,0 c -57.81,0 -77.28,-34.66 -96.1,-68.18 -15.35,-27.34 -29.86,-53.16 -63.9,-53.16 l -31.27,0 0,10 31.3,0 c 28.19,0 40.7,22.27 55.18,48.06 9.68,17.23 19.69,35.06 35.5,49.13 18.26,16.22 40.93,24.15 69.33,24.15 l 25,0 z"
     class="cls-2"
     inkscape:connector-curvature="0"
     style="fill:#252e43" />
  <path
     id="path43"
     d="m 390.97925,27.876183 -21.09,0 c -28.4,0 -51.07,7.9 -69.32,24.15 -15.81,14.08 -25.82,31.9 -35.5,49.129997 -14.48,25.79 -27,48.06 -55.18,48.06 l -31.31,0 0,10 31.3,0 c 34,0 48.54,-25.82 63.9,-53.16 18.8,-33.569997 38.3,-68.179997 96.11,-68.179997 l 21.09,0 z"
     class="cls-1"
     inkscape:connector-curvature="0"
     style="fill:#da1f26" />
  <path
     id="path45"
     d="m 429.38925,17.956183 a 14.92,14.92 0 1 0 14.92,14.92 14.92,14.92 0 0 0 -14.92,-14.92 z m 0,21 a 6.08,6.08 0 1 1 6.08,-6.08 6.08,6.08 0 0 1 -6.08,6.08 z"
     class="cls-1"
     inkscape:connector-curvature="0"
     style="fill:#da1f26" />
  <path
     id="path47"
     d="m 433.38925,284.53618 a 14.92,14.92 0 1 0 14.92,14.95 14.92,14.92 0 0 0 -14.92,-14.95 z m 0,21 a 6.08,6.08 0 1 1 6.09,-6.05 6.08,6.08 0 0 1 -6.09,6.05 z"
     class="cls-2"
     inkscape:connector-curvature="0"
     style="fill:#252e43" />
  <flowRoot
     style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
     id="flowRoot4236"
     xml:space="preserve"
     transform="translate(0,-72.53)"><flowRegion
       id="flowRegion4238"><rect
         y="179.54243"
         x="18.988897"
         height="58.373276"
         width="94.241196"
         id="rect4240" /></flowRegion><flowPara
       id="flowPara4242">ZakładaZ</flowPara></flowRoot>  <text
     x="27.791037"
     y="169.90349"
     font-size="20px"
     id="text49-1"
     style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:15px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Bold';text-align:start;writing-mode:lr-tb;text-anchor:start;fill:#252e43;fill-opacity:1"
     sodipodi:linespacing="125%">
    <tspan
       sodipodi:role="line"
       id="tspan4528"
       x="27.791037"
       y="169.90349">PLEASE CHOOSE</tspan>
  </text>
</svg>


</div>

【问题讨论】:

    标签: html css svg


    【解决方案1】:

    简短的回答是否定的。

    如果文本位于带有viewBox 的 SVG 中,并且 SVG 被缩放,其内容也会被缩放。无法使文本具有不受 SVG 缩放影响的“全局”大小。

    唯一可能的解决方案是使用 Javascript 计算缩放因子,并在每次 SVG 大小更改时动态更新字体大小。

    【讨论】:

    • 这个答案不是 100% 正确的。您可以计算 svg 的当前缩放因子,例如,请参阅此 SO 答案:stackoverflow.com/questions/52576376/… 如果您知道缩放因子,您现在可以设置相对文本的字体大小属性。我在 Angular 中这样做:[attr.font-size]="15 / scale"
    【解决方案2】:

    最后……

    我已经从 svg 中删除了文本,并在共享的 html 容器中添加了绝对定位的 div 文本块。那行得通。 Div 的外观由带有媒体查询的 css 控制 - 它独立于 svg 缩放。

    您可以在https://www.xtech.pl/jak-to-dziala-dla-dostawcy 看到实际的图表(向下滚动到页面的第二部分,然后您可以调整屏幕大小以查看其工作原理)。

    【讨论】:

      【解决方案3】:

      我建议使用嵌套的 SVG 标签。您可以保留最外层的 SVG 而不使用 viewBox,并在此标记下添加所有文本,同时添加第二个 SVG 以覆盖整个区域但使用 viewBox。

      您需要将文本的位置从绝对值更改为相对值,但效果很好。

      这样您的文本将随着 svg 大小而改变位置,但不会缩放文本。不过,内部 SVG 会,因为您设置了一个 viewBox。

      示例:JS 用于变量容器,SVG 总是填充 div。 缩放是纯 SVG。

      function changeCircleDiv(element) {
        s = document.getElementById("container").style;
        s.width=element.value + 'px';
        s.height = s.width;
      }
      body {
        font-size: 2em;
      }
      <input type="number" onchange="changeCircleDiv(this);" value="100"></input>
      <div id="container" style="width: 100px; height: 100px;">
          <svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100%" height="100%">
              <svg width="100%" height="100%" viewBox="0 0 20 20">
                  <circle cx="10" cy="10" r="8" stroke="black" fill="none"/>
              </svg>
            <text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle">Center</svg>
          </svg>
      </div>

      【讨论】:

      • 你能举个例子吗?
      • 已编辑。如果有帮助,请告诉我。
      • 天哪,我才意识到这个问题是三年前提出的。
      【解决方案4】:

      您可以通过“带有粘性文本的响应式 SVG”来做到这一点 见这里:https://bl.ocks.org/veltman/5cd1ba0b3c623e7b5146

      或者...如果您想在 SVG 中使用媒体查询字体,答案是肯定的。运行这段代码sn-p。

      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100%" height="200px">
        <style>
          text {
            font-size: 10px;
          }
      
          @media (max-width: 600px) {
            text {
              font-size: 20px;
            }
          }
      
          @media (max-width: 800px) {
            text {
              font-size: 16px;
            }
          }
      
        </style>
        <circle cx="50" cy="50" r="50" fill="orange"/>
        <text x="50" y="60" text-anchor="middle">Testing</text>
      </svg>

      【讨论】:

      • 似乎是一个合理的解决方案,类似于任何类型的响应式设计调整...
      【解决方案5】:

      我实际上找到了一个相对简单的解决方法。

      使用 D3 的 scaleSqrt(),您可以根据 svg 占用的像素宽度进行一些数学运算。

      例如,如果svg viewbox的宽度是800,那么当svg的宽度为800px时,比例为1。当svg的像素宽度为400px时,相对于view box,那就是比例1/2

      scaleRatio = d3.scaleSqrt()
          .domain([1600, 800, 600, 400, 200, 100])
          .range([0.5, 1, 1.5, 2, 4, 8]);
      const svgWidth = d3.select(svg).node().getBoundingClientRect().width;
      someD3Element.attr('transform', `scale(${scaleRatio(svgWidth)})`);
      

      【讨论】:

      • 有点复杂,需要额外的javascript参考。
      • 抱歉,我想“简单”是主观的。额外的 JS 引用是什么意思?
      • 我假设你必须参考 d3?不是吗?
      • 也许可以使用这个地图函数代替 d3.scalesqrt 但我还没有测试过。函数映射(x,in_min,in_max,out_min,out_max){ return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; }
      猜你喜欢
      • 2013-08-23
      • 1970-01-01
      • 1970-01-01
      • 2021-12-16
      • 2015-12-20
      • 2020-09-21
      • 2013-07-13
      • 2014-08-27
      • 1970-01-01
      相关资源
      最近更新 更多