如何沿着文本段的边界框画一条线?

时间:2019-09-18 04:30:10

标签: svg gnuplot svg-filters

Gnuplot支持“装箱的文本”属性,该属性在文本标签周围绘制带有可选填充的框。由于gnuplot对字体基本上一无所知,因此它依赖于设备特定的代码来生成适当的框。大多数gnuplot输出设备都实现了此功能,但是我不知道如何为svg输出支持此功能。特别是,我知道如何使用过滤器在文本周围生成一个实心填充框(请参见下面的示例),但是我不知道如何在同一框周围画一条线。

这是gnuplot输出的svg的一部分,以及截取的渲染svg图像的屏幕截图以及其他gnuplot输出设备输出的所需结果。

请注意,我 不是 询问如何获取和修改javascript中的边界框。我要求生成本机的svg文档。

<svg 
 width="600" height="480"
 viewBox="0 0 600 480"
 xmlns="http://www.w3.org/2000/svg"
 xmlns:xlink="http://www.w3.org/1999/xlink"
>
<rect x="0" y="0" width="600" height="480" fill="none"/>
<defs>

        <filter id='textbox' filterUnits='objectBoundingBox' x='0' y='0' height='1' width='1'>
          <feFlood flood-color='cyan' flood-opacity='1' result='bgnd'/>
          <feComposite in='SourceGraphic' in2='bgnd' operator='atop'/>
        </filter>
</defs>

<g id="textbox 1">
        <g transform="translate(297.9,244.6)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="start" style='filter:url(#textbox)'>
                <text><tspan font-family="Arial" >A two-line label</tspan>
                      <tspan x="0" dy="12" font-family="Arial" > in a box </tspan></text>
        </g>
</g>
</svg>

svg output png output

更新

到目前为止,提出的三个答案是基于使用filter + fill操作,实际上是将一个稍大的矩形放在一个稍小的矩形周围。这与画线不同。它不容易缩放,并且所得外观与同一图中其他线条的外观不匹配。我确实想要某种方法来为组或文本边界框发出“笔触”而不是“填充”操作。这样可以匹配图中其他线条的连接,粗细和其他属性。

边界框坐标显然在svg上下文中是隐式的,这既是因为它们由filter + fill使用,也可以由javascript查询。真的可以将它们用于“中风”吗?

3 个答案:

答案 0 :(得分:1)

我没有成为SVG专家,而是与Inkscape和您的SVG一起玩。似乎没有简单的框架命令(至少我没有找到),但是可以将一些高斯模糊滤镜效果应用于文本框。我假设您可以将id="filter1780"重命名为其他名称。

我还更改了该行以使文本周围有一些空白:

<filter id='textbox' filterUnits='objectBoundingBox' x='-0.1' y='-0.1' height='1.2' width='1.2'>

如果修改数字,则最终可能会在文本周围出现清晰的边框。 无法保证这是有效的SVG,它看起来像一个丑陋且冗长的解决方法,但至少看起来像您想要的目标。

SVG代码:

<svg 
 width="600" height="480"
 viewBox="0 0 600 480"
 xmlns="http://www.w3.org/2000/svg"
 xmlns:xlink="http://www.w3.org/1999/xlink"
>
<rect x="0" y="0" width="600" height="480" fill="none"/>
<defs>

    <filter id='textbox' filterUnits='objectBoundingBox' x='-0.1' y='-0.1' height='1.2' width='1.2'>
      <feFlood flood-color='cyan' flood-opacity='1' result='bgnd'/>
      <feComposite in='SourceGraphic' in2='bgnd' operator='atop'/>
    </filter>

    <filter id="filter1780" x="-.2" y="-.2" width="1.4" height="1.4" color-interpolation-filters="sRGB">
      <feGaussianBlur in="SourceAlpha" result="blur1" stdDeviation="0.33"/>
      <feComposite in="SourceGraphic" in2="blur1" operator="out" result="composite1"/>
      <feColorMatrix result="colormatrix1" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 100 -0 "/>
      <feGaussianBlur result="blur2" stdDeviation="0.01"/>
      <feComposite in="blur2" in2="blur2" result="composite2"/>
      <feColorMatrix result="colormatrix2" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 100 -0 "/>
      <feGaussianBlur result="blur3" stdDeviation="0.01"/>
      <feColorMatrix result="colormatrix3" values="1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 5 -1 "/>
      <feFlood flood-color="rgb(0,0,0)" result="flood"/>
      <feComposite in="flood" in2="colormatrix3" k2="1" operator="in" result="composite3"/>
      <feComposite in="SourceGraphic" in2="colormatrix3" operator="out" result="composite4"/>
      <feComposite in="composite4" in2="composite3" k2="1" k3="1" operator="arithmetic" result="composite5"/>
    </filter>

</defs>

<g id="textbox 1">
    <g filter="url(#filter1780)">
        <g transform="translate(297.9,244.6)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="start" style='filter:url(#textbox)'>
            <text><tspan font-family="Arial" >A two-line label</tspan>
                  <tspan x="0" dy="12" font-family="Arial" > in a box </tspan></text>
        </g>
    </g>
</g>
</svg>

结果:

enter image description here

答案 1 :(得分:1)

一个稍微简单的解决方案:

<svg 
 width="600" height="480"
 viewBox="0 0 600 480"
 xmlns="http://www.w3.org/2000/svg"
 xmlns:xlink="http://www.w3.org/1999/xlink"
>
<rect x="0" y="0" width="600" height="480" fill="none"/>
<defs>

        <filter id='textbox' filterUnits='objectBoundingBox' x='-0.1' y='-0.1' height='1.2' width='1.2'>
          <feFlood flood-color='red' flood-opacity='1' result='fg'/>
          <feFlood flood-color='cyan' flood-opacity='1' result='bgnd'/>
          <feOffset in="bgnd" dx="2" dy="2" result="disp1" />
          <feOffset in="bgnd" dx="-2" dy="-2" result="disp2" />
          <feComposite in='disp2' in2='disp1' operator='in' result="crop" />
          <feComposite in='crop' in2='fg' operator='atop' result="op1" />
          <feComposite in='SourceGraphic' in2='op1' operator='atop' result="op2" />
        </filter>
</defs>

<g id="textbox 1">
        <g transform="translate(297.9,244.6)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="start" style='filter:url(#textbox)'>
                <text><tspan font-family="Arial" >A two-line label</tspan>
                      <tspan x="0" dy="12" font-family="Arial" > in a box </tspan></text>
        </g>
</g>
</svg>

答案 2 :(得分:1)

我不知道文本标签大小的范围。这样,滤镜会使用滤镜区域尺寸在父级g上添加较大的背景-但这些尺寸与标签尺寸有关-因此它不适用于所有宽高比。

<svg 
 width="600" height="480"
 viewBox="0 0 600 480"
 xmlns="http://www.w3.org/2000/svg"
 xmlns:xlink="http://www.w3.org/1999/xlink"
>
<rect x="0" y="0" width="600" height="480" fill="none"/>
<defs>
  
          <filter id='outline' filterUnits='objectBoundingBox' x='-.02' y='-0.06' height='1.12' width='1.04'>
          <feFlood flood-color='black' flood-opacity='1' result='bgnd'/>
          <feComposite in='SourceGraphic' in2='bgnd' operator='over'/>
        </filter>

        <filter id='textbox' filterUnits='objectBoundingBox' x='0' y='0' height='1' width='1'>
          <feFlood flood-color='cyan' flood-opacity='1' result='bgnd'/>
          <feComposite in='SourceGraphic' in2='bgnd' operator='atop'/>
        </filter>
</defs>

<g id="textbox 1" filter="url(#outline)">
        <g transform="translate(297.9,244.6)" stroke="none" fill="black" font-family="Arial" font-size="12.00"  text-anchor="start" style='filter:url(#textbox)'>
                <text><tspan font-family="Arial" >A two-line label</tspan>
                      <tspan x="0" dy="12" font-family="Arial" > in a box </tspan></text>
        </g>
</g>
</svg>