score:12

*Accepted answer*

Just to be clear for others, what we're talking about is a quadratic Bezier curve. That gives you a smooth curve between two points with one control point.

The basic method is:

- Find your A-B midpoint, call it J.
- Do some trig to find the point at the end of line segment M, call it K
- Use the SVG Q or T path commands to draw the quadratic Bezier curve, starting from A, going to B, with the control point K. (note that this won't look exactly like your diagram, but that can be tuned by changing the length of M).

Here's a JavaScript function to return the path you'll need:

```
function draw_curve(Ax, Ay, Bx, By, M) {
// Find midpoint J
var Jx = Ax + (Bx - Ax) / 2
var Jy = Ay + (By - Ay) / 2
// We need a and b to find theta, and we need to know the sign of each to make sure that the orientation is correct.
var a = Bx - Ax
var asign = (a < 0 ? -1 : 1)
var b = By - Ay
var bsign = (b < 0 ? -1 : 1)
var theta = Math.atan(b / a)
// Find the point that's perpendicular to J on side
var costheta = asign * Math.cos(theta)
var sintheta = asign * Math.sin(theta)
// Find c and d
var c = M * sintheta
var d = M * costheta
// Use c and d to find Kx and Ky
var Kx = Jx - c
var Ky = Jy + d
return "M" + Ax + "," + Ay +
"Q" + Kx + "," + Ky +
" " + Bx + "," + By
}
```

You can see this in action at this jsfiddle or the snippet (below).

Edit: If a quadratic curve doesn't fit, you can pretty easily adapt the function to do cubic Bezier or arc segments.

```
var adjacencyList = {
1: [2],
2: [3],
3: [1],
};
var nodes = d3.values(adjacencyList),
links = d3.merge(nodes.map(function(source) {
return source.map(function(target) {
return {
source: source,
target: adjacencyList[target]
};
});
}));
var w = 960,
h = 500;
var M = 50;
var vis = d3.select("#svg-container").append("svg")
.attr("width", w)
.attr("height", h);
var force = d3.layout.force()
.nodes(nodes)
.links(links)
.size([w, h])
.linkDistance(100)
.charge(-100)
.start();
var link = vis.selectAll(".link")
.data(links)
.enter().append("svg:path")
.attr("class", "link");
console.log(link)
var node = vis.selectAll("circle.node")
.data(nodes)
.enter().append("svg:circle")
.attr("r", 5)
.call(force.drag);
force.on("tick", function() {
link.attr("d", function(d) {
return draw_curve(d.source.x, d.source.y, d.target.x, d.target.y, M);
});
node.attr("cx", function(d) {
return d.x;
})
.attr("cy", function(d) {
return d.y;
});
});
function draw_curve(Ax, Ay, Bx, By, M) {
// side is either 1 or -1 depending on which side you want the curve to be on.
// Find midpoint J
var Jx = Ax + (Bx - Ax) / 2
var Jy = Ay + (By - Ay) / 2
// We need a and b to find theta, and we need to know the sign of each to make sure that the orientation is correct.
var a = Bx - Ax
var asign = (a < 0 ? -1 : 1)
var b = By - Ay
var bsign = (b < 0 ? -1 : 1)
var theta = Math.atan(b / a)
// Find the point that's perpendicular to J on side
var costheta = asign * Math.cos(theta)
var sintheta = asign * Math.sin(theta)
// Find c and d
var c = M * sintheta
var d = M * costheta
// Use c and d to find Kx and Ky
var Kx = Jx - c
var Ky = Jy + d
return "M" + Ax + "," + Ay +
"Q" + Kx + "," + Ky +
" " + Bx + "," + By
}
```

```
.node {
stroke: #fff;
stroke-width: 1.5px;
}
.link {
stroke: #ccc;
fill: none
}
```

```
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.0.0/d3.min.js"></script>
<body>
<div id="svg-container">
</div>
</body>
```

Source: stackoverflow.com

#### Related Query

- d3.js: How to convert edges from lines to curved paths in a network visualization by drawing a quadratic Bezier curve?
- How to make curved lines to straight lines for Hierarchy Chart using d3.js
- How to stop paths from blurring/disappearing in D3 when using a viewbox?
- How to draw area/fill between two curved lines of different lengths (different x values) in d3
- How can I efficiently convert data from string to int within a d3 method chain?
- How to convert d3.value() iterable and d3.rollup from javaScript into TypeScript
- How do I Bind Data from a .tsv to an SVG's paths using d3.js for a Choropleth Map
- How to retrieve Vector Tiles from Mapbox with d3.js and convert to geojson?
- How to remove D3 link text from visualization
- In a d3 scatterplot using data from a csv file, how do i draw lines connecting related points when the mouse is over a point?
- How do I convert an svg file from inkscape to geoJson format
- How to convert D3 time scale from V3 to V4?
- How do I convert strings from csv in d3.js and be able to use them as a dataset?
- How to create curved lines connecting nodes in D3
- How to convert from v4 to v3 in d3
- How can I give this radial cluster straight lines instead of curved lines?
- how to convert data selected from a postgres database to json or csv to use it with d3js lib?
- How can I hide lines from the axes of my bar chart?
- How to convert D3 data array-of-objects from long-format to wide-format in JavaScript and D3?
- How to convert to nested json from dataframe
- How to convert a chart with kernel density estimation line from d3.js version 3 to d3.js version 4
- How to keep an element from splitting into two paths
- How to remove extras lines using stylesheet from axies in the D3.js
- How to make d3-diagram visualization from json-array working?
- how to import php script that convert mysql data to json format, from d3.json function in force directed layout
- How do I remove all children elements from a node and then apply them again with different color and size?
- How to write vertical text from bottom to top without using transform rotate?
- How to convert to D3's JSON format?
- How to load data from a CSV file in D3 v5
- How do I convert a JavaScript forEach loop/function to CoffeeScript

#### More Query from same tag

- d3 js drag event listener isnt getting the event - (d3, react)
- d3 conventional indentation with eslint
- Getting average of object within an array
- remove a legend dimple.js
- Script in D3.js make Chrome crash
- d3.js v4.9 Get the calculated width of selected element
- How to add custom colors in D3 nodes of a graph
- d3js force layout dynamically adding image or circle for each node
- D3.js Stacked Bar OnClick Action Not Triggered
- D3.v3 Brush Strange Behavior
- dc.js heatmap colour range not getting updated after filter applied
- How to build data set for D3 In JavaScript?
- How to tune Typescript StencilJS with Jest to support ES6 dynamic module imports
- How to do thIs diagram with force-directed graph in D3.js?
- Why do I need to start a web server to use d3?
- Angular D3 bar chart animation
- D3.js vs Raphael.js
- Drawing a Multi Line Chart from nested data
- Why svg text is unselectable?
- d3.js how to set y-axis fixed position
- D3js pie animation on load not working
- how to display date and time both in xScale in D3
- Zoom extent issue in d3 axis
- Transition partition arcs back to original angles
- How do I include newlines in labels in D3 charts?
- Customize the d3 month or year tick format
- How to hide data of database but display it as an interactive visualization?
- Need D3 Map file uStates.js
- Handling Removal of Elements with Data Join in D3.js
- How to add filled sections to SVG circles using d3.js