├── .angular-cli.json ├── .editorconfig ├── .gitignore ├── README.md ├── package.json ├── src ├── app │ ├── app.component.css │ ├── app.component.html │ ├── app.component.ts │ ├── app.config.ts │ ├── app.module.ts │ ├── d3 │ │ ├── d3.service.ts │ │ ├── directives │ │ │ ├── draggable.directive.ts │ │ │ ├── index.ts │ │ │ └── zoomable.directive.ts │ │ ├── index.ts │ │ └── models │ │ │ ├── force-directed-graph.ts │ │ │ ├── index.ts │ │ │ ├── link.ts │ │ │ └── node.ts │ └── visuals │ │ ├── graph │ │ ├── graph.component.css │ │ └── graph.component.ts │ │ └── shared │ │ ├── index.ts │ │ ├── link-visual │ │ ├── link-visual.component.css │ │ └── link-visual.component.ts │ │ └── node-visual │ │ ├── node-visual.component.css │ │ └── node-visual.component.ts ├── assets │ └── .gitkeep ├── environments │ ├── environment.prod.ts │ └── environment.ts ├── favicon.ico ├── index.html ├── main.ts ├── polyfills.ts ├── styles.css └── tsconfig.json └── tslint.json /.angular-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "project": { 3 | "version": "1.0.0-beta.26", 4 | "name": "angular-d3-graph-example" 5 | }, 6 | "apps": [ 7 | { 8 | "root": "src", 9 | "outDir": "dist", 10 | "assets": [ 11 | "assets", 12 | "favicon.ico" 13 | ], 14 | "index": "index.html", 15 | "main": "main.ts", 16 | "polyfills": "polyfills.ts", 17 | "tsconfig": "tsconfig.json", 18 | "prefix": "app", 19 | "mobile": false, 20 | "styles": [ 21 | "styles.css" 22 | ], 23 | "scripts": [], 24 | "environmentSource": "environments/environment.ts", 25 | "environments": { 26 | "dev": "environments/environment.ts", 27 | "prod": "environments/environment.prod.ts" 28 | } 29 | } 30 | ], 31 | "e2e": { 32 | "protractor": { 33 | "config": "./protractor.conf.js" 34 | } 35 | }, 36 | "test": { 37 | "karma": { 38 | "config": "./karma.conf.js" 39 | } 40 | }, 41 | "defaults": { 42 | "styleExt": "css", 43 | "prefixInterfaces": false, 44 | "inline": { 45 | "style": false, 46 | "template": true 47 | }, 48 | "spec": { 49 | "class": false, 50 | "component": false, 51 | "directive": false, 52 | "module": false, 53 | "pipe": false, 54 | "service": false 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | 7 | # dependencies 8 | /node_modules 9 | 10 | # IDEs and editors 11 | /.idea 12 | .project 13 | .classpath 14 | .c9/ 15 | *.launch 16 | .settings/ 17 | 18 | # IDE - VSCode 19 | .vscode/* 20 | !.vscode/settings.json 21 | !.vscode/tasks.json 22 | !.vscode/launch.json 23 | !.vscode/extensions.json 24 | 25 | # misc 26 | /.sass-cache 27 | /connect.lock 28 | /coverage/* 29 | /libpeerconnection.log 30 | npm-debug.log 31 | testem.log 32 | /typings 33 | 34 | # e2e 35 | /e2e/*.js 36 | /e2e/*.map 37 | 38 | #System Files 39 | .DS_Store 40 | Thumbs.db 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Angular D3 Graph Example 2 | 3 | This is the code of a short tutorial [published on medium](https://medium.com/@lsharir/visualizing-data-with-angular-and-d3-209dde784aeb) 4 | 5 | This project was generated with [angular-cli](https://github.com/angular/angular-cli) version 1.0.0-beta.26. 6 | 7 | ## Development server 8 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-d3-graph-example", 3 | "version": "0.0.1", 4 | "license": "MIT", 5 | "angular-cli": {}, 6 | "scripts": { 7 | "ng": "ng", 8 | "start": "ng serve", 9 | "lint": "ng lint" 10 | }, 11 | "private": true, 12 | "dependencies": { 13 | "@angular/common": "^5.0.1", 14 | "@angular/compiler": "^5.0.1", 15 | "@angular/core": "^5.0.1", 16 | "@angular/forms": "^5.0.1", 17 | "@angular/http": "^5.0.1", 18 | "@angular/platform-browser": "^5.0.1", 19 | "@angular/platform-browser-dynamic": "^5.0.1", 20 | "@angular/router": "^5.0.1", 21 | "core-js": "^2.4.1", 22 | "d3": "^4.11.0", 23 | "rxjs": "^5.5.2", 24 | "ts-helpers": "^1.1.2", 25 | "zone.js": "^0.8.14" 26 | }, 27 | "devDependencies": { 28 | "@angular/cli": "1.5.0", 29 | "@angular/compiler-cli": "^5.0.1", 30 | "@types/d3": "^4.4.1", 31 | "@types/node": "^6.0.60", 32 | "codelyzer": "~4.0.0", 33 | "ts-node": "~3.2.0", 34 | "tslint": "^5.7.0", 35 | "typescript": "2.4.2" 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/app/app.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lsharir/angular-d3-graph-example/57b88e1fbaef6dd565c6a0a2ddaa05b44155215d/src/app/app.component.css -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import APP_CONFIG from './app.config'; 3 | import { Node, Link } from './d3'; 4 | 5 | @Component({ 6 | selector: 'app-root', 7 | templateUrl: './app.component.html', 8 | styleUrls: ['./app.component.css'] 9 | }) 10 | 11 | export class AppComponent { 12 | nodes: Node[] = []; 13 | links: Link[] = []; 14 | 15 | constructor() { 16 | const N = APP_CONFIG.N, 17 | getIndex = number => number - 1; 18 | 19 | /** constructing the nodes array */ 20 | for (let i = 1; i <= N; i++) { 21 | this.nodes.push(new Node(i)); 22 | } 23 | 24 | for (let i = 1; i <= N; i++) { 25 | for (let m = 2; i * m <= N; m++) { 26 | /** increasing connections toll on connecting nodes */ 27 | this.nodes[getIndex(i)].linkCount++; 28 | this.nodes[getIndex(i * m)].linkCount++; 29 | 30 | /** connecting the nodes before starting the simulation */ 31 | this.links.push(new Link(i, i * m)); 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/app/app.config.ts: -------------------------------------------------------------------------------- 1 | const CONFIG = { 2 | N : 100, 3 | SPECTRUM: [ 4 | // "rgb(222,237,250)" 5 | "rgb(176,212,243)", 6 | "rgb(128,186,236)", 7 | "rgb(77,158,228)", 8 | "rgb(38,137,223)", 9 | "rgb(0,116,217)", 10 | "rgb(0,106,197)" 11 | // "rgb(0,94,176)" 12 | // "rgb(0,82,154)" 13 | // "rgb(0,60,113)" 14 | ] 15 | } 16 | 17 | export default CONFIG; 18 | -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { BrowserModule } from '@angular/platform-browser'; 2 | import { NgModule } from '@angular/core'; 3 | import { FormsModule } from '@angular/forms'; 4 | import { HttpModule } from '@angular/http'; 5 | 6 | import { D3Service, D3_DIRECTIVES } from './d3'; 7 | 8 | import { AppComponent } from './app.component'; 9 | 10 | import { GraphComponent } from './visuals/graph/graph.component'; 11 | import { SHARED_VISUALS } from './visuals/shared'; 12 | 13 | @NgModule({ 14 | declarations: [ 15 | AppComponent, 16 | GraphComponent, 17 | ...SHARED_VISUALS, 18 | ...D3_DIRECTIVES 19 | ], 20 | imports: [ 21 | BrowserModule, 22 | FormsModule, 23 | HttpModule 24 | ], 25 | providers: [D3Service], 26 | bootstrap: [AppComponent] 27 | }) 28 | export class AppModule { } 29 | -------------------------------------------------------------------------------- /src/app/d3/d3.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, EventEmitter } from '@angular/core'; 2 | import { Node, Link, ForceDirectedGraph } from './models'; 3 | import * as d3 from 'd3'; 4 | 5 | @Injectable() 6 | export class D3Service { 7 | /** This service will provide methods to enable user interaction with elements 8 | * while maintaining the d3 simulations physics 9 | */ 10 | constructor() { } 11 | 12 | /** A method to bind a pan and zoom behaviour to an svg element */ 13 | applyZoomableBehaviour(svgElement, containerElement) { 14 | let svg, container, zoomed, zoom; 15 | 16 | svg = d3.select(svgElement); 17 | container = d3.select(containerElement); 18 | 19 | zoomed = () => { 20 | const transform = d3.event.transform; 21 | container.attr('transform', 'translate(' + transform.x + ',' + transform.y + ') scale(' + transform.k + ')'); 22 | } 23 | 24 | zoom = d3.zoom().on('zoom', zoomed); 25 | svg.call(zoom); 26 | } 27 | 28 | /** A method to bind a draggable behaviour to an svg element */ 29 | applyDraggableBehaviour(element, node: Node, graph: ForceDirectedGraph) { 30 | const d3element = d3.select(element); 31 | 32 | function started() { 33 | /** Preventing propagation of dragstart to parent elements */ 34 | d3.event.sourceEvent.stopPropagation(); 35 | 36 | if (!d3.event.active) { 37 | graph.simulation.alphaTarget(0.3).restart(); 38 | } 39 | 40 | d3.event.on('drag', dragged).on('end', ended); 41 | 42 | function dragged() { 43 | node.fx = d3.event.x; 44 | node.fy = d3.event.y; 45 | } 46 | 47 | function ended() { 48 | if (!d3.event.active) { 49 | graph.simulation.alphaTarget(0); 50 | } 51 | 52 | node.fx = null; 53 | node.fy = null; 54 | } 55 | } 56 | 57 | d3element.call(d3.drag() 58 | .on('start', started)); 59 | } 60 | 61 | /** The interactable graph we will simulate in this article 62 | * This method does not interact with the document, purely physical calculations with d3 63 | */ 64 | getForceDirectedGraph(nodes: Node[], links: Link[], options: { width, height }) { 65 | const sg = new ForceDirectedGraph(nodes, links, options); 66 | return sg; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/app/d3/directives/draggable.directive.ts: -------------------------------------------------------------------------------- 1 | import { Directive, Input, ElementRef, OnInit } from '@angular/core'; 2 | import { Node, ForceDirectedGraph } from '../models'; 3 | import { D3Service } from '../d3.service'; 4 | 5 | @Directive({ 6 | selector: '[draggableNode]' 7 | }) 8 | export class DraggableDirective implements OnInit { 9 | @Input('draggableNode') draggableNode: Node; 10 | @Input('draggableInGraph') draggableInGraph: ForceDirectedGraph; 11 | 12 | constructor(private d3Service: D3Service, private _element: ElementRef) { } 13 | 14 | ngOnInit() { 15 | this.d3Service.applyDraggableBehaviour(this._element.nativeElement, this.draggableNode, this.draggableInGraph); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/app/d3/directives/index.ts: -------------------------------------------------------------------------------- 1 | import { ZoomableDirective } from './zoomable.directive'; 2 | import { DraggableDirective } from './draggable.directive'; 3 | 4 | export * from './zoomable.directive'; 5 | export * from './draggable.directive'; 6 | 7 | export const D3_DIRECTIVES = [ 8 | ZoomableDirective, 9 | DraggableDirective 10 | ]; -------------------------------------------------------------------------------- /src/app/d3/directives/zoomable.directive.ts: -------------------------------------------------------------------------------- 1 | import { Directive, Input, ElementRef, OnInit } from '@angular/core'; 2 | import { D3Service } from '../d3.service'; 3 | 4 | @Directive({ 5 | selector: '[zoomableOf]' 6 | }) 7 | export class ZoomableDirective implements OnInit { 8 | @Input('zoomableOf') zoomableOf: ElementRef; 9 | 10 | constructor(private d3Service: D3Service, private _element: ElementRef) {} 11 | 12 | ngOnInit() { 13 | this.d3Service.applyZoomableBehaviour(this.zoomableOf, this._element.nativeElement); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/app/d3/index.ts: -------------------------------------------------------------------------------- 1 | export * from './d3.service'; 2 | export * from './models'; 3 | export * from './directives'; 4 | -------------------------------------------------------------------------------- /src/app/d3/models/force-directed-graph.ts: -------------------------------------------------------------------------------- 1 | import { EventEmitter } from '@angular/core'; 2 | import { Link } from './link'; 3 | import { Node } from './node'; 4 | import * as d3 from 'd3'; 5 | 6 | const FORCES = { 7 | LINKS: 1 / 50, 8 | COLLISION: 1, 9 | CHARGE: -1 10 | } 11 | 12 | export class ForceDirectedGraph { 13 | public ticker: EventEmitter> = new EventEmitter(); 14 | public simulation: d3.Simulation; 15 | 16 | public nodes: Node[] = []; 17 | public links: Link[] = []; 18 | 19 | constructor(nodes, links, options: { width, height }) { 20 | this.nodes = nodes; 21 | this.links = links; 22 | 23 | this.initSimulation(options); 24 | } 25 | 26 | connectNodes(source, target) { 27 | let link; 28 | 29 | if (!this.nodes[source] || !this.nodes[target]) { 30 | throw new Error('One of the nodes does not exist'); 31 | } 32 | 33 | link = new Link(source, target); 34 | this.simulation.stop(); 35 | this.links.push(link); 36 | this.simulation.alphaTarget(0.3).restart(); 37 | 38 | this.initLinks(); 39 | } 40 | 41 | initNodes() { 42 | if (!this.simulation) { 43 | throw new Error('simulation was not initialized yet'); 44 | } 45 | 46 | this.simulation.nodes(this.nodes); 47 | } 48 | 49 | initLinks() { 50 | if (!this.simulation) { 51 | throw new Error('simulation was not initialized yet'); 52 | } 53 | 54 | this.simulation.force('links', 55 | d3.forceLink(this.links) 56 | .id(d => d['id']) 57 | .strength(FORCES.LINKS) 58 | ); 59 | } 60 | 61 | initSimulation(options) { 62 | if (!options || !options.width || !options.height) { 63 | throw new Error('missing options when initializing simulation'); 64 | } 65 | 66 | /** Creating the simulation */ 67 | if (!this.simulation) { 68 | const ticker = this.ticker; 69 | 70 | this.simulation = d3.forceSimulation() 71 | .force('charge', 72 | d3.forceManyBody() 73 | .strength(d => FORCES.CHARGE * d['r']) 74 | ) 75 | .force('collide', 76 | d3.forceCollide() 77 | .strength(FORCES.COLLISION) 78 | .radius(d => d['r'] + 5).iterations(2) 79 | ); 80 | 81 | // Connecting the d3 ticker to an angular event emitter 82 | this.simulation.on('tick', function () { 83 | ticker.emit(this); 84 | }); 85 | 86 | this.initNodes(); 87 | this.initLinks(); 88 | } 89 | 90 | /** Updating the central force of the simulation */ 91 | this.simulation.force('centers', d3.forceCenter(options.width / 2, options.height / 2)); 92 | 93 | /** Restarting the simulation internal timer */ 94 | this.simulation.restart(); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/app/d3/models/index.ts: -------------------------------------------------------------------------------- 1 | export * from './node'; 2 | export * from './link'; 3 | export * from './force-directed-graph'; 4 | -------------------------------------------------------------------------------- /src/app/d3/models/link.ts: -------------------------------------------------------------------------------- 1 | import { Node } from './'; 2 | 3 | export class Link implements d3.SimulationLinkDatum { 4 | // optional - defining optional implementation properties - required for relevant typing assistance 5 | index?: number; 6 | 7 | // must - defining enforced implementation properties 8 | source: Node | string | number; 9 | target: Node | string | number; 10 | 11 | constructor(source, target) { 12 | this.source = source; 13 | this.target = target; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/app/d3/models/node.ts: -------------------------------------------------------------------------------- 1 | import APP_CONFIG from '../../app.config'; 2 | 3 | export class Node implements d3.SimulationNodeDatum { 4 | // optional - defining optional implementation properties - required for relevant typing assistance 5 | index?: number; 6 | x?: number; 7 | y?: number; 8 | vx?: number; 9 | vy?: number; 10 | fx?: number | null; 11 | fy?: number | null; 12 | 13 | id: string; 14 | linkCount: number = 0; 15 | 16 | constructor(id) { 17 | this.id = id; 18 | } 19 | 20 | normal = () => { 21 | return Math.sqrt(this.linkCount / APP_CONFIG.N); 22 | } 23 | 24 | get r() { 25 | return 50 * this.normal() + 10; 26 | } 27 | 28 | get fontSize() { 29 | return (30 * this.normal() + 10) + 'px'; 30 | } 31 | 32 | get color() { 33 | let index = Math.floor(APP_CONFIG.SPECTRUM.length * this.normal()); 34 | return APP_CONFIG.SPECTRUM[index]; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/app/visuals/graph/graph.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lsharir/angular-d3-graph-example/57b88e1fbaef6dd565c6a0a2ddaa05b44155215d/src/app/visuals/graph/graph.component.css -------------------------------------------------------------------------------- /src/app/visuals/graph/graph.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Input, ChangeDetectorRef, HostListener, ChangeDetectionStrategy, OnInit, AfterViewInit } from '@angular/core'; 2 | import { D3Service, ForceDirectedGraph, Node } from '../../d3'; 3 | 4 | @Component({ 5 | selector: 'graph', 6 | changeDetection: ChangeDetectionStrategy.OnPush, 7 | template: ` 8 | 9 | 10 | 11 | 13 | 14 | 15 | `, 16 | styleUrls: ['./graph.component.css'] 17 | }) 18 | export class GraphComponent implements OnInit, AfterViewInit { 19 | @Input('nodes') nodes; 20 | @Input('links') links; 21 | graph: ForceDirectedGraph; 22 | private _options: { width, height } = { width: 800, height: 600 }; 23 | 24 | @HostListener('window:resize', ['$event']) 25 | onResize(event) { 26 | this.graph.initSimulation(this.options); 27 | } 28 | 29 | 30 | constructor(private d3Service: D3Service, private ref: ChangeDetectorRef) {} 31 | 32 | ngOnInit() { 33 | /** Receiving an initialized simulated graph from our custom d3 service */ 34 | this.graph = this.d3Service.getForceDirectedGraph(this.nodes, this.links, this.options); 35 | 36 | /** Binding change detection check on each tick 37 | * This along with an onPush change detection strategy should enforce checking only when relevant! 38 | * This improves scripting computation duration in a couple of tests I've made, consistently. 39 | * Also, it makes sense to avoid unnecessary checks when we are dealing only with simulations data binding. 40 | */ 41 | this.graph.ticker.subscribe((d) => { 42 | this.ref.markForCheck(); 43 | }); 44 | } 45 | 46 | ngAfterViewInit() { 47 | this.graph.initSimulation(this.options); 48 | } 49 | 50 | get options() { 51 | return this._options = { 52 | width: window.innerWidth, 53 | height: window.innerHeight 54 | }; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/app/visuals/shared/index.ts: -------------------------------------------------------------------------------- 1 | export * from './node-visual/node-visual.component'; 2 | export * from './link-visual/link-visual.component'; 3 | 4 | import { NodeVisualComponent } from './node-visual/node-visual.component'; 5 | import { LinkVisualComponent } from './link-visual/link-visual.component'; 6 | 7 | export const SHARED_VISUALS = [ 8 | NodeVisualComponent, 9 | LinkVisualComponent 10 | ]; 11 | -------------------------------------------------------------------------------- /src/app/visuals/shared/link-visual/link-visual.component.css: -------------------------------------------------------------------------------- 1 | .link { 2 | stroke-width: 0.25; 3 | stroke: rgb(222,237,250); 4 | } 5 | -------------------------------------------------------------------------------- /src/app/visuals/shared/link-visual/link-visual.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Input } from '@angular/core'; 2 | import { Link } from '../../../d3'; 3 | 4 | @Component({ 5 | selector: '[linkVisual]', 6 | template: ` 7 | 14 | `, 15 | styleUrls: ['./link-visual.component.css'] 16 | }) 17 | export class LinkVisualComponent { 18 | @Input('linkVisual') link: Link; 19 | } 20 | -------------------------------------------------------------------------------- /src/app/visuals/shared/node-visual/node-visual.component.css: -------------------------------------------------------------------------------- 1 | .node { 2 | cursor: pointer; 3 | transition: stroke-width 0.1s ease-out, 4 | fill 0.1s ease-out, 5 | stroke 0.1s ease-out; 6 | 7 | stroke: white; 8 | stroke-width: 0.25; 9 | } 10 | 11 | .node-name { 12 | font-family: 'Lato'; 13 | text-anchor: middle; 14 | alignment-baseline: central; 15 | font-weight: 300; 16 | fill: white; 17 | } 18 | -------------------------------------------------------------------------------- /src/app/visuals/shared/node-visual/node-visual.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Input } from '@angular/core'; 2 | import { Node } from '../../../d3'; 3 | 4 | @Component({ 5 | selector: '[nodeVisual]', 6 | template: ` 7 | 8 | 14 | 15 | 18 | {{node.id}} 19 | 20 | 21 | `, 22 | styleUrls: ['./node-visual.component.css'] 23 | }) 24 | export class NodeVisualComponent { 25 | @Input('nodeVisual') node: Node; 26 | } 27 | -------------------------------------------------------------------------------- /src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lsharir/angular-d3-graph-example/57b88e1fbaef6dd565c6a0a2ddaa05b44155215d/src/assets/.gitkeep -------------------------------------------------------------------------------- /src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // The file contents for the current environment will overwrite these during build. 2 | // The build system defaults to the dev environment which uses `environment.ts`, but if you do 3 | // `ng build --env=prod` then `environment.prod.ts` will be used instead. 4 | // The list of which env maps to which file can be found in `angular-cli.json`. 5 | 6 | export const environment = { 7 | production: false 8 | }; 9 | -------------------------------------------------------------------------------- /src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lsharir/angular-d3-graph-example/57b88e1fbaef6dd565c6a0a2ddaa05b44155215d/src/favicon.ico -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | AngularD3GraphExample 6 | 7 | 8 | 9 | 10 | 11 | 12 | Loading... 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 2 | import { enableProdMode } from '@angular/core'; 3 | import { environment } from './environments/environment'; 4 | import { AppModule } from './app/app.module'; 5 | 6 | if (environment.production) { 7 | enableProdMode(); 8 | } 9 | 10 | platformBrowserDynamic().bootstrapModule(AppModule); 11 | -------------------------------------------------------------------------------- /src/polyfills.ts: -------------------------------------------------------------------------------- 1 | // This file includes polyfills needed by Angular and is loaded before 2 | // the app. You can add your own extra polyfills to this file. 3 | import 'core-js/es6/symbol'; 4 | import 'core-js/es6/object'; 5 | import 'core-js/es6/function'; 6 | import 'core-js/es6/parse-int'; 7 | import 'core-js/es6/parse-float'; 8 | import 'core-js/es6/number'; 9 | import 'core-js/es6/math'; 10 | import 'core-js/es6/string'; 11 | import 'core-js/es6/date'; 12 | import 'core-js/es6/array'; 13 | import 'core-js/es6/regexp'; 14 | import 'core-js/es6/map'; 15 | import 'core-js/es6/set'; 16 | import 'core-js/es6/reflect'; 17 | 18 | import 'core-js/es7/reflect'; 19 | import 'zone.js/dist/zone'; 20 | -------------------------------------------------------------------------------- /src/styles.css: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | body, html { 3 | margin: 0; 4 | padding: 0; 5 | background: white; 6 | } 7 | -------------------------------------------------------------------------------- /src/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": "", 4 | "declaration": false, 5 | "emitDecoratorMetadata": true, 6 | "experimentalDecorators": true, 7 | "lib": ["es6", "dom"], 8 | "mapRoot": "./", 9 | "module": "es6", 10 | "moduleResolution": "node", 11 | "outDir": "../dist/out-tsc", 12 | "sourceMap": true, 13 | "target": "es5", 14 | "typeRoots": [ 15 | "../node_modules/@types" 16 | ] 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rulesDirectory": [ 3 | "node_modules/codelyzer" 4 | ], 5 | "rules": { 6 | "callable-types": true, 7 | "class-name": true, 8 | "comment-format": [ 9 | true, 10 | "check-space" 11 | ], 12 | "curly": true, 13 | "eofline": true, 14 | "forin": true, 15 | "import-blacklist": [true, "rxjs"], 16 | "import-spacing": true, 17 | "indent": [ 18 | true, 19 | "spaces" 20 | ], 21 | "interface-over-type-literal": true, 22 | "label-position": true, 23 | "max-line-length": [ 24 | true, 25 | 140 26 | ], 27 | "member-access": false, 28 | "member-ordering": [ 29 | true, 30 | "static-before-instance", 31 | "variables-before-functions" 32 | ], 33 | "no-arg": true, 34 | "no-bitwise": true, 35 | "no-console": [ 36 | true, 37 | "debug", 38 | "info", 39 | "time", 40 | "timeEnd", 41 | "trace" 42 | ], 43 | "no-construct": true, 44 | "no-debugger": true, 45 | "no-duplicate-variable": true, 46 | "no-empty": false, 47 | "no-empty-interface": true, 48 | "no-eval": true, 49 | "no-inferrable-types": true, 50 | "no-shadowed-variable": true, 51 | "no-string-literal": false, 52 | "no-string-throw": true, 53 | "no-switch-case-fall-through": true, 54 | "no-trailing-whitespace": true, 55 | "no-unused-expression": true, 56 | "no-use-before-declare": true, 57 | "no-var-keyword": true, 58 | "object-literal-sort-keys": false, 59 | "one-line": [ 60 | true, 61 | "check-open-brace", 62 | "check-catch", 63 | "check-else", 64 | "check-whitespace" 65 | ], 66 | "prefer-const": true, 67 | "quotemark": [ 68 | true, 69 | "single" 70 | ], 71 | "radix": true, 72 | "semicolon": [ 73 | "always" 74 | ], 75 | "triple-equals": [ 76 | true, 77 | "allow-null-check" 78 | ], 79 | "typedef-whitespace": [ 80 | true, 81 | { 82 | "call-signature": "nospace", 83 | "index-signature": "nospace", 84 | "parameter": "nospace", 85 | "property-declaration": "nospace", 86 | "variable-declaration": "nospace" 87 | } 88 | ], 89 | "typeof-compare": true, 90 | "unified-signatures": true, 91 | "variable-name": false, 92 | "whitespace": [ 93 | true, 94 | "check-branch", 95 | "check-decl", 96 | "check-operator", 97 | "check-separator", 98 | "check-type" 99 | ], 100 | 101 | "directive-selector": [true, "attribute", "app", "camelCase"], 102 | "component-selector": [true, "element", "app", "kebab-case"], 103 | "use-input-property-decorator": true, 104 | "use-output-property-decorator": true, 105 | "use-host-property-decorator": true, 106 | "no-input-rename": true, 107 | "no-output-rename": true, 108 | "use-life-cycle-interface": true, 109 | "use-pipe-transform-interface": true, 110 | "component-class-suffix": true, 111 | "directive-class-suffix": true, 112 | "no-access-missing-member": true, 113 | "templates-use-public": true, 114 | "invoke-injectable": true 115 | } 116 | } 117 | --------------------------------------------------------------------------------