【问题标题】:How to draw a line along the bounding box of a text segment?如何沿着文本段的边界框画一条线?
【发布时间】:2019-09-18 04:30:10
【问题描述】:

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 上下文中,这既是因为它们被 filter+fill 使用,又因为它们可以被 javascript 查询。真的不能用于“中风”吗?

【问题讨论】:

  • 在javascript中你可以使用'.getBBox()'方法来获取边界框的位置(x,y)和大小(宽度,高度),你可以使用所有这些来绘制文本周围的矩形。
  • 是的,但问题显然与 javascript 无关,也与 DOM 方法无关。目标是生成静态 svg 文档,例如用于发布或包含在文字处理文档中。
  • @Ethan 你能包含你的 gnuplot 代码吗?我以前从未使用过 gnuplot,但在 gnuplot 5.2 版中,文本框具有设置边框的样式。也许这就是你可以使用的。它在gnuplot 5.2 manual的第175页上进行了描述
  • 您是否还打算使用 gnuplot 创建一个围绕它的线的 svg 或编写进入 gnuplot 本身的代码以便它可以支持该功能?我开始认为你的意思是后者,因为我重读了你的陈述,但我写了我之前的评论,好像你的意思是前者。
  • @约翰。我是为文本框添加 gnuplot 支持的人,但我无法在所有终端上都这样做。在尚不支持它的终端类型中,恕我直言 SVG 是最重要的,其次是 EMF。

标签: svg gnuplot svg-filters


【解决方案1】:

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

我还更改了行以在文本周围留出一些边距:

&lt;filter id='textbox' filterUnits='objectBoundingBox' x='-0.1' y='-0.1' height='1.2' width='1.2'&gt;

如果您调整数字,您的文本周围可能会出现清晰的边框。 不能保证这是有效的 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>

结果:

【讨论】:

    【解决方案2】:

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

    <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>

    【讨论】:

      【解决方案3】:

      我不知道文本标签大小的范围。这会放置一个过滤器,使用过滤器区域尺寸在父 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>

      【讨论】:

        猜你喜欢
        • 2020-09-20
        • 1970-01-01
        • 1970-01-01
        • 2015-03-17
        • 2020-10-12
        • 2017-03-25
        • 1970-01-01
        • 1970-01-01
        • 2013-10-08
        相关资源
        最近更新 更多