UNPKG

app-overview

Version:

> A visualization of the application structure. See, read & learn the code, effortlessly.

224 lines (195 loc) 5.35 kB
function mountRadial() { var radial = new Radial(); return radial; } class Radial { traverse(func) { let arr = this.tree.nodes; for (var i = 0; i < arr.length; i++) { let node = arr[i]; let funcSaysStopRecursing = func(node) === false; if (funcSaysStopRecursing) return; } } update() { // updates by click } constructor() { const width = document.body.clientWidth; const height = document.body.clientHeight; let linkedNodes = {}; let svg = d3v4 .select("#graph") .append("svg") .attr("width", width) .attr("height", height) .call( d3v4 .zoom() .scaleExtent([0.4, 4]) .on("zoom", () => { svg.attr("transform", d3v4.event.transform); }) ) .append("g"); const render = data => { let arr = []; for (let i in data) { if (i === "root") data[i]["depth"] = 0; else data[i]["depth"] = 1; arr.push(data[i]); } return arr; }; this.tree = { nodes: render(data), links: getLinks(render(data)) }; var simulation = d3v4 .forceSimulation(this.tree.nodes) .force("charge", d3v4.forceManyBody()) .force("collide", d3v4.forceCollide(15)) .force("link", d3v4.forceLink(this.tree.links).strength(0.1)) .force("center", d3v4.forceCenter(width / 2, height / 2)) .on("tick", ticked); var link = svg .append("g") .attr("class", "links") .selectAll("line") .data(this.tree.links) .enter() .append("line") .attr("stroke", "darkgrey") .attr("stroke-width", 2); var node = svg .append("g") .attr("class", "nodes") .selectAll("g") .data(this.tree.nodes) .enter() .append("g") .attr("class", "node"); var circles = node .append("circle") .attr("r", 10) .attr("fill", "lightsteelblue") .on("mouseover", mouseOver(0.2)) .on("mouseout", mouseOut) .call( d3v4 .drag() .on("start", dragstarted) .on("drag", dragged) .on("end", dragended) ); var lables = node .append("text") .text(function(d) { return d.name; }) .attr("x", 8) .attr("y", 18); simulation .nodes(this.tree.nodes) .alphaTarget(1) .restart() .on("tick", ticked); simulation.force("link").links(this.tree.links); var circleUpdate = d3v4.selectAll("g.nodes circle"); function ticked() { link .attr("x1", function(d) { return d.source.x; }) .attr("y1", function(d) { return d.source.y; }) .attr("x2", function(d) { return d.target.x; }) .attr("y2", function(d) { return d.target.y; }); node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); circleUpdate .attr("fill", function(d) { return d["highlight"] && d.highlight === 1 ? "#ea762d" : "lightsteelblue"; }) .attr("class", function(d) { return d["highlight"] && d.highlight === 1 ? "highlighted" : null; }); } function dragstarted(d) { if (!d3v4.event.active) simulation.alphaTarget(0.5).restart(); d.fx = d.x; d.fy = d.y; } function dragged(d) { d.fx = d3v4.event.x; d.fy = d3v4.event.y; } function dragended(d) { if (!d3v4.event.active) simulation.alphaTarget(0); d.fx = null; d.fy = null; } this.tree.links.forEach(d => { linkedNodes[d.source.index + "," + d.target.index] = 1; }); const isConnected = (a, b) => { return ( linkedNodes[a.index + "," + b.index] || linkedNodes[b.index + "," + a.index] || a.index == b.index ); }; function mouseOver(opacity) { return function(d) { node.style("stroke-opacity", function(o) { let thisOpacity = isConnected(d, o) ? 1 : opacity; return thisOpacity; }); node.style("fill-opacity", function(o) { let thisOpacity = isConnected(d, o) ? 1 : opacity; return thisOpacity; }); link.style("stroke-opacity", function(o) { return o.source === d || o.target === d ? 1 : opacity; }); link.style("stroke", function(o) { return o.source === d || o.target === d ? o.source.colour : "#ddd"; }); }; } function mouseOut() { node.style("stroke-opacity", 1); node.style("fill-opacity", 1); link.style("stroke-opacity", 1); link.style("stroke", "#ddd"); } function getLinks(data) { return _.flatten( _.map(_.filter(data, "children"), function(source, i) { return _.map(source.children, function(target) { return { source: i, target: _.findIndex(data, { id: target }) }; }); }) ); } } } window.onload = function() { if (typeof switch_is_present == "undefined") mountRadial(); }; function unmountRadial() { if (simulation !== undefined) simulation.on("tick", null); }