g6/demos/mapping-visual.html
2020-02-14 11:30:12 +08:00

314 lines
8.1 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Visual Mapping</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="tip">
节点:颜色 —— cluster大小 —— value形状 —— subCluster <br />边:颜色 —— 起始点颜色;粗细 ——
weight
</div>
<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)',
];
const shapes = ['circle', 'rect'];
const data = {
nodes: [
{
id: '0',
label: '0',
value: 10,
cluster: 'a',
subCluster: 'sa',
},
{
id: '1',
label: '1',
value: 20,
cluster: 'b',
subCluster: 'sb',
},
{
id: '2',
label: '2',
value: 5,
cluster: 'a',
subCluster: 'sa',
},
{
id: '3',
label: '3',
value: 10,
cluster: 'a',
subCluster: 'sa',
},
{
id: '4',
label: '4',
value: 12,
cluster: 'c',
subCluster: 'sb',
},
{
id: '5',
label: '5',
value: 18,
cluster: 'c',
subCluster: 'sa',
},
{
id: '6',
label: '6',
value: 3,
cluster: 'c',
subCluster: 'sa',
},
{
id: '7',
label: '7',
value: 7,
cluster: 'b',
subCluster: 'sa',
},
{
id: '8',
label: '8',
value: 21,
cluster: 'd',
subCluster: 'sb',
},
{
id: '9',
label: '9',
value: 9,
cluster: 'd',
subCluster: 'sb',
},
],
edges: [
{
source: '0',
target: '1',
weight: 20,
},
{
source: '0',
target: '3',
weight: 12,
},
{
source: '0',
target: '4',
weight: 19,
},
{
source: '0',
target: '5',
weight: 2,
},
{
source: '0',
target: '7',
weight: 8,
},
{
source: '0',
target: '8',
weight: 14,
},
{
source: '0',
target: '9',
weight: 5,
},
{
source: '2',
target: '3',
weight: 20,
},
{
source: '4',
target: '5',
weight: 10,
},
{
source: '4',
target: '6',
weight: 11,
},
],
};
const graph = new G6.Graph({
container: 'mountNode',
width: 1000,
height: 800,
layout: {
type: 'force',
linkDistance: 100,
nodeStrength: -30,
edgeStrength: 0.1,
},
modes: {
default: [
{
type: 'tooltip',
formatText(model) {
const text =
'NODE' +
'<br/> id: ' +
model.id +
'<br/> cluster: ' +
model.cluster +
'<br/> subCluster: ' +
model.subCluster +
'<br/> value: ' +
model.value;
return text;
},
shouldUpdate: e => {
return true;
},
},
{
type: 'edge-tooltip',
formatText(model) {
const text =
'EDGE' +
'<br/> source: ' +
model.source +
'<br/> weight: ' +
model.weight +
'<br/> target: ' +
model.target;
return text;
},
shouldUpdate: e => {
return true;
},
},
],
},
defaultNode: {
size: [10, 10],
color: 'steelblue',
style: {
opacity: 0.8,
lineWidth: 1,
stroke: '#999',
},
},
defaultEdge: {
size: 1,
color: '#e2e2e2',
style: {
opacity: 0.6,
lineAppendWidth: 5,
},
},
});
// mapping
const edges = data.edges;
const nodes = data.nodes;
const nodeMap = new Map();
const clusterMap = new Map();
const subClusterMap = new Map();
let clusterId = 0;
let subClusterId = 0;
nodes.forEach((node, i) => {
nodeMap.set(node.id, node);
// cluster
if (node.cluster && clusterMap.get(node.cluster) === undefined) {
clusterMap.set(node.cluster, clusterId);
clusterId++;
}
// subCluster
if (node.subCluster && subClusterMap.get(node.subCluster) === undefined) {
subClusterMap.set(node.subCluster, subClusterId);
subClusterId++;
}
const cid = clusterMap.get(node.cluster);
const scid = subClusterMap.get(node.subCluster);
if (node.style) {
node.style.fill = colors[cid % colors.length];
} else {
node.style = {
fill: colors[cid % colors.length],
};
}
node.shape = shapes[scid % shapes.length];
});
// map the value to node size
let maxEdgeWeight = -9999,
minEdgeWeight = 9999;
edges.forEach((edge, i) => {
const source = nodeMap.get(edge.source);
const target = nodeMap.get(edge.target);
edge.color = source.style.fill;
// lineWidth
if (maxEdgeWeight < edge.weight) maxEdgeWeight = edge.weight;
if (minEdgeWeight > edge.weight) minEdgeWeight = edge.weight;
});
// map the value to node size
let maxNodeValue = -9999,
minNodeValue = 9999;
nodes.forEach(n => {
if (maxNodeValue < n.value) maxNodeValue = n.value;
if (minNodeValue > n.value) minNodeValue = n.value;
});
const nodeSizeRange = [10, 30];
const nodeSizeDataRange = [minNodeValue, maxNodeValue];
const lineWidthRange = [0.5, 3];
const lineWidthDataRange = [minEdgeWeight, maxEdgeWeight];
scaleNodeProp(nodes, 'size', 'value', nodeSizeDataRange, nodeSizeRange);
scaleNodeProp(edges, 'style.lineWidth', 'weight', lineWidthDataRange, lineWidthRange);
graph.data(data);
graph.render();
function scaleNodeProp(elements, propName, refPropName, dataRange, outRange) {
const outLength = outRange[1] - outRange[0];
const dataLength = dataRange[1] - dataRange[0];
elements.forEach(n => {
if (propName.split('.')[0] === 'style') {
if (n.style) {
n.style[propName.split('.')[1]] =
((n[refPropName] - dataRange[0]) * outLength) / dataLength + outRange[0];
} else {
n.style = {
[propName.split('.')[1]]:
((n[refPropName] - dataRange[0]) * outLength) / dataLength + outRange[0],
};
}
} else {
n[propName] = ((n[refPropName] - dataRange[0]) * outLength) / dataLength + outRange[0];
}
});
}
</script>
</body>
</html>