2017-01-22 3 views
1

У кого-нибудь есть идея, можно ли рисовать вдоль линии между точками, сохраняя определенное расстояние от конечных точек в SVG?Как нарисовать часть строки в SVG?

В случае линия горизонтальна (например, от (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" /> 

Для диагональных линий, однако, его немного сложнее. Чтобы нарисовать (легкий) диагональную линию от (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" /> 

Демонстрация этого кода может можно найти в этом fiddle

Это, таким образом, представляется возможным сделать это, при расчете

  1. угла между направленной линией с горизонтальной линией
  2. Синус и косинус угла
  3. Концы фактической части линии, которую вы хотите нарисовать

Является ли это единственным способом или SVG способен указать части линий или есть умнее , более удобные способы сделать это?

ответ

1

Я не уверен, что это разумно или удобно, но один способ сделать это без скрипта - это следующее.

Вы можете использовать прямоугольник как маркер (маркер-старт и маркер-конец), а также свойство 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>

теперь представьте себе, мы используем белый прямоугольник, то маркер будет перекрывать линию с фиксированной шириной, и мы имели бы фиксированное расстояние до конечных точек.

Но это не совсем то, что мы хотим. Чтобы действительно «вырезать» линию маркером, вы можете использовать маску. Поэтому нарисуйте свою линию как маску с белым штрихом, но с черными маркерами.

применить эту маску к вашей линии (без маркера) ... там вы идете: линия с видимым ударом, которая имеет фиксированное расстояние до конечных точек.

плюсы: нет Javascript участвует

минусы: вы должны сделать свою линию дважды

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>

0

После того, как Hacky способ сделать это обман с круговой диаграммой масштабируется к размер вашей линии.Не совершенным, но зависит от случая использования:

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

Конечно, это только дает вам возможность показать строку, которая является специфическим% от концов, не точное значение пикселя. Надеюсь, это даст вам некоторые идеи.

Обратите внимание, что это немного неправильно - оно не работает для горизонтальных или вертикальных линий ... вам придется отображать их как прямоугольники или дорожки и использовать заливку вместо штриха.