165 lines
4.7 KiB
HTML
165 lines
4.7 KiB
HTML
|
<!doctype html>
|
||
|
<html lang="en">
|
||
|
<head>
|
||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||
|
|
||
|
<title>PIXI ForceLayout</title>
|
||
|
|
||
|
<link rel="stylesheet" href="../3rdparty/highlight/styles/default.css">
|
||
|
<link rel="stylesheet" href="../../css/doctest.css">
|
||
|
|
||
|
<script src="../3rdparty/highlight/highlight.pack.js"></script>
|
||
|
<script src="../3rdparty/all.js"></script>
|
||
|
|
||
|
<script src="../all.js"></script>
|
||
|
<script src="./all.js"></script>
|
||
|
|
||
|
<script src="./lib/graphology.min.js"></script>
|
||
|
<script src="./lib/graphology-layout-forceatlas2.js"></script>
|
||
|
</head>
|
||
|
<body onload="Doctest.run()">
|
||
|
<h1>ForceLayout</h1>
|
||
|
<p>
|
||
|
Comparison of a <a href="https://github.com/d3/d3-force/blob/master/README.md">D3 ForceLayout</a> with a <a href="https://github.com/graphology/graphology-layout-forceatlas2">ForceAtlas 2</a> forcelayout.
|
||
|
</p>
|
||
|
<h2>Let's look at the D3 ForceLayout:</h2><br />
|
||
|
<canvas id="canvas" class="interactive"></canvas>
|
||
|
<script class="doctest">
|
||
|
|
||
|
const app = new PIXIApp({
|
||
|
view: canvas,
|
||
|
width: 900,
|
||
|
height: 420,
|
||
|
transparent: false
|
||
|
}).setup().run()
|
||
|
|
||
|
app.loadTextures([
|
||
|
'./assets/circle.png'
|
||
|
], textures => {
|
||
|
|
||
|
// add sprites
|
||
|
//--------------------
|
||
|
const sprites = []
|
||
|
|
||
|
for (let i = 0; i < 100; i++) {
|
||
|
const sprite = new PIXI.Sprite(textures.get('./assets/circle.png'))
|
||
|
sprite.x = randomInt(0, app.size.width)
|
||
|
sprite.y = randomInt(0, app.size.height)
|
||
|
sprite.width = sprite.height = 2
|
||
|
sprite.anchor.set(.5, .5)
|
||
|
sprite.__random = Math.random()
|
||
|
sprites.push(sprite)
|
||
|
}
|
||
|
|
||
|
app.scene.addChild(...sprites)
|
||
|
|
||
|
// force simulation
|
||
|
//--------------------
|
||
|
const forceCollide = d3.forceCollide().radius(d => d.width / 2 + 1)
|
||
|
const simulation = d3.forceSimulation(sprites)
|
||
|
.on('tick', () => {
|
||
|
//forceCollide.radius(d => d.radius)
|
||
|
})
|
||
|
.force('collide', forceCollide)
|
||
|
.force('x', d3.forceX(app.center.x))
|
||
|
.force('y', d3.forceY(app.center.y))
|
||
|
.stop()
|
||
|
.force('radial', d3.forceRadial(d => {
|
||
|
return d.__random < .5 ? 60 : 160
|
||
|
}, app.center.x, app.center.y))
|
||
|
|
||
|
d3.timeout(() => {
|
||
|
simulation.restart()
|
||
|
}, 500)
|
||
|
|
||
|
}, {resolutionDependent: false})
|
||
|
|
||
|
</script>
|
||
|
|
||
|
<h2>D3 ForceLayout with links:</h2><br />
|
||
|
<canvas id="canvas2" class="interactive"></canvas>
|
||
|
<script class="doctest">
|
||
|
|
||
|
const app2 = new PIXIApp({
|
||
|
view: canvas2,
|
||
|
width: 900,
|
||
|
height: 420,
|
||
|
transparent: false
|
||
|
}).setup().run()
|
||
|
|
||
|
app2.loadTextures([
|
||
|
'./assets/circle2.png'
|
||
|
], textures => {
|
||
|
|
||
|
// add sprites
|
||
|
//--------------------
|
||
|
const sprites = []
|
||
|
|
||
|
for (let i = 0; i < 100; i++) {
|
||
|
const sprite = new PIXI.Sprite(textures.get('./assets/circle2.png'))
|
||
|
sprite.id = i
|
||
|
sprite.x = randomInt(0, app2.size.width)
|
||
|
sprite.y = randomInt(0, app2.size.height)
|
||
|
sprite.width = sprite.height = 16
|
||
|
sprite.anchor.set(.5, .5)
|
||
|
sprites.push(sprite)
|
||
|
}
|
||
|
|
||
|
app2.scene.addChild(...sprites)
|
||
|
|
||
|
const links = new PIXI.Graphics()
|
||
|
app2.scene.addChildAt(links, 0)
|
||
|
|
||
|
// force simulation
|
||
|
//--------------------
|
||
|
const forceCollide = d3.forceCollide().radius(d => d.width / 2 + 4)
|
||
|
const forceLink = d3.forceLink([
|
||
|
{source: 88, target: 8},
|
||
|
{source: 47, target: 55},
|
||
|
{source: 70, target: 1},
|
||
|
{source: 12, target: 12},
|
||
|
{source: 26, target: 33},
|
||
|
{source: 48, target: 53},
|
||
|
{source: 10, target: 70},
|
||
|
{source: 68, target: 61},
|
||
|
{source: 28, target: 65},
|
||
|
{source: 12, target: 34},
|
||
|
{source: 6, target: 55},
|
||
|
{source: 9, target: 16},
|
||
|
{source: 87, target: 96},
|
||
|
{source: 64, target: 24},
|
||
|
{source: 98, target: 14},
|
||
|
{source: 18, target: 23},
|
||
|
{source: 53, target: 62},
|
||
|
{source: 11, target: 53},
|
||
|
{source: 43, target: 23},
|
||
|
{source: 80, target: 9},
|
||
|
{source: 72, target: 88},
|
||
|
{source: 62, target: 3},
|
||
|
{source: 72, target: 15},
|
||
|
{source: 84, target: 25},
|
||
|
{source: 57, target: 58},
|
||
|
{source: 87, target: 19}
|
||
|
]).id(d => d.id).strength(.05)
|
||
|
const simulation = d3.forceSimulation(sprites)
|
||
|
.on('tick', () => {
|
||
|
links.clear()
|
||
|
links.lineStyle(1, 0xfdc02f)
|
||
|
for (let link of forceLink.links()) {
|
||
|
links.moveTo(link.source.x, link.source.y)
|
||
|
links.lineTo(link.target.x, link.target.y)
|
||
|
}
|
||
|
})
|
||
|
.force('collide', forceCollide)
|
||
|
.force('link', forceLink)
|
||
|
.stop()
|
||
|
|
||
|
d3.timeout(() => {
|
||
|
simulation.restart()
|
||
|
}, 1000)
|
||
|
|
||
|
}, {resolutionDependent: false})
|
||
|
|
||
|
</script>
|
||
|
</body>
|