2017-01-22 6 views
1

Hätte jemand eine Idee, ob/wie es möglich ist, eine Linie zwischen Punkten zu zeichnen, während ein bestimmter Abstand zu den Endpunkten in SVG eingehalten wird?Wie zeichne ich einen Teil einer Linie in SVG?

Falls die Linie horizontal ist (zB von (40,40) bis (100,40)), man leicht eine Linie, die einen Abstand von etwa 20 zu den Punkten hält ziehen könnte als

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

Für diagonale Linien folgte, ist es jedoch, ist ein bisschen schwieriger. Um eine (leicht) diagonale Linie von (40,40) zu (100,100) zu ziehen, würden Sie cos(pi/4) = sin(pi/4) = sqrt(2) brauchen die Strecke, die Sie vom Endpunkt bleiben weg wollen maßstab (in diesem Fall: 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" /> 

Eine Demonstration dieses Codes können in diesen fiddle

fand es scheint also möglich, es zu tun, wenn

  1. der Winkel zwischen der Richtungslinie mit einer horizontalen Linie Berechnung
  2. Der Sinus und Kosinus des Winkels
  3. Die Endpunkte des aktuellen Teils der Linie, die Sie

Ist dies der einzige Weg zeichnen möchten oder SVG können Teile von Linien gehen oder gibt es intelligentere , bequemere Möglichkeiten, dies zu tun?

Antwort

1

Ich bin mir nicht sicher, ob dies schlau oder praktisch ist, aber eine Möglichkeit, dies ohne Skript zu tun, ist das Folgende.

Sie können ein Rect als Marker verwenden (marker-start und marker-end) und mit der markerWidth- und markerHeight -Eigenschaft in Kombination mit der Strichbreite der Linie können Sie die Größe des Markers steuern.

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>

jetzt stellen wir uns einen weißen rect verwenden, dann wird die Markierung, um die Leitung mit einer festen Breite überlappen, und wir würden in einem festen Abstand zu den Endpunkten haben.

Aber das ist nicht wirklich was wir wollen. Um die Linie wirklich mit dem Marker zu "schneiden", können Sie dann eine Maske verwenden. Also zeichne deine Linie als Maske, mit weißem Strich, aber mit schwarzen Markierungen.

wenden Sie diese Maske auf Ihre Linie (ohne Marker) ... Sie gehen: eine Linie mit einem sichtbaren Strich, der einen festen Abstand zu den Endpunkten hat.

Profis: kein JavaScript

Nachteile beteiligt: ​​Sie Ihre Linie zweimal

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

Sobald hacky Weg zu zeichnen zu tun haben, ist es mit einem kreisförmigen Muster um die skalierte Betrug Größe Ihrer Linie.Nicht perfekt, aber abhängig von Ihrem Anwendungsfall:

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

Natürlich ist dies nur gibt Ihnen eine Möglichkeit, eine Linie zu zeigen, dass ein bestimmtes% von dem Enden ist, kein exakter Pixelwert. Hoffe das gibt dir ein paar Ideen.

Beachten Sie, dass dies ein bisschen buggy ist - es funktioniert nicht für horizontale oder vertikale Linien ... Sie müssten sie als Rechtecke oder Pfade rendern und füllen Sie anstelle von Strich.

Verwandte Themen