Skip to content

Commit

Permalink
Readme.md fixes and styles
Browse files Browse the repository at this point in the history
  • Loading branch information
gr1m1um committed Jun 20, 2021
1 parent 18b4007 commit 637d06d
Show file tree
Hide file tree
Showing 7 changed files with 263 additions and 24 deletions.
17 changes: 17 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
129 changes: 120 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
-------

# vnodes

Vue bare components to create svg interactive graphs, diagrams or node visual tools.

### Demo
### Demo

https://txlabs.github.io/vnodes/

Expand All @@ -25,8 +23,8 @@ https://txlabs.github.io/vnodes/
import { Screen, Node, Edge, graph } from 'vnodes'
export default {
components: {
Screen,
Node,
Screen,
Node,
Edge
}
data () {
Expand All @@ -45,7 +43,120 @@ export default {

## Components

- Screen - svg wrapper with zoom, panning and others
- Node - svg element that contain html
- Edge - connect nodes using svg lines
- Group - surround nodes with a container
Vnodes components are independent and can be used anywhere in your project.

### Screen

Svg wrapper with zoom, panning and other features.

```html
<screen width="300" height="500">
<circle cx="50" cy="50" r="50" fill="red"/>
</screen>
```

### Node

Html wrapper for svg with additional features like, dragging and fitting contents.


```html
<svg width="500" height="500">
<node :data="{
id: 'test',
x: 100,
y: 100,
width: 250,
height: 150}">
<h1>My First Node!</h1>
</node>
</svg>
```

### Edge

Connects nodes using svg lines

```html
<edge :data="{
from: { x: 0, y: 0},
to: { x: 100, y: 100}}"
></edge>
```

Edges data require node references `{ from: String|Object, to: String:Object }`, if nodes are refered by id(String) edges must also include an array with those `nodes` as property.


Edges can take **anchor** information to offset their position relative to a node,

```html
<edge :data="{
from: nodes[0],
to: nodes[1],
fromAnchor: 'center',
toAnchor: 'top-left'
}">
```
anchors format can be:

* String `'center', 'left', 'right', 'top', 'top-left', 'top-right', 'bottom', 'bottom-left', 'bottom-right', 'cirlce', 'rect'`

* Object `{ x?:Number | String, y?: Number | String, align?: String, snap?: String }`

Examples of valid anchor values:

```js
null
{ x: 0, y: 0} // snaps to top left corner
{ x: 10, y: 0 } // offsets x,y by 10 pixels
{ x: '50%', '50%' } // snaps to center
{ x: '50%', '50%', snap: 'rect' } // offsets around node rectangle
{ align: 'bottom-right' } // same as { x: '100%', y: '100% }
'center' // same as { x: '50%', y: '50%' }
'top-left' // same as { x: 0, y: 0 }
'circle' // offsets to circle with radius node.width/2
'rect' // offsets around node rectangle
```

### Group

Surround nodes with a visible container, allows dragging multiple nodes,

```html
<group :nodes="nodes">
<h1>Group Label</h1>
</group>
```


### Port

Helper component to offset an edge anchor to a specific position inside the html of a node.

### graph

Graph utils that can be used to store edges and nodes.
Contains utility methods to build graphs, position nodes remove and create nodes, edges etc.

## Styling

The simplest way to style nodes / edges is using CSS

### Markers

TODO

```css
<style>
.node .content {
border-radius: 50%;
background-color: red;
}

.edge {
stroke-width: 10;
stroke: blue;
marker-start: url(#arrow-start);
}
</style>
```
16 changes: 10 additions & 6 deletions src/components/Edge.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@ export default {
},
nodes: { // graph nodes reference
type: Array,
required: true
}
},
computed: {
fromNode: vm => vm.nodes.find(n => n.id === vm.data.from),
toNode: vm => vm.nodes.find(n => n.id === vm.data.to),
fromNode: vm => typeof vm.data.from === 'string'
? vm.nodes.find(n => n.id === vm.data.from)
: vm.data.from,
toNode: vm => typeof vm.data.to === 'string'
? vm.nodes.find(n => n.id === vm.data.to)
: vm.data.to,
fromAnchor: vm => vm.parseAnchor(vm.data.fromAnchor, vm.fromNode),
toAnchor: vm => vm.parseAnchor(vm.data.toAnchor, vm.toNode),
Expand All @@ -29,7 +32,7 @@ export default {
let x2 = this.toNode.x + (this.toAnchor.x || 0)
let y2 = this.toNode.y + (this.toAnchor.y || 0)
if (this.fromAnchor.snap) {
if (this.fromAnchor?.snap) {
if (this.fromAnchor.snap === 'circle') {
const radius = Math.max(this.fromNode.width, this.fromNode.height) / 2
const vec = new Victor(x2 - x1, y2 - y1).normalize()
Expand All @@ -44,7 +47,7 @@ export default {
}
}
}
if (this.toAnchor.snap) {
if (this.toAnchor?.snap) {
if (this.toAnchor.snap === 'circle') {
const radius = Math.max(this.toNode.width, this.toNode.height) / 2
const vec = new Victor(x2 - x1, y2 - y1).normalize()
Expand Down Expand Up @@ -95,6 +98,7 @@ export default {
* }
*/
parseAnchor(anchor, node) {
if (!anchor) return { x: 0, y: 0 }
let snap = anchor.snap
let align = anchor.align
let pos = { x: anchor.x || 0, y: anchor.y || 0 }
Expand Down Expand Up @@ -162,7 +166,7 @@ export default {
<style lang="stylus" scoped>
.edge
stroke-width: 2
stroke-width: 4
stroke: green
// marker-start: url(#arrow-start)
marker-end: url(#arrow-end)
Expand Down
4 changes: 2 additions & 2 deletions src/components/Markers.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@
const defaults = [{
id: 'arrow-start',
type: 'arrow-start',
scale: 1,
scale: 0.5,
style: 'fill: green'
},
{
id: 'arrow-end',
type: 'arrow-end',
scale: 1,
scale: 0.5,
style: 'fill: green'
}]
Expand Down
99 changes: 99 additions & 0 deletions src/demo/Benchmark.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<template>
<div class="demo" id="benchmark-demo">
<div class="viewport">
<screen ref="screen" :options="{onUpdatedCTM: test}">
<edge v-for="edge in graph.edges" :data="edge" :nodes="graph.nodes" :key="edge.id">
</edge>
<node :data="node" ref="node" v-for="node in graph.nodes" :key="node.id">
</node>
</screen>
</div>
<div class="sidebar">
<div ref="fps" style="margin-bottom:10px"></div>
<span>Node Count</span>
<input type="number" v-model=nodeCount>
<!-- fps # -->
<!-- virtualized yes/no -->
<!-- hidden nodes -->
<!-- hidden edges -->
<!-- group nodes + filter -->
</div>
</div>
</template>

<script>
import Screen from '../components/Screen'
import Node from '../components/Node'
import Edge from '../components/Edge'
import graph from '../graph'
import Stats from 'stats.js'
export default {
components: {
Screen,
Node,
Edge,
},
data() {
return {
graph: new graph(),
nodeCount: 100,
}
},
methods: {
test (e) {
console.log('test', e)
},
makeGraph () {
this.graph.reset();
this.graph.createNode('0')
for (let i=1; i < this.nodeCount; i++) {
const parent = this.graph.nodes[Math.round(Math.random() * (this.graph.nodes.length - 1))]
const node = this.graph.createNode({
id: String(i),
x: Math.random() * this.nodeCount * 12,
y: Math.random() * this.nodeCount * 12
})
this.graph.createEdge(parent, node, { type: 'smooth' })
}
this.$refs.screen.zoomNodes(this.graph.nodes)
},
},
mounted () {
this.makeGraph()
const stats = new Stats()
stats.setMode(1)
stats.domElement.style.setProperty('position', 'relative')
this.$refs.fps.appendChild(stats.domElement)
function animate() {
stats.begin()
requestAnimationFrame(() => {
stats.end()
animate()
})
}
animate()
},
watch: {
nodeCount: 'makeGraph'
}
}
</script>

<style lang="stylus">
#benchmark-demo
.node .content
// background-color #14c56a
background-color: #47696e;
color: white;
.node:hover .content
background-color red
.edge
stroke #ccc
stroke-width 4
marker-end: none
.edge:hover
stroke: red
</style>
22 changes: 15 additions & 7 deletions src/demo/Demo.vue
Original file line number Diff line number Diff line change
@@ -1,28 +1,36 @@
<template>
<div style="margin-top: 50px; margin-bottom: 50px">
<h2>Vnodes</h2>
<h1>Vnodes</h1>

<h2>Sink</h2>
<sink>
</sink>

<h2>Edit</h2>
<h2>Html</h2>
<edit>
</edit>

<h2>Groups and Ports</h2>
<groups>
</groups>
<h2>Ports</h2>
<ports>
</ports>

<h2>Benchpress</h2>
<benchpress>
</benchpress>
</div>
</template>

<script>
import Sink from './Sink'
import Edit from './Edit'
import Groups from './Groups'
import Ports from './Ports'
import Benchpress from './Benchmark'
export default {
components: {
Sink,
Edit,
Groups,
Ports,
Benchpress
},
}
</script>
Expand Down
File renamed without changes.

0 comments on commit 637d06d

Please sign in to comment.