g6/demos/case-beijing-metro-animation.html

244 lines
7.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></script>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>data process</title>
<style>
canvas{
background: rgb(0, 0, 0);
background-image: url("./assets/data/background-small.png");
/* background-repeat: no-repeat; */
background-size: 600px 600px;
}
.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)' ];
// custom the node
G6.registerNode('breath-node', {
afterDraw(cfg, group) {
const r = cfg.size / 2;
console.log(cfg);
const back1 = group.addShape('circle', {
zIndex: -3,
attrs: {
x: 0,
y: 0,
r,
fill: cfg.color || (cfg.style && cfg.style.fill),
opacity: 0.6
}
});
const back2 = group.addShape('circle', {
zIndex: -2,
attrs: {
x: 0,
y: 0,
r,
fill: cfg.color,
// 为了显示清晰,随意设置了颜色
opacity: 0.6
}
});
const back3 = group.addShape('circle', {
zIndex: -1,
attrs: {
x: 0,
y: 0,
r,
fill: cfg.color,
opacity: 0.6
}
});
group.sort(); // 排序根据zIndex 排序
const delayBase = Math.random() * 2000;
back1.animate({ // 逐渐放大,并消失
r: r + 10,
opacity: 0.0,
repeat: true // 循环
},
3000, 'easeCubic', null, delayBase) // 无延迟
back2.animate({ // 逐渐放大,并消失
r: r + 10,
opacity: 0.0,
repeat: true // 循环
},
3000, 'easeCubic', null, delayBase + 1000) // 1 秒延迟
back3.animate({ // 逐渐放大,并消失
r: r + 10,
opacity: 0.0,
repeat: true // 循环
},
3000, 'easeCubic', null, delayBase + 2000) // 2 秒延迟
}
},
'circle');
// custom the edge
G6.registerEdge('running-polyline', {
afterDraw(cfg, group) {
const shape = group.get('children')[0];
const length = shape.getTotalLength();
const startPoint = shape.getPoint(0);
let circleCount = Math.ceil(length / 20);
circleCount = circleCount === 0 ? 1 : circleCount;
for (let i = 0; i < circleCount; i++) {
const delay = Math.random() * 1000;
const start = shape.getPoint(i / circleCount);
const circle = group.addShape('circle', {
attrs: {
x: start.x,
y: start.y,
r: 0.8,
fill: '#A0F3AF',
shadowColor: '#fff',
shadowBlur: 30,
}
});
circle.animate({
onFrame(ratio) {
ratio += i / circleCount;
if (ratio > 1) {
ratio %= 1;
}
const tmpPoint = shape.getPoint(ratio);
return {
x: tmpPoint.x,
y: tmpPoint.y
};
},
repeat: true
}, 10 * length, 'easeCubic', null, delay);
}
}
},
'polyline');
const graphSize = [ 600, 600 ];
const graph = new G6.Graph({
container: 'mountNode',
width: graphSize[0],
height: graphSize[1],
modes: {
default: [{
type: 'edge-tooltip',
formatText(model) {
const text = model.class;
return text;
},
shouldUpdate: e => {
return true;
}
}]
},
defaultNode: {
shape: 'breath-node',
size: 3,
style: {
lineWidth: 0,
fill: 'rgb(240, 223, 83)'
}
},
defaultEdge: {
shape: 'running-polyline',
size: 1,
color: 'rgb(14,142,63)',
style: {
opacity: 0.4,
lineAppendWidth: 3
}
},
nodeStyle: {
default: {
lineWidth: 2,
fill: '#fff'
}
}
});
$.getJSON('./assets/data/beijing-metro-lines.json', data => {
const nodes = data.nodes;
const edges = data.edges;
const classMap = new Map();
let classId = 0;
nodes.forEach(node => {
node.y = -node.y;
});
edges.forEach(edge => {
// edge cluster
if (edge.class && classMap.get(edge.class) === undefined) {
classMap.set(edge.class, classId);
classId ++;
}
const cid = classMap.get(edge.class);
edge.color = colors[cid % colors.length];
const controlPoints = edge.controlPoints;
controlPoints.forEach(cp => {
cp.y = -cp.y;
});
})
scaleNodesPoints(nodes, edges, graphSize);
graph.data(data);
graph.render();
});
function scaleNodesPoints(nodes, edges, graphSize) {
const size = graphSize[0] < graphSize[1] ? graphSize[0] : graphSize[1];
let minX = 99999999999999999;
let maxX = -99999999999999999;
let minY = 99999999999999999;
let maxY = -99999999999999999;
nodes.forEach(node => {
if (node.x > maxX) maxX = node.x;
if (node.x < minX) minX = node.x;
if (node.y > maxY) maxY = node.y;
if (node.y < minY) minY = node.y;
});
edges.forEach(edge => {
const controlPoints = edge.controlPoints;
controlPoints.forEach(cp => {
if (cp.x > maxX) maxX = cp.x;
if (cp.x < minX) minX = cp.x;
if (cp.y > maxY) maxY = cp.y;
if (cp.y < minY) minY = cp.y;
});
});
const xScale = maxX - minX;
const yScale = maxY - minY;
nodes.forEach(node => {
node.orix = node.x;
node.oriy = node.y;
node.x = (node.x - minX) / xScale * size;
node.y = (node.y - minY) / yScale * size;
});
edges.forEach(edge => {
const controlPoints = edge.controlPoints;
controlPoints.forEach(cp => {
cp.x = (cp.x - minX) / xScale * size;
cp.y = (cp.y - minY) / yScale * size;
});
});
}
</script>
</body>
</html>