如何在SVG线上放置箭头三角形?

问题描述 投票:38回答:2

我是SVG的新手,我想在两点之间划一条直线。到目前为止我使用此命令管理:

<line x1="50" y1="50" x2="150" y2="150" style="stroke:rgb(255,255,0); stroke-width:2" stroke-dasharray="5,3" />"

在这条线上添加微小三角形或箭头(均匀间隔)以指示方向的最简单方法是什么?

编辑1:

为了更清楚,我不是在线末端的箭头之后,而是沿着整条线的多个三角形(均匀间隔)。如果可能的话,我想用一个指向线方向的三角形替换虚线中的每个破折号。

编辑2

根据Phrogz的建议,我创建了一个如下所示的页面,但没有显示任何内容。我究竟做错了什么?

<%@LANGUAGE="VBSCRIPT" CODEPAGE="65001"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<link href="css/com.css" rel="stylesheet" type="text/css" />
</head>
<body style="background:none;">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-10 -10 70 90">
<defs>
<marker id="t" markerWidth="4" markerHeight="4"
        orient="auto" refY="2">
  <path d="M0,0 L4,2 0,4" />
</marker>
</defs>
<polyline points="0,0 0,50 20,70 40,10 42,8 44,10, 46,14 50,50" />
</svg>
<script type="text/javascript">
midMarkers(document.querySelector('polyline'),6);

    // Given a polygon/polyline, create intermediary points along the
    // "straightaways" spaced no closer than `spacing` distance apart.
    // Intermediary points along each section are always evenly spaced.
    // Modifies the polygon/polyline in place.
    function midMarkers(poly,spacing){
        var svg = poly.ownerSVGElement;
        for (var pts=poly.points,i=1;i<pts.numberOfItems;++i){
            var p0=pts.getItem(i-1), p1=pts.getItem(i);
            var dx=p1.x-p0.x, dy=p1.y-p0.y;
            var d = Math.sqrt(dx*dx+dy*dy);
            var numPoints = Math.floor( d/spacing );
            dx /= numPoints;
            dy /= numPoints;
            for (var j=numPoints-1;j>0;--j){
                var pt = svg.createSVGPoint();
                pt.x = p0.x+dx*j;
                pt.y = p0.y+dy*j;
                pts.insertItemBefore(pt,i);
            }
            if (numPoints>0) i += numPoints-1;
        }
    }
</script>
</body>
</html>
svg lines
2个回答
145
投票

基于对问题的澄清,这里是沿<polyline>元素创建中间点的实现,这样marker-mid="url(#arrowhead)"属性将起作用。有关标记和箭头的介绍,请参阅下文。

但是:ぁzxswい

http://jsfiddle.net/Zv57N/

上面的代码修改了现有的midMarkers(document.querySelector('polyline'),6); // Given a polygon/polyline, create intermediary points along the // "straightaways" spaced no closer than `spacing` distance apart. // Intermediary points along each section are always evenly spaced. // Modifies the polygon/polyline in place. function midMarkers(poly,spacing){ var svg = poly.ownerSVGElement; for (var pts=poly.points,i=1;i<pts.numberOfItems;++i){ var p0=pts.getItem(i-1), p1=pts.getItem(i); var dx=p1.x-p0.x, dy=p1.y-p0.y; var d = Math.sqrt(dx*dx+dy*dy); var numPoints = Math.floor( d/spacing ); dx /= numPoints; dy /= numPoints; for (var j=numPoints-1;j>0;--j){ var pt = svg.createSVGPoint(); pt.x = p0.x+dx*j; pt.y = p0.y+dy*j; pts.insertItemBefore(pt,i); } if (numPoints>0) i += numPoints-1; } } 元素,以便沿每条直边每个间距单位添加点。将其与<polyline>相结合,在每个顶点放置一个旋转标记,您就可以沿着路径一致地绘制任意复杂的形状/图形。

虽然代码沿着每个段均匀分布点(因此在角落处不会出现难看的“聚集”),因为上面的演示显示代码不会删除路径中已经存在的距离比间距更近的任何点值。


(原始的“标记简介”答案如下。)


你想定义一个marker-mid并将SVG <marker> element和/或marker-start="…"属性添加到你的行。使用标记将任意形状复制到路径的末端,并(使用marker-end="…")旋转形状以匹配。

orient="auto"

Demo: <svg xmlns="http://www.w3.org/2000/svg" viewBox="-50 -100 200 200"> <defs> <marker id='head' orient='auto' markerWidth='2' markerHeight='4' refX='0.1' refY='2'> <path d='M0,0 V4 L2,2 Z' fill='red' /> </marker> </defs> <path marker-end='url(#head)' stroke-width='5' fill='none' stroke='black' d='M0,0 C45,45 45,-45 90,0' /> </svg>​

在上面:

  • http://jsfiddle.net/Z5Qkf/1/使标记随线旋转
  • orient="auto"定义了一个用于标记的边界框(如viewBox)。 请注意,这些是由最后一行的markerWidth and markerHeight缩放的;高度为“4”时,最终图纸(4×5)的宽度为20个单位。
  • stroke-width定义将形状放置在路径末端时“原点”的位置 我使用了refX and refY来确保标记略微重叠在线的末端
  • 要使自动方向正常工作,您需要标记的“向前”方向为+ x方向。 (用于标记的红色路径看起来像这样▶未旋转时。)
  • 您可以单独调整标记和/或线的refX="0.1"fill-opacity,但是对线的stroke-opacity的更改也会影响绘制的标记。 由于线和标记重叠,如果你降低标记的opacity,你会看到重叠;但是,如果你降低线本身的fill-opacity,那么标记在线上合成完全不透明,然后两者的组合在不透明度下降低。

如果你想沿着线的长度箭头,你将需要使用opacitymarker-mid="…"<path>和沿着线的临时点。

Demo: <polyline>

唯一的问题是任何改变方向的点http://jsfiddle.net/Z5Qkf/2/;这就是为什么在演示中我使用Bézier曲线绕过角落,使得线上的中点沿着直线部分。

messes up the orientation

要以程序方式执行此操作,可以使用JavaScript和<svg xmlns="http://www.w3.org/2000/svg" viewBox="-50 -100 200 200"> <defs> <marker id='mid' orient="auto" markerWidth='2' markerHeight='4' refX='0.1' refY='1'> <!-- triangle pointing right (+x) --> <path d='M0,0 V2 L1,1 Z' fill="orange"/> </marker> <marker id='head' orient="auto" markerWidth='2' markerHeight='4' refX='0.1' refY='2'> <!-- triangle pointing right (+x) --> <path d='M0,0 V4 L2,2 Z' fill="red"/> </marker> </defs> <path id='arrow-line' marker-mid='url(#mid)' marker-end='url(#head)' stroke-width='5' fill='none' stroke='black' d='M0,0 L20,20 C40,40 40,40 60,20 L80,0' /> </svg>​ 命令获取getPointAtLength()的路径。


4
投票

只想添加一些有用的链接和示例:

箭头可以是二次sample the path

2.立方曲线enter image description here

文档:enter image description here

演示:这里实现的两种箭头:

© www.soinside.com 2019 - 2024. All rights reserved.