【问题标题】:DRY for sub-paths in SVGDRY 用于 SVG 中的子路径
【发布时间】:2020-11-10 20:56:48
【问题描述】:

在 SVG 中是否有办法重用 <path> 的一部分,同时保持 <path> 的其他部分完好无损?

我正在尝试构建一个静态 SVG 文件(不允许使用 HTML 或 JS,尽管可以利用外部 CSS),它有 20 多个可变宽度水平花括号实例,如下所示:

所有实例的高度相同,但宽度不同,这意味着弧 (a) 相同,但每个实例的初始位置和水平线 (h) 将不同。这也意味着我不能使用<use> 然后水平缩放每个实例,因为缩放会导致看起来很糟糕的延伸弧。 (顺便说一句,在研究这个时我了解到vector-effect="non-scaling-stroke",如果不涉及曲线,如果与<use> 结合使用将是一个完美的解决方案。)

我知道我可以使用<use> 并覆盖每个属性中的d 属性,但是有没有比克隆相同的d 属性20 多次并编辑每个属性中的h 值更好的方法?一个理想的解决方案是能够重用子路径,例如d="${left} h 100 ${middle} h 100 ${left}" 如果允许 JS,我可以轻松做到这一点,但可惜我不能在这种情况下使用脚本。

有没有办法做类似下面的事情(在 SVG 中;我知道我可以在 HTML 中做到这一点),其中每个路径都在最后一个结束的地方拾取?

<use href="#left">
<path d="h 200">
<use href="#mid">
<path d="h 200">
<use href="#right">

如果没有,还有其他方法可以做我正在寻找的吗?

这是我现在拥有的 SVG:(https://codepen.io/justingrant/pen/rNLqQRo)

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 3000 500" width="3000" height="500" fill="none" stroke-width="5" stroke="green" >
  <path d="m 80,80 
           a 30 30 0 0 1 30,-30
           h 100
           a 30 30 0 0 0 30,-30
           a 30 30 0 0 0 30,30
           h 100 
           a 30 30 0 0 1 30,30"/>
  <path d="m 500,80 
           a 30 30 0 0 1 30,-30 
           h 40
           a 30 30 0 0 0 30,-30
           a 30 30 0 0 0 30,30
           h 40 
           a 30 30 0 0 1 30,30"/>
</svg>

我知道我可以通过构建步骤或预处理器运行原始代码,但我更喜欢原生 SVG 解决方案,然后再拼凑类似的东西。

【问题讨论】:

  • 创建一个模板,然后运行 ​​XSLT 进程(或类似进程)以在编译时而不是运行时生成您想要的所有静态文件。

标签: svg


【解决方案1】:

你想要的东西是可以通过一些技巧来实现的。但是,您需要接受始终在已知颜色的背景下绘制它。

请参见下面的示例。尝试运行它,切换到“整页”,然后更改浏览器窗口的宽度。

path {
  stroke: green;
  stroke-width: 4;
  fill: none;
}

.bg-color {
  fill: white;
}
<svg width="100%" height=="50">
  <defs>
    <g id="left">
      <rect x="0" y="0" width="27" height="50" class="bg-color"/>
      <path d="M 2 50 a 25 25 0 0 1 25 -25"/>
    </g>
    <g id="centre">
      <rect x="-25" y="0" width="50" height="50" class="bg-color"/>
      <path d="M -25 25 a 25 25 0 0 0 25 -25 a 25 25 0 0 0 25 25"/>
    </g>
    <g id="right">
      <rect x="-27" y="0" width="27" height="50" class="bg-color"/>
      <path d="M -27 25 a 25 25 0 0 1 25 25"/>
    </g>
  </defs>
  <path d="M 0 25 L 9999 25"/>
  <use xlink:href="#left" x="0" y="0"/>
  <use xlink:href="#centre" x="50%" y="0"/>
  <use xlink:href="#right" x="100%" y="0"/>
</svg>

它的工作原理是我们在 SVG 的整个宽度上画一条绿线。然后我们在两个末端形状和中心形状的顶部绘制。这三个部分必须将绿线部分隐藏在它们后面。所以它们每个都必须包含一个与背景颜色匹配的矩形。

【讨论】:

    【解决方案2】:

    此解决方案仅适用于 Chrome(不是 Firefox),并且需要一些更广泛的外部 SCSS,但我仍然想分享它,因为它是我在运行时最接近结构化解决方案的方法。

    使用 SCSS @for 为所有 10 的倍数生成 CSS 类,其中该数字表示直线部分的长度(以像素为单位)。然后,设置路径的类并使用您可以在某些前沿浏览器中set path() in CSS 的事实。

    @for $i from 1 through 20 {
      path.path-#{$i * 10} {
        d: path('m 20,80 a 30 30 0 0 1 30,-30 h #{$i * 10} a 30 30 0 0 0 30,-30 a 30 30 0 0 0 30,30 h #{$i * 10} a 30 30 0 0 1 30,30');
      }
    }
    
    <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 3000 500" width="3000" height="500" fill="none" stroke-width="5" stroke="green" >
      <path class="path-100"/>
      <path class="path-40"/>
    </svg>
    

    你可以在here看到它。

    【讨论】:

      猜你喜欢
      • 2021-07-04
      • 2012-03-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-13
      • 2016-05-13
      • 1970-01-01
      • 2021-04-13
      相关资源
      最近更新 更多