如何在不缩放字体的情况下缩放SVG坐标系?

时间:2019-03-11 19:53:04

标签: html svg

我正在像这样进行数据可视化:

enter image description here

,使用viewBox缩放SVG以便将图形的宽度缩放为数据范围的宽度将很方便。

在此示例中,我的数据点为12,549,因此我希望范围从0到14,000,并使用宽度为12,549的viewBox在宽度为14,000的rect中进行渲染。换句话说,要对我的数据使用自然单位。

但是,当我这样做时,轴上的字体也会缩放 ,并且10px字体也会缩放,并且变得太小以至于无法看到。

所以我需要的是在不缩放字体单位的情况下缩放图形单位的方法,但是我看不到这样做的方法。

更新

这是有问题的代码:

<svg width="960" height="50" class="bullet2" style="margin-top: 10px;">
  <svg viewBox="0 0 14000 25" preserveAspectRatio="none" width="100%" height="25" class="bars">
<rect x="0" y="0" width="14000" height="25" class="background"/>
<rect x="0" y="0" height="12.5" width="12549" class="item player"/>
<rect x="0" y="12.5" height="12.5" width="3750" class="item team-average"/>
<line x1="2000" x2="2000" y1="0" y2="25" class="marker" style="stroke-width: 29.1667px;"/>
  </svg>
  <g class="axis">
<g transform="translate(0, 25)" class="tick" style="opacity: 1;">
  <line y1="0" y2="5"/>
  <text text-anchor="middle" dy="1em" y="6">0</text>
</g>
<g transform="translate(140, 25)" class="tick" style="opacity: 1;">
  <line y1="0" y2="5"/>
  <text text-anchor="middle" dy="1em" y="6">2000</text>
</g>
<g transform="translate(280, 25)" class="tick" style="opacity: 1;">
  <line y1="0" y2="5"/>
  <text text-anchor="middle" dy="1em" y="6">4000</text>
</g>
<g transform="translate(420, 25)" class="tick" style="opacity: 1;">
  <line y1="0" y2="5"/>
  <text text-anchor="middle" dy="1em" y="6">6000</text>
</g>
<g transform="translate(560, 25)" class="tick" style="opacity: 1;">
  <line y1="0" y2="5"/>
  <text text-anchor="middle" dy="1em" y="6">8000</text>
</g>
<g transform="translate(700, 25)" class="tick" style="opacity: 1;">
  <line y1="0" y2="5"/>
  <text text-anchor="middle" dy="1em" y="6">10000</text>
</g>
<g transform="translate(840, 25)" class="tick" style="opacity: 1;">
  <line y1="0" y2="5"/>
  <text text-anchor="middle" dy="1em" y="6">12000</text>
</g>
<g transform="translate(980, 25)" class="tick" style="opacity: 1;">
  <line y1="0" y2="5"/>
  <text text-anchor="middle" dy="1em" y="6">14000</text>
</g>
  </g>
</svg>

请注意,内部viewBox元素上的svg按比例缩放。我在外部svg元素(也包括轴)上以相同的比例进行了尝试,但是当我这样做时,图像看起来像这样:

enter image description here

轴标签在那里,但是它们也被缩放,在14000像素缩放比例中,10px字体很小,以至于看不到。

2 个答案:

答案 0 :(得分:1)

这是我对您问题的解决方案。我建议阅读有关SVGPointcreateSVGPoint的内容。我认为本书中的信息特别有用:Using SVG with CSS3 and HTML5: Vector Graphics for Web Design

function init(){
  // a function called on resize
  // the function get the new font-size and set the new value of the "font-size"
  let fontSize = 25;
  let newSize = getValue(fontSize);
  // reset the font size
  theText.setAttributeNS(null,"font-size",newSize.x)
}


setTimeout(function() {
		init();
		addEventListener('resize', init, false);
}, 15);


// a function used to recalculate the font size on resize
function getValue(size){
var p = svg.createSVGPoint();
p.x = size;
p.y = 0;
p = p.matrixTransform(svg.getScreenCTM().inverse());
return p
}
svg{border:1px solid;}
<svg id="svg" viewBox="0 0 1000 100">
  <line x1="50" x2="950" y1="50" y2="50" stroke-width="20" stroke="skyblue" />
  
  <line x1="500" x2="500" y1="30" y2="70" stroke-width="1" stroke="#999" />
  <text id="theText"  dominant-baseline="middle" text-anchor="middle" x="500" y="85" font-size="16" >middle</text>
</svg>

更新

  

您能解释一下该解决方案如何工作吗?

代码中有注释。我还在Using SVG with CSS3 and HTML5: Vector Graphics for Web Design中加了引号:

  

每个可以进行转换[....]的SVG元素都有一个getScreenCTM()方法。 CMT代表累积转换矩阵。屏幕CMT [...]定义了如何将元素坐标系中的点转换回文档窗口的原始,未缩放,未转换的坐标系。它包括对该元素及其祖先的转换以及viewBox缩放。

我希望这是有用的。但是我认为您需要阅读本书的第18章以完全理解代码。

答案 1 :(得分:0)

  

请输入Minimal, Complete, and Verifiable example

有两种方法可以解决模糊/一般的缩放问题:

  • 1)将缩放后的SVG放入容器SVG中吗?堆叠;绝对不要缩放容纳字体的容器相对于其中的 child SVG的百分比。

  • 2)states here可以使用绝对px或相对em单位缩放字体。请参阅here for valid length

    我看不到是否可以设置rem单位,但是如果可以,请尝试设置是否有效?

(我经常在SVG和CSS上使用SVG,因此我的建议中可能会有空白)