feat: ngx-graph automatic fit to screen and dynamic data
This commit is contained in:
parent
93b7cd3959
commit
34fccf5982
@ -1,122 +1,101 @@
|
|||||||
<div>
|
<div>
|
||||||
<h1>Slow shit</h1>
|
<h1>Slow shit</h1>
|
||||||
<app-graph-component></app-graph-component>
|
<app-graph-component></app-graph-component>
|
||||||
<ngx-graph
|
<!--
|
||||||
class="chart-container"
|
<ngx-graph [links]="links" [nodes]="nodes" [clusters]="clusters" [curve]="curve" [layout]="layout"
|
||||||
[view]="[800, 550]"
|
[layoutSettings]="layoutSettings" [enableZoom]="false" [draggingEnabled]="false" [panningEnabled]="false"
|
||||||
[links]="[
|
[autoZoom]="true" [autoCenter]="true" [animate]="false" [update$]="update$" [center$]="center$"
|
||||||
|
[zoomToFit$]="zoomToFit$" (window:resize)="onResize($event)">
|
||||||
|
-->
|
||||||
|
<button (click)="handleAddNode()">+</button>
|
||||||
|
<div style="border: 1px solid #ff0000;width: 800px;height: 500px;position: relative">
|
||||||
|
<ngx-graph
|
||||||
|
class="chart-container"
|
||||||
|
[view]="[800, 500]"
|
||||||
|
[draggingEnabled]="false"
|
||||||
|
[links]="links"
|
||||||
|
[nodes]="nodes"
|
||||||
|
[update$]="update$"
|
||||||
|
[zoomToFit$]="zoom$"
|
||||||
|
[clusters]="[
|
||||||
{
|
{
|
||||||
id: 'a',
|
id: 'asdf',
|
||||||
source: 'first',
|
|
||||||
target: 'second',
|
|
||||||
label: 'is parent of'
|
|
||||||
}, {
|
|
||||||
id: 'b',
|
|
||||||
source: 'first',
|
|
||||||
target: 'c1',
|
|
||||||
label: 'custom label'
|
|
||||||
}, {
|
|
||||||
id: 'd',
|
|
||||||
source: 'first',
|
|
||||||
target: 'c2',
|
|
||||||
label: 'custom label'
|
|
||||||
}, {
|
|
||||||
id: 'e',
|
|
||||||
source: 'c1',
|
|
||||||
target: 'd',
|
|
||||||
label: 'first link'
|
|
||||||
}, {
|
|
||||||
id: 'f',
|
|
||||||
source: 'c1',
|
|
||||||
target: 'd',
|
|
||||||
label: 'second link'
|
|
||||||
}
|
|
||||||
]"
|
|
||||||
[nodes]="[
|
|
||||||
{
|
|
||||||
id: 'first',
|
|
||||||
label: 'A'
|
|
||||||
}, {
|
|
||||||
id: 'second',
|
|
||||||
label: 'B'
|
|
||||||
}, {
|
|
||||||
id: 'c1',
|
|
||||||
label: 'C1'
|
|
||||||
}, {
|
|
||||||
id: 'c2',
|
|
||||||
label: 'C2'
|
|
||||||
}, {
|
|
||||||
id: 'd',
|
|
||||||
label: 'D'
|
|
||||||
}
|
|
||||||
]"
|
|
||||||
[clusters]="[
|
|
||||||
{
|
|
||||||
id: 'third',
|
|
||||||
label: 'Cluster node',
|
label: 'Cluster node',
|
||||||
childNodeIds: ['c1', 'c2']
|
childNodeIds: ['c1', 'd'],
|
||||||
|
data: {
|
||||||
|
fill: '#fff000'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'asdfg',
|
||||||
|
label: 'Cluster node 2',
|
||||||
|
childNodeIds: ['first', 'c2'],
|
||||||
|
data: {
|
||||||
|
fill: '#ff0000'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]"
|
]"
|
||||||
layout="dagreCluster"
|
layout="dagreCluster"
|
||||||
(select)="handleNodeSelect($event)"
|
(select)="handleNodeSelect($event)"
|
||||||
>
|
>
|
||||||
<ng-template #defsTemplate>
|
<ng-template #defsTemplate>
|
||||||
<svg:marker id="arrow" viewBox="0 -5 10 10" refX="8" refY="0" markerWidth="4" markerHeight="4" orient="auto">
|
<svg:marker id="arrow" viewBox="0 -5 10 10" refX="8" refY="0" markerWidth="4" markerHeight="4" orient="auto">
|
||||||
<svg:path d="M0,-5L10,0L0,5" class="arrow-head" />
|
<svg:path d="M0,-5L10,0L0,5" class="arrow-head" />
|
||||||
</svg:marker>
|
</svg:marker>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
<ng-template #clusterTemplate let-cluster>
|
<ng-template #clusterTemplate let-cluster>
|
||||||
<svg:g class="node cluster">
|
<svg:g class="node cluster">
|
||||||
<svg:rect
|
<svg:rect
|
||||||
rx="5"
|
rx="5"
|
||||||
ry="5"
|
ry="5"
|
||||||
[attr.width]="cluster.dimension.width"
|
[attr.width]="cluster.dimension.width"
|
||||||
[attr.height]="cluster.dimension.height"
|
[attr.height]="cluster.dimension.height"
|
||||||
[attr.fill]="cluster.data.color"
|
[attr.fill]="cluster.data.fill"
|
||||||
/>
|
/>
|
||||||
</svg:g>
|
</svg:g>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
<ng-template #nodeTemplate let-node>
|
<ng-template #nodeTemplate let-node>
|
||||||
<svg:g class="node">
|
<svg:g class="node">
|
||||||
<svg:rect
|
<svg:rect
|
||||||
[attr.width]="node.dimension.width"
|
[attr.width]="node.dimension.width"
|
||||||
[attr.height]="node.dimension.height"
|
[attr.height]="node.dimension.height"
|
||||||
[attr.fill]="node.data.color"
|
[attr.fill]="node.data.color"
|
||||||
/>
|
/>
|
||||||
<svg:text alignment-baseline="central" [attr.x]="10" [attr.y]="node.dimension.height / 2">
|
<svg:text alignment-baseline="central" [attr.x]="10" [attr.y]="node.dimension.height / 2">
|
||||||
{{node.label}}
|
{{node.label}}
|
||||||
</svg:text>
|
</svg:text>
|
||||||
<!--<foreignObject width="100%" height="100%">
|
<!--<foreignObject width="100%" height="100%">
|
||||||
<xhtml:div>
|
<xhtml:div>
|
||||||
<xhtml:div #source style="border:1px green solid;width: fit-content;margin-left:200px;margin-top:50px;">
|
<xhtml:div #source style="border:1px green solid;width: fit-content;margin-left:200px;margin-top:50px;">
|
||||||
I'm a div inside a SVG.
|
I'm a div inside a SVG.
|
||||||
|
</xhtml:div>
|
||||||
|
<xhtml:p #target style="border:1px green solid;width: fit-content;margin-left:10px;margin-top:120px">
|
||||||
|
I'm a second div inside a SVG.
|
||||||
|
</xhtml:p>
|
||||||
</xhtml:div>
|
</xhtml:div>
|
||||||
<xhtml:p #target style="border:1px green solid;width: fit-content;margin-left:10px;margin-top:120px">
|
</foreignObject>-->
|
||||||
I'm a second div inside a SVG.
|
</svg:g>
|
||||||
</xhtml:p>
|
</ng-template>
|
||||||
</xhtml:div>
|
|
||||||
</foreignObject>-->
|
|
||||||
</svg:g>
|
|
||||||
</ng-template>
|
|
||||||
|
|
||||||
<ng-template #linkTemplate let-link>
|
<ng-template #linkTemplate let-link>
|
||||||
<svg:g class="edge">
|
<svg:g class="edge">
|
||||||
<svg:path class="line" stroke-width="2" marker-end="url(#arrow)"></svg:path>
|
<svg:path class="line" stroke-width="2" marker-end="url(#arrow)"></svg:path>
|
||||||
<svg:text class="edge-label" text-anchor="middle">
|
<svg:text class="edge-label" text-anchor="middle">
|
||||||
<textPath
|
<textPath
|
||||||
class="text-path"
|
class="text-path"
|
||||||
[attr.href]="'#' + link.id"
|
[attr.href]="'#' + link.id"
|
||||||
[style.dominant-baseline]="link.dominantBaseline"
|
[style.dominant-baseline]="link.dominantBaseline"
|
||||||
startOffset="50%"
|
startOffset="50%"
|
||||||
>
|
>
|
||||||
{{link.label}}
|
{{link.label}}
|
||||||
</textPath>
|
</textPath>
|
||||||
</svg:text>
|
</svg:text>
|
||||||
</svg:g>
|
</svg:g>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</ngx-graph>
|
</ngx-graph>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<router-outlet />
|
<router-outlet />
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
import {Component} from "@angular/core";
|
import {AfterViewInit, Component} from "@angular/core";
|
||||||
import { RouterOutlet } from '@angular/router';
|
import { RouterOutlet } from '@angular/router';
|
||||||
import {GraphModule} from "./view/graph/graph.module";
|
import {GraphModule} from "./view/graph/graph.module";
|
||||||
import {NgxGraphModule} from "@kr0san89/ngx-graph";
|
import {NgxGraphModule} from "@kr0san89/ngx-graph";
|
||||||
|
import {randomString} from "./utils/utils";
|
||||||
|
import {Subject} from "rxjs";
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -11,9 +13,78 @@ import {NgxGraphModule} from "@kr0san89/ngx-graph";
|
|||||||
templateUrl: './app.component.html',
|
templateUrl: './app.component.html',
|
||||||
styleUrl: './app.component.scss'
|
styleUrl: './app.component.scss'
|
||||||
})
|
})
|
||||||
export class AppComponent {
|
export class AppComponent implements AfterViewInit {
|
||||||
|
update$ = new Subject<boolean>();
|
||||||
|
zoom$ = new Subject<any>();
|
||||||
|
links: any = []
|
||||||
|
|
||||||
|
nodes: any = []
|
||||||
|
|
||||||
|
ngAfterViewInit() {
|
||||||
|
this.nodes = [
|
||||||
|
{
|
||||||
|
id: 'first',
|
||||||
|
label: 'A'
|
||||||
|
}, {
|
||||||
|
id: 'second',
|
||||||
|
label: 'B'
|
||||||
|
}, {
|
||||||
|
id: 'c1',
|
||||||
|
label: 'C1'
|
||||||
|
}, {
|
||||||
|
id: 'c2',
|
||||||
|
label: 'C2'
|
||||||
|
}, {
|
||||||
|
id: 'd',
|
||||||
|
label: 'D'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
this.links = [
|
||||||
|
{
|
||||||
|
id: 'a',
|
||||||
|
source: 'first',
|
||||||
|
target: 'second',
|
||||||
|
label: 'is parent of'
|
||||||
|
}, {
|
||||||
|
id: 'b',
|
||||||
|
source: 'first',
|
||||||
|
target: 'c1',
|
||||||
|
label: 'custom label'
|
||||||
|
}, {
|
||||||
|
id: 'd',
|
||||||
|
source: 'first',
|
||||||
|
target: 'c2',
|
||||||
|
label: 'custom label'
|
||||||
|
}, {
|
||||||
|
id: 'e',
|
||||||
|
source: 'c1',
|
||||||
|
target: 'd',
|
||||||
|
label: 'first link'
|
||||||
|
}, {
|
||||||
|
id: 'f',
|
||||||
|
source: 'c1',
|
||||||
|
target: 'd',
|
||||||
|
label: 'second link'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
setTimeout(() => {
|
||||||
|
this.zoom$.next({ force: true, autoCenter: true })
|
||||||
|
}, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
handleAddNode = () => {
|
||||||
|
const node = {id: randomString(5), label: randomString(5)}
|
||||||
|
this.nodes.push(node)
|
||||||
|
console.log('node', node)
|
||||||
|
this.update$.next(true)
|
||||||
|
this.zoom$.next(true)
|
||||||
|
}
|
||||||
|
|
||||||
handleNodeSelect = (event: any) => {
|
handleNodeSelect = (event: any) => {
|
||||||
console.log('handleNodeSelect', event)
|
console.log('handleNodeSelect', event)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toJSON = (val: any) => {
|
||||||
|
return JSON.stringify(val)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user