2021年3月30日星期二

Limit Number of Nodes & Links in D3 Force Graph After CSV is Parsed (Angular & D3.JS)

I'm working on an application where I am parsing a CSV file on the client-side in Angular and D3.JS to create a graph node and I have an issue where the .csv file rows are a large data set and it is considerably slowing down the application and crashing.

How can I limit the number of nodes and links so the application doesn't crash? The CSV Parser library I am using is NgxCsvParser.

client-parser.component

import { Component, OnInit } from '@angular/core';  import { Router } from '@angular/router';  import { NgxCsvParser } from 'ngx-csv-parser';  import { NgxCSVParserError } from 'ngx-csv-parser';      @Component({    selector: 'app-login',    templateUrl: './login.component.html',    styleUrls: ['./login.component.scss']  })    export class LoginComponent implements OnInit {    files: File[] = [];      connections: any[] = [];    header = true;    nodes: any[] = [];    links: any[] = [];        constructor(      public router: Router,      private ngxCsvParser: NgxCsvParser    ) {}      ngOnInit(): void {}        onSelect(event: {      addedFiles: any;    }) {      this.files.push(...event.addedFiles);        this.ngxCsvParser.parse(this.files[0], {          header: this.header,          delimiter: ','        })        .pipe().subscribe((result: Array < any > ) => {            this.connections = result;            this.nodes.push({            "firstName": "You",            "lastName": "",            "name": "You",            "company": ""          });            for (const source of this.connections) {            const sourceName = source["First Name"] + " " + source["Last Name"];              this.links.push({              "source": "You",              "target": sourceName            });              this.nodes.push({              "firstName": source["First Name"],              "lastName": source["Last Name"],              "name": sourceName,              "company": source["Company"]            });              for (const target of this.connections) {              const targetName = target["First Name"] + " " + target["Last Name"];              if (sourceName != targetName && source["Company"] == target["Company"]) {                this.links.push({                  "source": sourceName,                  "target": targetName                });              }            }              const graph = {              "nodes": this.nodes,              "links": this.links            }              console.log(graph);              localStorage.setItem('graph', JSON.stringify(graph));            }          }, (error: NgxCSVParserError) => {          console.log('Error', error);        });      //  this.router.navigateByUrl('/graph');      }      onRemove(event: File) {      console.log(event);      this.files.splice(this.files.indexOf(event), 1);    }    }  

d3.component

import { Component, OnInit } from '@angular/core';  import * as d3 from 'd3';  import {Node} from '../d3/models/node';  import {Link} from '../d3/models/link';      @Component({    selector: 'app-graph',    templateUrl: './graph.component.html',    styleUrls: ['./graph.component.scss']  })  export class GraphComponent implements OnInit {      constructor() { }      ngOnInit() {      const retrievedObject = localStorage.getItem('graph');      const graph = JSON.parse(retrievedObject);      this.loadForceDirectedGraph(graph.nodes, graph.links);      }      loadForceDirectedGraph(nodes: Node[], links: Link[]) {      const svg = d3.select('svg');      const width = +svg.attr('width');      const height = +svg.attr('height');        const color = d3.scaleOrdinal(d3.schemeBlues[9]);          const simulation = d3.forceSimulation()        .force('link', d3.forceLink().id((d: Node) => d.name))// the id of the node        .force("charge", d3.forceManyBody().strength(-5).distanceMax(0.5 * Math.min(width, height)))        .force('center', d3.forceCenter(width / 2, height / 2));        console.log(nodes, links);        const link = svg.append('g')        .attr('class', 'links')        .selectAll('line')        .data(links)        .enter()        .append('line')        .attr('stroke-width', d => Math.sqrt(d.index))        .attr('stroke', 'black');        const node = svg.append('g')        .attr('class', 'nodes')        .selectAll('circle')        .data(nodes)        .enter()        .append('circle')        .attr('r', 8)        .attr("fill", function(d) { return color(d.company); })        .call(d3.drag()          .on('start', dragStarted)          .on('drag', dragged)          .on('end', dragEnded)        );         node.append('text')              .text((d) => d.company)              .attr('x', 6)              .attr('y', 3);          node.append('title').text((d) => d.name);        simulation        .nodes(nodes)        .on('tick', ticked);        simulation.force<d3.ForceLink<any, any>>('link')        .links(links);        function ticked() {        node          .attr('cx', d => d.x)          .attr('cy', d => d.y);          link            .attr('x1', d => d.source.x)            .attr('y1', d => d.source.y)            .attr('x2', d => d.target.x)            .attr('y2', d => d.target.y);      }        function dragStarted(event) {        if (!event.active) { simulation.alphaTarget(0.3).restart(); }        event.subject.fx = event.subject.x;        event.subject.fy = event.subject.y;      }        function dragged(event) {        event.subject.fx = event.x;        event.subject.fy = event.y;      }        function dragEnded(event) {        if (!event.active) { simulation.alphaTarget(0); }        event.subject.fx = null;        event.subject.fy = null;      }    }    }  
https://stackoverflow.com/questions/66880693/limit-number-of-nodes-links-in-d3-force-graph-after-csv-is-parsed-angular-d March 31, 2021 at 10:05AM

没有评论:

发表评论