如何在SVG线上放置箭头三角形? [英] How to place arrow head triangles on SVG lines?

查看:115
本文介绍了如何在SVG线上放置箭头三角形?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是SVG的新手,我试图在两点之间画一条直线.到目前为止,我通过使用以下命令进行了管理:

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?

更清楚一点,我不是在行尾的箭头后面,而是沿着整条线的多个三角形(均匀分布).如果可能的话,我想将虚线中的每个破折号替换为一个指向该线方向的三角形.

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.

编辑2

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

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>

推荐答案

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

Based on a clarification of the question, here's an implementation of creating intermediary points along a <polyline> element such that the marker-mid="url(#arrowhead)" attribute will work. See below that for an introduction to markers and arrowheads.

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>元素,以沿每个直边沿每个 spacing 单位添加点.将此与marker-mid结合使用,可以在每个顶点处放置一个旋转的标记,您便能够沿路径一致地绘制任意复杂的形状/图形.

The above code modifies an existing <polyline> element to add points every spacing units along each straight edge. Combine this with marker-mid to place a rotated marker at every vertex, and you have the ability to draw arbitrarily complex shapes/graphics consistently along your path.

尽管代码沿每个线段均匀地隔开了点(这样就不会在拐角处出现难看的聚结"),如上面的演示所示,该代码不会删除路径中已经存在的更靠近的点比 spacing 值.

Although the code spaces out the points evenly along each segment (so that no unsightly 'bunching up' occurs at corners) as the above demo shows the code does not remove any points that you already have in your path that are closer together than the spacing value.

(以下是标记的简介"的原始答案.)

您要定义 SVG <marker>元素并添加marker-start="…"和/或marker-end="…"属性添加到您的行.使用标记将任意形状复制到路径的末端,然后使用orient="auto"旋转形状以匹配.

You want to define an SVG <marker> element and add the marker-start="…" and/or marker-end="…" attributes to your line. Using a marker copies any arbitrary shape onto the end(s) of your path, and (with orient="auto") rotates the shape to match.

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

Demo: http://jsfiddle.net/Z5Qkf/1/

在上面:

  • orient="auto" 导致标记随线旋转
  • markerWidthmarkerHeight 定义一个边界框(如viewBox)用于标记.
    • 请注意,然后按最后一行的stroke-width缩放比例.高度为"4"会导致其在最终图形中变为20个单位宽(4 x 5).
    • orient="auto" causes the marker to rotate with the line
    • markerWidth and markerHeight define a bounding box (like a viewBox) to use for the marker.
      • Note that these are then scaled by the stroke-width of the final line; having a height of "4" causes it to be 20 units wide in the final drawing (4×5).
      • 我已经使用refX="0.1"来确保标记与行的末端稍微重叠
      • I've used refX="0.1" to ensure that the marker overlaps the end of the line slightly
      • 由于线条和标记重叠,因此,如果降低标记的fill-opacity,则会看到重叠;但是,如果降低线本身的opacity,则标记将在该线上完全不透明地合成,然后降低两者的组合的不透明度.
      • Since the line and marker are overlapping, if you lower the fill-opacity of the marker you would see the overlap; however, if you lower the opacity of the line itself then the marker is composited fully-opaque over the line and the combination of the two are then lowered in opacity.

      如果要沿线的长度箭头,则需要对<path><polyline>使用marker-mid="…"以及沿线的中间点.

      If you want arrows along the length of the line, you will need to use marker-mid="…" with either <path> or <polyline> and interim points along the line.

      唯一的问题是,沿线改变方向的任何点都会弄乱方向;这就是为什么在演示中我使用贝塞尔曲线将拐角圆角,以使直线上的中点沿直线部分的原因.

      The only problem is that any point that changes direction along the line messes up the orientation; this is why in the demo I've used a Bézier curve to round the corner so that the midpoint on the line is along a straight section.

      <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()命令作为路径的路径.

      To do this procedurally, you can use JavaScript and the getPointAtLength() command for a path to sample the path.

      这篇关于如何在SVG线上放置箭头三角形?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆