如何在SVG中绘制一部分线?

时间:2017-01-22 21:58:33

标签: svg line

是否有人知道是否/如何沿着点之间的线绘制,同时与SVG中的终点保持一定距离?

如果该行是水平的(例如从(40,40)(100,40)),您可以轻松地绘制一条与20保持距离的线,如下所示

<line x1="40" y1="40" x2="100" y2="40" desc="directional line" />
<line x1="60" y1="40" x2="80" y2="40" desc="actual part of line" />

然而,对于对角线,它有点难度。要绘制从(40,40)(100,100)的(简单)对角线,您需要cos(pi/4) = sin(pi/4) = sqrt(2)来缩放您想要远离终点的距离(在这种情况下:{{1} }})

20*sqrt(2) = 14.1

可以在此fiddle

中找到此代码的演示

因此在计算

时似乎可以这样做
  1. 方向线与水平线之间的角度
  2. 角度的正弦和余弦
  3. 您要绘制的线条实际部分的终点
  4. 这是唯一的方法,还是SVG能够指定部分线路,还是有更智能,更方便的方法吗?

2 个答案:

答案 0 :(得分:1)

我不确定这是否聪明或方便,但是没有脚本的一种方法是:

您可以使用rect作为标记(marker-start和marker-end),并将markerWidth和markerHeight属性与行的行程宽度结合使用,可以控制标记的大小。

markerWidth * stroke-width = real width

<svg width="220" height="220">
  <marker id="m1" orient="auto" viewBox="0 0 20 6" markerWidth="10" markerHeight="3" refX="20" refY="3">
    <rect x="0" y="0" width="20" height="6" fill="red" opacity="0.5" />
  </marker>
  <marker id="m2" orient="auto" viewBox="0 0 20 6" markerWidth="10" markerHeight="3" refX="0" refY="3">
    <rect x="0" y="0" width="20" height="6" fill="red" opacity="0.5" />
  </marker>

  <line id="l2" x1="20" y1="20" x2="200" y2="80" marker-end="url(#m1)" marker-start="url(#m2)" stroke="black" stroke-width="2" />

</svg>

现在想象我们使用白色矩形,然后标记将与具有固定宽度的线重叠,并且我们将具有到端点的固定距离。

但这不是我们想要的。要通过标记“切割”线条,您可以使用蒙版。因此,绘制你的线作为面具,白色笔划,但带有黑色标记。

将此蒙版应用于您的线条(不带标记)...您可以使用:具有可见笔划的线条,该线条与端点之间的距离固定。

专业人士:不涉及javascript

缺点:你必须画两次

function redraw() {
  var x1 = Math.random() * 200
  var y1 = Math.random() * 200
  var x2 = Math.random() * 200
  var y2 = Math.random() * 200

  l1.setAttribute("x1", x1)
  l1.setAttribute("y1", y1)
  l1.setAttribute("x2", x2)
  l1.setAttribute("y2", y2)

  l2.setAttribute("x1", x1)
  l2.setAttribute("y1", y1)
  l2.setAttribute("x2", x2)
  l2.setAttribute("y2", y2)

  c1.setAttribute("cx", x1)
  c1.setAttribute("cy", y1)
  c2.setAttribute("cx", x2)
  c2.setAttribute("cy", y2)
}
line {
  stroke-width: 2px
}
<svg width="220" height="220">
  <marker id="m1" orient="auto" viewBox="0 0 20 6" markerWidth="10" markerHeight="3" refX="20" refY="3">
    <rect x="0" y="0" width="20" height="6" fill="black" />
  </marker>
  <marker id="m2" orient="auto" viewBox="0 0 20 6" markerWidth="10" markerHeight="3" refX="0" refY="3">
    <rect x="0" y="0" width="20" height="6" fill="black" />
  </marker>
  <mask id="mask">
    <line id="l2" x1="20" y1="20" x2="200" y2="80" marker-end="url(#m1)" marker-start="url(#m2)" stroke="white" />
  </mask>
  <circle id="c1" cx="200" cy="80" r="5" fill="blue" />
  <circle id="c2" cx="20" cy="20" r="5" fill="blue" />
  <line id="l1" x1="20" y1="20" x2="200" y2="80" mask="url(#mask)" stroke="black" />
</svg>

<button onclick="redraw()">redraw</button>

答案 1 :(得分:0)

一旦hacky方式做到这一点是作弊与圆形图案缩放到你的线的大小。不完美但取决于您的使用案例:

<svg width="200" height="200" viewbox="0 0 200 200">
  <defs>
    <pattern id="patt" width="1" height="1" patternContentUnits="objectBoundingBox">
      <rect x="0" y="0" width="1" height="1" fill="cyan" />
      <circle cx=".5" cy=".5" r=".4" fill="blue" />
    </pattern>
  </defs>
  
  <g id="hand-drawn">
    <line x1="40" y1="40" x2="100" y2="100" stroke="red" stroke-width="2" />
    <line x1="54.1" y1="54.1" x2="85.9" y2="85.9" stroke="green" stroke-width="2" />
  </g>
  
  <g id="circle-pattern">
    <line x1="80" y1="60" x2="200" y2="100" stroke="url(#patt)" stroke-width="2" />
    <line x1="150" y1="10" x2="100" y2="120" stroke="url(#patt)" stroke-width="2" />
    <line x1="0" y1="100" x2="150" y2="100" stroke="url(#patt)" stroke-width="2" />
    <line x1="0" y1="100" x2="150" y2="101" stroke="url(#patt)" stroke-width="2" />
  <g>
</svg>

当然,这只能让您通过两端显示一条特定%的线,而不是精确的像素值。希望这会给你一些想法。

请注意,这有点儿错误 - 它不适用于水平或垂直线......您必须将它们渲染为矩形或路径,并使用填充而不是笔划。