Как разместить треугольники стрелки на линиях SVG?

Я новичок в 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

Основываясь на предположении Фрогца, я создал страницу, как показано ниже, но ничего не появляется. Что я делаю неправильно?

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

Ответ 1

Основываясь на пояснении вопроса, здесь реализована реализация создания промежуточных точек вдоль элемента <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, чтобы поместить повернутый маркер в каждую вершину, и у вас есть возможность последовательно рисовать произвольно сложные фигуры/графику вдоль вашего пути.

Bird Tracks

Хотя код помещает точки равномерно вдоль каждого сегмента (так что в углах не возникает неприглядная "группировка" ), поскольку приведенная выше демонстрация показывает, что код не удаляет точки, которые у вас уже есть на вашем пути, которые ближе друг к другу чем значение расстояния.


(Далее следует ответ "Вступление к маркерам" ).


Вы хотите определить элемент 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/

Curved line with arrowhead

В приведенном выше примере:

  • orient="auto" заставляет маркер вращаться с линией
  • markerWidth и markerHeight определяют ограничивающий прямоугольник (например, viewBox) для использования для маркера.
    • Обратите внимание, что они затем масштабируются с помощью stroke-width конечной строки; имеющий высоту "4", в конечном чертеже он составляет 20 единиц ширины (4 и 5 раз).
  • refX и refY определить, где "происхождение" находится при размещении фигуры в конце пути
    • Я использовал refX="0.1", чтобы убедиться, что маркер частично перекрывает конец строки.
  • Для правильной работы автоматической ориентации вы хотите, чтобы направление "вперед" маркера находилось в направлении + x. (Красный путь, используемый для маркера, выглядит следующим образом: ▶ при отключении.)
  • Вы можете отрегулировать fill-opacity и stroke-opacity маркера и/или строки независимо, но изменения в строке opacity будут влиять на рисованный маркер.
    • Так как линия и маркер перекрываются, если вы опустите fill-opacity маркера, вы увидите перекрытие; однако, если вы опустите opacity самой линии, тогда маркер будет скомпонован полностью непрозрачным по линии, а затем комбинация этих двух будет уменьшена в непрозрачности.
      enter image description here

Если вам нужны стрелки вдоль длины строки, вам нужно будет использовать marker-mid="…" с помощью <path> или <polyline> и промежуточных точек вдоль линии.

Демо: http://jsfiddle.net/Z5Qkf/2/

enter image description here

Единственная проблема заключается в том, что любая точка, меняющая направление вдоль линии испортила ориентацию; поэтому в демо я использовал кривую Безье, чтобы обогнуть угол, так что средняя точка на линии находится вдоль прямой секции.

<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() для пути к пример пути.

Ответ 2

Просто хочу добавить несколько полезных ссылок и примеров:

1. Стрелка может быть квадратичной enter image description here

2. Кубическая кривая enter image description here

Документация: 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>