59

I am new to SVG and I am trying to draw a straight line between two points. I managed so far by using this command:

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

What is the simplest way to add tiny triangles or arrow heads (evenly spaced) over this line in order to indicate the direction?

Edit 1:

Just to be more clear, I am not after an arrow at the end of the line, but multiple triangles (evenly spaced) along the whole line. If possible, I would like to replace each dash in the dashed line with a triangle pointing in the direction of the line.

Edit 2

Based on Phrogz' suggestion, I created a page as shown below, but nothing is showing up. What am I doing wrong?

<%@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>
4

2 回答 2

175

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

演示: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>元素并将marker-start="…"和/或marker-end="…"属性添加到您的行中。使用标记将任意形状复制到路径的末端,并(使用orient="auto")旋转形状以匹配。

<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"使标记随线旋转
  • markerWidthmarkerHeight定义一个用于标记的边界框(如 viewBox)。
    • 请注意,这些然后由stroke-width最后一行的缩放;高度为“4”会使其在最终图纸(4×5)中为 20 个单位宽。
  • refXrefY在将形状放置在路径末端时定义“原点”的位置
    • 我曾经refX="0.1"确保标记与行尾略微重叠
  • 为了使自动方向正常工作,您希望标记的“向前”方向位于 +x 方向。(用于标记的红色路径在未旋转时看起来像这样 ▶。)
  • 您可以单独调整标记和/或线的fill-opacityand stroke-opacity,但更改opacity线的 也会影响绘制的标记。
    • 由于线和标记重叠,如果降低fill-opacity标记的 ,您会看到重叠;但是,如果您降低opacity线条本身的 ,则标记将在线条上完全不透明地合成,然后两者的组合会降低不透明度。
      在此处输入图像描述

如果您想要沿直线长度的箭头,则需要使用沿直线marker-mid="…"的任何一个<path><polyline>和中间点。

演示:http: //jsfiddle.net/Z5Qkf/2/

在此处输入图像描述

唯一的问题是沿线改变方向的任何点都会弄乱方向;这就是为什么在演示中我使用 Bézier 曲线来圆角,使直线上的中点沿着直线段。

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

要在程序上执行此操作,您可以使用 JavaScript 和getPointAtLength()路径命令对路径进行采样

于 2012-08-04T15:40:30.710 回答
11

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

1.箭头可以是二次的 在此处输入图像描述

2.三次曲线 在此处输入图像描述

文档:https ://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Paths

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

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>

  
  <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'>
    <!-- triangle pointing right (+x) -->
    <path d='M0,0 V4 L2,2 Z' fill="black"/>
  </marker>
</defs>

<path
  id='arrow-line'
  marker-end='url(#head)'
  stroke-width='1'
  fill='none' stroke='black'  
  d='M0,0 Q45,-20 90,0'
  />
    
<path
  id='arrow-line'
  marker-end='url(#head)'
  stroke-width='1'
  fill='none' stroke='black'  
  d='M0,50 C10,30 80,30 90,50'
  />

</svg>
</body>
</html>

于 2018-09-20T21:07:08.193 回答