2017-01-19 13 views
0

SVGを使用して1つのポイント(x0,y0)から別の(x1,y1)に素敵なストロークブロックの矢印を描く必要があります。私は想像することができますブロック矢印SVGを使用

arrow

唯一の方法は、ラインマーカーで(ストロークをシミュレートし、埋めるために基本的に2つの線)を使用することですが、それが原因overlapingストロークに醜いのようなものを探します。

理想的には、ラインとマーカーの両方が同じ色で塗りつぶされ、同じストロークカラーでなければならず、全体的な矢印幅を固定することができます(ただし、それをパラメータ化することもできます)。基本的には、提供される写真と同じように見えるべきであり、2点の座標を提供するだけで描くことができるはずです。 それは可能ですか?

+0

私はあなたが全体の矢印でパスが含まれているシンボルとして全体を作成することができると思います(静的高さXDを追加しました)。 タグとトランスフォームを使用して、必要に応じてそのシンボルを配置することができます。 –

答えて

2

私は退屈していたので、ここに行きます。私は正しい形のパスを生成する関数を書いています。

"から"、 "行"の太さ、線の幅、矢じりの幅、および矢じりの長さを指定するだけです。

お楽しみください!

var from = {x: 50, y: 250}; 
 
var to = {x: 250, y: 100}; 
 

 
var lineWidth = 30; 
 
var arrowheadWidth = 60; 
 
var arrowheadLength = 50; 
 

 
var svg = document.getElementById("test"); 
 

 
drawArrow(svg, from, to, lineWidth, arrowheadWidth, arrowheadLength); 
 

 

 
function drawArrow(svg, from, to, lineWidth, arrowheadWidth, arrowheadLength) 
 
{ 
 
    var dx = to.x - from.x; 
 
    var dy = to.y - from.y; 
 
    // Calculate the length of the line 
 
    var len = Math.sqrt(dx * dx + dy * dy); 
 
    if (len < arrowheadLength) return; 
 

 
    // The difference between the line width and the arrow width 
 
    var dW = arrowheadWidth - lineWidth; 
 
    // The angle of the line 
 
    var angle = Math.atan2(dy, dx) * 180/Math.PI; 
 
    // Generate a path describing the arrow. For simplicity we define it as a 
 
    // horizontal line of the right length, and starting at 0,0. Then we rotate 
 
    // and move it into place with a transform attribute. 
 
    var d = ['M', 0, -lineWidth/2, 
 
      'h', len - arrowheadLength, 
 
      'v', -dW/2, 
 
      'L', len, 0, 
 
      'L', len - arrowheadLength, arrowheadWidth/2, 
 
      'v', -dW/2, 
 
      'H', 0, 
 
      'Z' ]; 
 
    var path = document.createElementNS("http://www.w3.org/2000/svg", "path"); 
 
    path.setAttribute("d", d.join(' ')); 
 
    path.setAttribute("transform", "translate("+from.x+","+from.y+") rotate("+angle+")"); 
 
    path.setAttribute("class", "arrow-line"); 
 
    svg.appendChild(path); 
 
}
.arrow-line { 
 
    fill: gold; 
 
    stroke: black; 
 
    stroke-width: 6; 
 
}
<svg id="test" width="300" height="300"> 
 
</svg>

+0

私たちは同じアイデアを持っていましたが、少し早く;-) –

0

これを行うための最も簡単な方法は、単に矢印を作成するためのスクリプトを使用することです。 ここでは、単純に2点P1、P2の長さおよび矢印の角度を決定し、次いで、適切な長さに単純なパスを作成し、計算された角度でそれを回転させる:

svgns="http://www.w3.org/2000/svg" 
 
function arrow(p1,p2){ 
 
    var h1=15 // line thickness 
 
    var h2=35 // arrow height 
 
    var w2=22 // arrow width 
 
    var deg = Math.atan2(p1.y - p2.y, p1.x - p2.x) * (180/Math.PI); 
 
    var len = Math.sqrt(Math.pow(p1.y - p2.y,2)+Math.pow(p1.x - p2.x,2)) 
 
    var arr = document.createElementNS(svgns,"path") 
 
    var d = `M${p1.x} ${p1.y-h1/2}v${h1}h${h2/2-len}v${(h2-h1)/2}l${-w2} ${-h2/2}l${w2} ${-h2/2}v${(h2-h1)/2}z` 
 
    arr.setAttribute("d",d) 
 
    arr.setAttribute("transform",`rotate(${deg} ${p1.x} ${p1.y})`) 
 
    arr.classList.add("arrow") 
 
    return arr 
 
} 
 

 
var a1 = arrow({x:50,y:50},{x:200,y:200}) 
 
var a2 = arrow({x:450,y:50},{x:300,y:200}) 
 
var a3 = arrow({x:450,y:450},{x:300,y:300}) 
 
var a4 = arrow({x:50,y:450},{x:200,y:300}) 
 
svg.appendChild(a1) 
 
svg.appendChild(a2) 
 
svg.appendChild(a3) 
 
svg.appendChild(a4)
.arrow{stroke-width:3px} 
 
.arrow:nth-of-type(1){fill:green;stroke:lime} 
 
.arrow:nth-of-type(2){fill:red;stroke:orange} 
 
.arrow:nth-of-type(3){fill:blue;stroke:turquoise} 
 
.arrow:nth-of-type(4){fill:violet;stroke:pink}
<svg id="svg" viewBox="0 0 500 500" width="400" height="400"> 
 

 
</svg>

スクリプトレスのソリューションを見つけようとすると、多くのループが必要になります。 上から右へ、右上から下へ、少なくとも4つの矢印が必要です左下から右上へ、右下から左上へ、左下から右上に向かって順番に表示されます。

ここでは、それはなんとかですコンセプトの証明ですが、私は強く、それに対するアドバイス...チェックし、すべての私の数学のトリプルの数時間を座った後

svg{overflow:visible;}
<svg width="200" height="200" style="overflow:visible" stroke="red" color="orange" opacity="0.5"> 
 
    <marker id="ah" viewBox="0 0 10 10" orient="auto" refX="10" refY="5" overflow="visible"> 
 
    <path d="M0 0L10 5L0 10z" stroke-width="1"/> 
 
    </marker> 
 
    <marker id="ah2" viewBox="0 0 10 10" orient="auto" refX="10" refY="5"> 
 
    <path d="M0 0L10 5L0 10z" fill="currentColor" stroke="none"/> 
 
    </marker> 
 
    <marker id="block" viewBox="0 0 10 10" orient="auto" refX="9" refY="5"> 
 
    <rect x="0" y="0" width="10" height="10" stroke="white" stroke-width="1"/> 
 
    </marker> 
 
    <marker id="block2" viewBox="0 0 10 10" orient="auto" refX="9" refY="5"> 
 
    <rect x="0" y="0" width="10" height="10" stroke-width="5"/> 
 
    </marker> 
 
    <mask id="m1"> 
 
    <rect x="-10%" y="-10%" width="110%" height="110%" fill="white"/> 
 
    <line x1="99.999%" y1="99.999%" x2="100%" y2="100%" stroke-width="20" marker-end="url(#block)"/> 
 
    </mask> 
 
    <line x1="0.001%" y1="0.001%" x2="0%" y2="0%" stroke-width="8" marker-end="url(#block2)"/> 
 
    <line x1="0" y1="0" x2="100%" y2="100%" stroke-width="25" mask="url(#m1)"/> 
 
    <line x1="99.999%" y1="99.999%" x2="100%" y2="100%" stroke-width="20" marker-end="url(#ah)"/> 
 
    <line x1="0" y1="0" x2="100%" y2="100%" stroke-width="20" stroke="currentColor" mask="url(#m1)"/> 
 
    <line x1="99.999%" y1="99.999%" x2="100%" y2="100%" stroke-width="20" marker-end="url(#ah2)"/> 
 
</svg>

0


作成されましたSVG Defsタグ内の正規化された矢印
次に、指定された座標の後に矢印をスケーリングします。 は

document.addEventListener("DOMContentLoaded", function(event) { 
 
    var svgDoc = document.getElementById("arrowSvg"); 
 
    var useArrow = svgDoc.getElementById("customArrow"); 
 
    var extraData = useArrow.getAttribute("extra:data"); 
 
    extraData = extraData.split(" "); 
 
    var x1 = parseInt(extraData[0]); 
 
    var x2 = parseInt(extraData[1]); 
 
    var y1 = parseInt(extraData[2]); 
 
    var y2 = parseInt(extraData[3]); 
 
    var arrowHeight = 15; 
 
    //Calculate the rotation needed 
 
    var deltaY = y1 - y2; 
 
    var deltaX = x2 - x1; 
 
    var angle = Math.atan2(deltaY, deltaX) * (180/Math.PI); 
 
    //Distance between the two points. 
 
    var distance = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)); 
 
    useArrow.setAttribute("transform", 
 
         "translate("+(x1+(deltaX/2))+" "+(y1-(deltaY/2))+") "+ 
 
         "rotate(" + -1*angle +") " + 
 
         "matrix("+distance+", 0, 0, "+arrowHeight+", "+(0.5-distance*0.5)+","+(0.5-arrowHeight* 0.5)+")"); 
 

 
});
svg { 
 
    width: 50%; 
 
    border: 1px solid black; 
 
} 
 
.arrow { 
 
    stroke: black; 
 
    stroke-width: 0.05; 
 
    fill: yellow; 
 
}
<svg id="arrowSvg" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:extra="ExtraNameSpace">> 
 
    <defs> 
 
    <path id="idArrow" class="arrow" d="M0,0.25 0.60,0.25 
 
         0.60,0 1,0.5 0.60,1 
 
         0.60,0.75 0,0.75z" /> 
 
    </defs> 
 
    <!--- Extra Data Param: x1 x2 y1 y2---> 
 
    <use id="customArrow" xlink:href="#idArrow" extra:data="10 90 90 5" /> 
 

 
</svg>

関連する問題