Appearance
Animate to bounds
This example shows how to animate the camera to focus on a specific cluster. It uses the moveToBounds method to automatically compute the bouding box of the cluster and animate the camera to focus on it.
ts
import Ogma, { Easing } from '@linkurious/ogma';
const ogma = new Ogma({
container: 'graph-container'
});
ogma.styles.setSelectedNodeAttributes({
color: '#1499ff',
innerStroke: {
width: 1
},
outerStroke: {
color: '#1499ff'
}
});
function zoomToRandomHub() {
// get the list of big hubs
const nodes = ogma.getNodes();
const highDegreeNodes = ogma.getNodes().filter(n => n.getDegree() > 15);
const root = highDegreeNodes.get(
Math.floor(Math.random() * highDegreeNodes.size)
);
// get a random hub
const randomHub = root
.getAdjacentNodes()
.filter(n => n.getDegree() === 1)
.concat(root.toList());
// highlight the hub
nodes.setSelected(false);
randomHub.setSelected(true);
// animate to it
return ogma.view.moveToBounds(randomHub.getBoundingBox(), {
easing: (document.getElementById('easing')! as HTMLInputElement)
.value as Easing
});
}
ogma.generate
.barabasiAlbert({
nodes: 1600,
m0: 10,
m: 1
})
.then(ogma.setGraph)
.then(() =>
ogma.layouts.force({
autoStop: true,
gravity: 0.001,
duration: 0
})
)
.then(() => ogma.view.locateGraph())
.then(() => setTimeout(startAnimation, 500));
const playButton = document.getElementById('play-button') as HTMLInputElement;
const stepButton = document.getElementById('step-button') as HTMLButtonElement;
let timer = 0;
let animating = playButton.checked;
function animate() {
if (animating) {
zoomToRandomHub().then(() => {
// @ts-expect-error
timer = setTimeout(animate, 1000);
});
}
}
function startAnimation() {
if (!animating) {
animating = true;
animate();
stepButton.setAttribute('disabled', 'disabled');
} else {
clearTimeout(timer);
animating = false;
stepButton.removeAttribute('disabled');
}
}
function step() {
zoomToRandomHub();
}
playButton.addEventListener('click', startAnimation);
stepButton.addEventListener('click', step);
startAnimation();
html
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<link
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.14.0/css/solid.min.css"
rel="stylesheet"
/>
<link
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.14.0/css/fontawesome.min.css"
rel="stylesheet"
/>
<link type="text/css" rel="stylesheet" href="styles.css" />
</head>
<body>
<div id="graph-container"></div>
<div id="controls">
<label
>Easing
<select id="easing">
<option value="quadraticOut">quadraticOut</option>
<option value="linear">linear</option>
<option value="quadraticIn">quadraticIn</option>
<option value="quadraticInOut">quadraticInOut</option>
<option value="cubicIn">cubicIn</option>
<option value="cubicOut">cubicOut</option>
<option value="cubicInOut">cubicInOut</option>
</select>
</label>
<p>
<label><input type="checkbox" id="play-button" checked />Repeat</label>
<button id="step-button" disabled>
<i class="fas fa-step-forward"></i>
</button>
</p>
</div>
<script type="module" src="index.ts"></script>
</body>
</html>
css
#graph-container {
top: 0;
bottom: 0;
left: 0;
right: 0;
position: absolute;
margin: 0;
overflow: hidden;
}
#controls {
font-family: Georgia, 'Times New Roman', Times, serif;
position: absolute;
background: #ffffff;
padding: 15px;
top: 20px;
right: 20px;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.5);
border-radius: 5px;
}