简体   繁体   English

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

[英]How to draw a part of a line in SVG?

Would anyone have an idea whether/how it is possible to draw along a line between points while keeping a certain distance from the end points in SVG?有没有人知道是否/如何在与 SVG 中的端点保持一定距离的同时沿着点之间的线绘制?

In case the line is horizontal (eg from (40,40) to (100,40) ), you could easily draw a line that keeps a distance of about 20 to the points as follows如果线是水平的(例如从(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" />

For diagonal lines, however, it is a bit harder.然而,对于对角线,它有点难。 To draw an (easy) diagonal line from (40,40) to (100,100) , you would need cos(pi/4) = sin(pi/4) = sqrt(2) to scale the distance you want to stay away from the end point (in this case: 20*sqrt(2) = 14.1 )要绘制从(40,40)(100,100)的(简单)对角线,您需要cos(pi/4) = sin(pi/4) = sqrt(2)来缩放您想要远离的距离终点(在这种情况下: 20*sqrt(2) = 14.1

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

A demonstration of this code can be found in this fiddle可以在这个小提琴中找到此代码的演示

It thus seems possible to do it, when calculating因此,在计算时似乎可以这样做

  1. The angle between the directional line with a horizontal line方向线与水平线的夹角
  2. The sine and cosine of the angle角的正弦和余弦
  3. The end points of the actual part of the line you want to draw您要绘制的线的实际部分的端点

Is this the only way or is SVG capable of specifying parts of lines or are there smarter, more convenient ways of doing this?这是唯一的方法还是 SVG 能够指定部分线条,或者是否有更智能、更方便的方法来做到这一点?

I'm not sure if this is smart or convinient, but one way to do this without script is the following.我不确定这是否明智或方便,但没有脚本的一种方法如下。

You can use a rect as marker (marker-start and marker-end) and with the markerWidth and markerHeight property in combination with the stroke-width of the line, you can controll the size of the marker.您可以使用矩形作为标记(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>

now imagine we use a white rect, then the marker will overlap the line with a fixed width, and we would have a fixed distance to the endpoints.现在假设我们使用白色矩形,那么标记将以固定宽度与线重叠,并且我们与端点的距离是固定的。

But this is not really what we want.但这并不是我们真正想要的。 To really "cut" the line by the marker, you can then use a mask.要真正通过标记“剪切”线条,您可以使用遮罩。 So draw your line as a mask, with white stroke, but with black markers.因此,将您的线条绘制为蒙版,使用白色笔触,但使用黑色标记。

apply this mask to your line (without marker)... there you go: a line with a visible stroke that has a fixed distance to the endpoints.将此蒙版应用到您的线条(不带标记)...就这样:一条具有可见笔划的线条,与端点的距离固定。

pros: no javascript involved优点:不涉及 javascript

cons: you have to draw your line twice缺点:你必须画两次线

 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>

Once hacky way to do it is cheating with a circular pattern scaled to the size of your line.曾经有一种黑客的方法是使用缩放到您的线条大小的圆形图案作弊。 Not perfect but depends on your use case:不完美,但取决于您的用例:

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

Of course this only gives you a way to show a line that is a specific % from the ends, not an exact pixel value.当然,这只为您提供了一种显示距离末端特定百分比的线的方法,而不是精确的像素值。 Hope this gives you some ideas.希望这能给你一些想法。

Note this is a bit buggy - it does not work for horizontal or vertical lines ... you would have to render them as rectangles or paths and use fill instead of stroke.请注意,这有点问题 - 它不适用于水平线或垂直线……您必须将它们渲染为矩形或路径并使用填充而不是笔划。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM