Published
Edited
Nov 22, 2020
2 forks
6 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
const svgD3Node = d3.select(svg`<svg width=${width} height=400></svg>`);

const sourceData = {
x: width/2-100,
y: 50
};
const targetData = {
x: width/2+100,
y: 200
};

const drag = d3.drag().on('drag', dragged)

const link = svgD3Node.append('path')
.attr('d', diagonal(sourceData, targetData))
.attr('fill', 'none')
.attr('stroke', 'steelblue')

const source = svgD3Node.append('circle')
.datum(sourceData)
.attr('r', 10)
.attr('cx', sourceData.x)
.attr('cy', sourceData.y)
.attr('fill', 'steelblue')
.attr('cursor', 'move')
.call(drag)

const target = svgD3Node.append('circle')
.datum(targetData)
.attr('r', 10)
.attr('cx', targetData.x)
.attr('cy', targetData.y)
.attr('fill', 'steelblue')
.attr('cursor', 'move')
.call(drag)

function dragged(d3Event,d) {
console.log('d',d,'d3Event',d3Event)
d.x = d3Event.x;
d.y = d3Event.y;
update();
}

function update() {
source.attr('cx', sourceData.x).attr('cy', sourceData.y);
target.attr('cx', targetData.x).attr('cy', targetData.y);
link.attr('d', diagonal(sourceData, targetData))
}


yield svgD3Node.node();
}
Insert cell
function diagonal(s, t) {
// Define source and target x,y coordinates
const x = s.x;
const y = s.y;
const ex = t.x;
const ey = t.y;

// Values in case of top reversed and left reversed diagonals
let xrvs = ex - x < 0 ? -1 : 1;
let yrvs = ey - y < 0 ? -1 : 1;

// Define preferred curve radius
let rdef = 35;
// Reduce curve radius, if source-target x space is smaller
let r = Math.abs(ex - x) / 2 < rdef ? Math.abs(ex - x) / 2 : rdef;

// Further reduce curve radius, is y space is more small
r = Math.abs(ey - y) / 2 < r ? Math.abs(ey - y) / 2 : r;

// Defin width and height of link, excluding radius
let h = Math.abs(ey - y) / 2 - r;
let w = Math.abs(ex - x) / 2 - r ;
// Build and return custom arc command
return `
M ${x} ${y}
L ${x+w*xrvs} ${y}
C ${x+w*xrvs+r*xrvs} ${y}
${x+w*xrvs+r*xrvs} ${y}
${x+w*xrvs+r*xrvs} ${y+r*yrvs}
L ${x+w*xrvs+r*xrvs} ${ey-r*yrvs}
C ${x+w*xrvs+r*xrvs} ${ey}
${x+w*xrvs+r*xrvs} ${ey}
${ex-w*xrvs} ${ey}
L ${ex} ${ey}
`

}
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more