g6/demos/circular-arc-diagram.html

158 lines
4.6 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Circular Arc Diagram</title>
<style>
.g6-tooltip {
border: 1px solid #e2e2e2;
border-radius: 4px;
font-size: 12px;
color: #545454;
background-color: rgba(255, 255, 255, 0.9);
padding: 10px 8px;
box-shadow: rgb(174, 174, 174) 0px 0px 10px;
}
</style>
</head>
<body>
<div id="mountNode"></div>
<script src="../build/g6.js"></script>
<script src="./assets/jquery-3.2.1.min.js"></script>
<script>
const colors = [ 'rgb(64, 174, 247)', 'rgb(108, 207, 169)', 'rgb(157, 223, 125)',
'rgb(240, 198, 74)', 'rgb(221, 158, 97)', 'rgb(141, 163, 112)', 'rgb(115, 136, 220)',
'rgb(133, 88, 219)', 'rgb(203, 135, 226)', 'rgb(227, 137, 163)' ];
const width = 1000;
const height = 800;
const graph = new G6.Graph({
container: 'mountNode',
width,
height,
linkCenter: true,
fitView: true,
modes: {
default: [{
type: 'edge-tooltip',
formatText(model) {
const text = 'source: ' + model.sourceName
+ '<br/> target: ' + model.targetName;
return text;
},
shouldUpdate: e => {
return true;
}
}]
},
defaultNode: {
size: [10, 10],
color: 'steelblue'
},
defaultEdge: {
size: 1,
color: '#e2e2e2',
style: {
opacity: 0.6,
lineAppendWidth: 3
}
},
nodeStyle: {
default: {
opacity: 0.8,
lineWidth: 1,
stroke: '#999'
}
},
edgeStyle: {
hover: {
opacity: 1,
lineWidth: 2
}
}
});
graph.on('edge:mouseenter', e => {
const edge = e.item;
graph.setItemState(edge, 'hover', true);
});
graph.on('edge:mouseleave', e => {
const edge = e.item;
graph.setItemState(edge, 'hover', false);
});
$.getJSON('./assets/data/relationship-with-weight.json', data => {
const origin = [ width / 2, height / 2 ];
const radius = width < height ? width / 3 : height / 3;
const edges = data.edges;
const nodes = data.nodes;
const nodeMap = new Map();
const clusterMap = new Map();
let clusterId = 0;
const n = nodes.length;
const angleSep = Math.PI * 2 / n;
nodes.forEach((node, i) => {
const angle = i * angleSep;
node.x = radius * Math.cos(angle) + origin[0];
node.y = radius * Math.sin(angle) + origin[1];
node.angle = angle;
nodeMap.set(node.id, node);
// cluster
if (node.cluster && clusterMap.get(node.cluster) === undefined) {
clusterMap.set(node.cluster, clusterId);
clusterId ++;
}
const id = clusterMap.get(node.cluster);
if (node.style) {
node.style.fill = colors[id % colors.length];
} else {
node.style = {
fill: colors[id % colors.length]
}
}
// label
node.label = node.name;
node.labelCfg = {
position: 'center',
style: {
rotate: angle,
textAlign: 'start'
}
}
});
edges.forEach((edge, i) => {
edge.shape = 'quadratic';
const source = nodeMap.get(edge.source);
const target = nodeMap.get(edge.target);
edge.controlPoints = [{ x: origin[0], y: origin[1] }];
edge.color = source.style.fill;
edge.sourceName = source.name;
edge.targetName = target.name;
});
// map the value to node size
let maxValue = -9999,
minValue = 9999;
nodes.forEach(n => {
if (maxValue < n.value) maxValue = n.value;
if (minValue > n.value) minValue = n.value;
});
const sizeRange = [3, 30];
const sizeDataRange = [minValue, maxValue];
scaleNodeProp(nodes, 'size', 'value', sizeDataRange, sizeRange);
graph.data(data);
graph.render();
});
function scaleNodeProp(nodes, propName, refPropName, dataRange, outRange) {
const outLength = outRange[1] - outRange[0];
const dataLength = dataRange[1] - dataRange[0];
nodes.forEach(n => {
n[propName] = (n[refPropName] - dataRange[0]) * outLength / dataLength + outRange[0];
});
}
</script>
</body>
</html>