Skip to content

Commit

Permalink
add demo
Browse files Browse the repository at this point in the history
  • Loading branch information
semibran committed Mar 6, 2018
1 parent f6be136 commit f11b90b
Show file tree
Hide file tree
Showing 8 changed files with 285 additions and 1 deletion.
1 change: 0 additions & 1 deletion .gitignore

This file was deleted.

3 changes: 3 additions & 0 deletions demo/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
shrinkwrap.yaml
dist
31 changes: 31 additions & 0 deletions demo/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# GNU Make 3.8.2 and above

PATH := $(PATH):node_modules/.bin
SHELL := /bin/bash

.ONESHELL:
.SILENT:

all: clean
make html js css
babel dist/script.js --presets=env | uglifyjs -o dist/script.js -c -m
postcss dist/style.css -u autoprefixer -o dist/style.css -m
cleancss dist/style.css -o dist/style.css --source-map --source-map-inline-sources
html-minifier --collapse-whitespace dist/index.html -o dist/index.html
rm dist/script.js.map dist/style.css.map

clean:
rm -rf dist
mkdir dist

html:
cp src/index.html dist/index.html

js:
rollup src/script.js -o dist/script.js -f iife -c -m

css:
node-sass src/style.scss -o dist --source-map true --source-map-contents

deploy: all
gh-pages -d dist -m "updates"
28 changes: 28 additions & 0 deletions demo/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"name": "demo",
"version": "0.0.0",
"description": "demo for semibran/graph-mst",
"author": "semibran (Brandon Semilla)",
"license": "MIT",
"repository": "semibran/graph-mst",
"main": "src/script.js",
"keywords": [],
"devDependencies": {
"autoprefixer": "^8.1.0",
"babel-cli": "^6.26.0",
"babel-preset-env": "^1.6.1",
"clean-css-cli": "^4.1.11",
"gh-pages": "^1.1.0",
"html-minifier": "^3.5.10",
"node-sass": "^4.7.2",
"postcss-cli": "^5.0.0",
"rollup": "^0.56.4",
"rollup-plugin-commonjs": "^9.0.0",
"rollup-plugin-json": "^2.3.0",
"rollup-plugin-node-resolve": "^3.0.3",
"uglify-js": "^3.3.13"
},
"dependencies": {
"euclidean": "^0.0.0"
}
}
8 changes: 8 additions & 0 deletions demo/rollup.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import resolve from "rollup-plugin-node-resolve"
import commonjs from "rollup-plugin-commonjs"
import json from "rollup-plugin-json"

export default {
output: { name: "app" },
plugins: [ resolve(), commonjs(), json() ]
}
13 changes: 13 additions & 0 deletions demo/src/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8"/>
<title>graph-mst/demo</title>
<meta name="description" content="demo for semibran/graph-mst">
<meta name="author" content="semibran (Brandon Semilla)">
<meta name="keywords" content="">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0">
<link href="style.css" rel="stylesheet"/>
<script defer src="script.js"></script>
</head>
</html>
188 changes: 188 additions & 0 deletions demo/src/script.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
import span from "../../lib/graph-mst"
import euclidean from "euclidean"

const width = window.innerWidth
const height = window.innerHeight

let graph = {
edges: [],
nodes: new Array(128)
.fill()
.map(_ => {
let direction = Math.random() * 2 * Math.PI
let magnitude = Math.sqrt(Math.random())
return [
Math.cos(direction) * magnitude,
Math.sin(direction) * magnitude
]
})
}

graph.nodes.sort((a, b) => euclidean([ 0, 0 ], a) - euclidean([ 0, 0 ], b))

for (let i = 0; i < graph.nodes.length - 1; i++) {
for (let j = i + 1; j < graph.nodes.length; j++) {
graph.edges.push({
endpoints: [ i, j ],
weight: euclidean(graph.nodes[i], graph.nodes[j])
})
}
}

let tree = span(graph)
let state = {
graph: tree,
animation: {
time: 0,
phase: "spawn",
nodes: [],
edges: [],
lines: [],
history: []
},
viewport: {
scale: Math.min(width, height) / 2.5,
halfsize: [ width / 2, height / 2 ],
position: [ 0, 0 ]
}
}

let canvas = document.createElement("canvas")
let context = canvas.getContext("2d")
canvas.width = width
canvas.height = height
document.body.appendChild(canvas)
requestAnimationFrame(loop)

function loop() {
context.clearRect(0, 0, canvas.width, canvas.height)
let { graph, animation, viewport } = state
const scale = (x, i) => x * viewport.scale + viewport.halfsize[i]
let phase = animation[animation.phase]
if (animation.phase === "spawn") {
if (animation.time < graph.nodes.length) {
animation.nodes.push([ 0, 0 ])
}
let farthest = 0
for (let i = 0; i < animation.nodes.length; i++) {
let position = animation.nodes[i]
let target = graph.nodes[i]
let next = animation.nodes[i] = [
position[0] + (target[0] - position[0]) / 16,
position[1] + (target[1] - position[1]) / 16
]
let distance = euclidean(position, target)
if (distance > farthest) {
farthest = distance
}
}
if (farthest < 1 / 256) {
animation.phase = "connect"
animation.nodes = graph.nodes
}
} else if (animation.phase === "connect") {
let { lines, history } = animation
if (!lines.length) {
let best = { distance: Infinity, node: null }
for (let node of graph.nodes) {
let distance = Math.sqrt(node[0] * node[0] + node[1] * node[1])
if (distance < best.distance) {
best.distance = distance
best.node = node
}
}
history.push(best.node)
lines.push({
origin: best.node,
position: best.node.slice(),
target: null
})
}
for (let i = 0; i < lines.length; i++) {
let line = lines[i]
if (!line.target) {
for (let edge of graph.edges) {
let [ a, b ] = edge.endpoints.map(i => graph.nodes[i])
let target = null
if (a === line.origin) {
target = b
} else if (b === line.origin) {
target = a
}
if (target && history.indexOf(target) === -1) {
history.push(target)
if (!line.target) {
line.target = target
} else {
lines.push({
origin: line.origin,
position: line.origin.slice(),
target: target
})
}
}
}
if (!line.target) {
lines.splice(i--, 1)
continue
}
}
let distance = euclidean(line.position, line.target)
if (distance < 1 / 64) {
animation.edges.push([ line.origin, line.target ])
line.origin = line.target
line.position = line.target.slice()
line.target = null
if (animation.edges.length === graph.edges.length) {
animation.phase = "done"
}
} else {
let delta = [
line.target[0] - line.origin[0],
line.target[1] - line.origin[1]
]
let direction = Math.atan2(delta[1], delta[0])
line.position[0] += Math.cos(direction) * 1 / 64,
line.position[1] += Math.sin(direction) * 1 / 64
}
}
}

for (let line of animation.lines) {
context.strokeStyle = "gray"
context.beginPath()
context.moveTo(...line.origin.map(scale))
context.lineTo(...line.position.map(scale))
context.stroke()
}

for (let node of animation.nodes) {
context.fillStyle = "white"
context.beginPath()
context.arc(...node.map(scale), 1, 0, 2 * Math.PI)
context.fill()
}

for (let edge of animation.edges) {
let [ a, b ] = edge

context.strokeStyle = "white"
context.beginPath()
context.moveTo(...a.map(scale))
context.lineTo(...b.map(scale))
context.stroke()

context.fillStyle = "white"
context.beginPath()
context.arc(...a.map(scale), 2, 0, 2 * Math.PI)
context.fill()
context.beginPath()
context.arc(...b.map(scale), 2, 0, 2 * Math.PI)
context.fill()
}

if (animation.phase !== "done") {
animation.time++
requestAnimationFrame(loop)
}
}
14 changes: 14 additions & 0 deletions demo/src/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

html, body {
height: 100%;
}

body {
background: black;
overflow: hidden;
}

0 comments on commit f11b90b

Please sign in to comment.