How to make custom SVG paths?

Viewed 153

I am using this piece of code to make a curved SVG path.

const bezierWeight = 0.6;
var boxPath = document.getElementById("boxPath_"+edge.id);
var x1 = edge.x1;
var y1 = edge.y1;
var x4 = edge.x4;
var y4 = edge.y4;
var dx = (x4 - x1) * bezierWeight;
var x2 = x1 - dx;
var x3 = x4 + dx;
var boxData = `M${x1} ${y1} C ${x2} ${y1} ${x3} ${y4} ${x4} ${y4}`;
boxPath.setAttribute("d", boxData);

Where x1,y1 and x4,y4 are the two points between which I want the SVG path. Which gives me this.

enter image description here

But I want something like this.

enter image description here

How do I do this?

2 Answers

getCubicBezierPath does exactly what you need:

const from = {x: 20, y: 20};
const to = {x: 150, y: 100};

const getCubicBezierPath = (p1, p2) => {
  const midY = (p1.y + p2.y) / 2;
    return `M ${p1.x},${p1.y} 
    C ${p1.x},${midY} ${p2.x},${midY} ${p2.x},${p2.y}`;
};

const svg = d3.select('svg');
svg.append('circle')
    .attr('cx', from.x) 
  .attr('cy', from.y)
  .attr('r', 3)
  .style('fill', 'red')
  
svg.append('circle')
    .attr('cx', to.x)   
  .attr('cy', to.y)
  .attr('r', 3)
  .style('fill', 'red')  
  
svg.append('path')
    .attr('d', getCubicBezierPath(from, to))
  .style('stroke', 'blue')  
  .style('fill', 'none')
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="200" height="150">
</svg>

A path with arrow head marker:

const from = {x: 20, y: 20};
const to = {x: 50, y: 100};

const getCubicBezierPath = (p1, p2) => {
  const midY = (p1.y + p2.y) / 2;
    return `M ${p1.x},${p1.y} 
    C ${p1.x},${midY} ${p2.x},${midY} ${p2.x},${p2.y}`;
};

const svg = d3.select('svg');
svg.append('circle')
    .attr('cx', from.x) 
  .attr('cy', from.y)
  .attr('r', 3)
  .style('fill', 'red')
  
svg.append('circle')
    .attr('cx', to.x)   
  .attr('cy', to.y)
  .attr('r', 3)
  .style('fill', 'red')  
  
svg.append('path')
    .attr('d', getCubicBezierPath(from, to))
  .attr('marker-end', 'url(#arrow-head)')
  .style('stroke', 'blue')  
  .style('fill', 'none')
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="200" height="150">
<defs>
    <marker id="arrow-head" 
          viewBox="0 0 12 12"
          refX="12" 
          refY="6"
          orient="auto"
          markerUnits="strokeWidth"
          markerWidth="12" markerHeight="12">
      <path d="M 0 0 L 12 6 L 0 12 z" fill="blue"/>
    </marker>
  </defs>
</svg>

Related