Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Block arrow using SVG

Tags:

svg

I need to draw nice stroked block arrow using SVG from one point (x0,y0) to another (x1,y1), like the one on the picture.

arrow

The only way I can imagine is to use a line (two lines basically to simulate stroke and fill) with marker, but it looks kind of ugly due to overlaping strokes.

Ideally both line and marker should be filled with the same color and should have the same stroke color, and overall arrow width can be fixed (but if I could parametrize that as well it would be cool). Basically it should look the same as on picture provided and should be able to be drawn by just providing coordinates of two points. Is it even possible?

like image 939
kaytrance Avatar asked Dec 23 '22 21:12

kaytrance


1 Answers

I was bored, so here you go. I have written a function to generate a path of the right shape.

You just need to give it the "from" and "to" coords, the line width, arrowhead width, and arrowhead length.

Enjoy!

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>
like image 172
Paul LeBeau Avatar answered Mar 08 '23 11:03

Paul LeBeau