xxxxxxxxxx
<body>
<style>
html {
font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
}
.button {
position: absolute;
bottom: 10px;
padding: 10px 20px;
font-size: 2em;
text-align: center;
background: #FFF;
border-radius: 5px;
border: 1px solid #DDD;
}
.button:hover {
background: #CCC;
cursor: pointer;
}
#locations {
right: 10px;
}
#systems {
right: 10px;
bottom: 75px;
}
/* svg { border: solid purple; }
g { border: solid blue; } */
</style>
<button id="locations" class="button">Locations</button>
<button id="systems" class="button">Systems</button>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script>
d3.json('data.json')
.then(function(data) {
data = data.filter(d => d.System != "");
var locations = [...new Set(data.map(d => d.Location))];
var nodes = [...new Set(data.map(d => d.Node))];
var systems = [...new Set(data.map(d => d.System))]
var margin = {left: 20, top: 20, right: 20, bottom: 20},
width = 950 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var svg = d3.select('body').append('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append('g')
.attr('transform', 'translate(' + [margin.left, margin.top] + ')');
var locScale = d3.scalePoint()
.range([margin.left,width-margin.right*6])
.domain(locations)
.padding(0.5);
var sysScale = d3.scalePoint()
.range([height-margin.bottom,margin.top*4])
.domain(systems)
.padding(0.5);
var countScale = d3.scaleLinear()
.range([5,20])
.domain(d3.extent(data, d => d.Count));
var nodeScale = d3.scaleOrdinal(d3.schemeSet1)
.domain([...new Set(data.map(d => d.Node))]);
nodeLeg();
//countLeg();
var locationsLables = svg.selectAll('text.locLables')
.data(locScale.domain())
.enter().append('text')
.attr('class', 'locLables')
.text(d => d)
.attr('x', width/2)
.attr('y', margin.top*3)
.attr('text-anchor', 'middle')
.attr('fill', '#fff');
var sysLables = svg.selectAll('text.sysLables')
.data(sysScale.domain())
.enter().append('text')
.attr('class', 'sysLables')
.text(d => d)
.attr('x', margin.left*2)
.attr('y', height - height/2)
.attr('text-anchor', 'middle')
.attr('fill', '#fff')
var xLocForce = d3.forceX(d => locScale(d.Location));
var ySysForce = d3.forceY(d => sysScale(d.System));
var locactionSplit = false;
var systemSplit = false;
document.getElementById('locations').onclick = function() {
if (!locactionSplit) {
simulation.force('x', xLocForce);
locationsLables.transition()
.attr('x', d => locScale(d))
.attr('fill', '#777')
} else {
simulation.force('x', centerXForce);
locationsLables.transition()
.attr('x', width/2)
.attr('fill', '#fff')
}
locactionSplit = !locactionSplit;
simulation.alpha(1).restart();
}
document.getElementById('systems').onclick = function() {
if (!systemSplit) {
simulation.force('y', ySysForce);
sysLables.transition()
.attr('y', d => sysScale(d))
.attr('fill', '#777')
} else {
simulation.force('y', centerYForce);
sysLables.transition()
.attr('y', height - height/2)
.attr('fill', '#fff')
}
systemSplit = !systemSplit;
simulation.alpha(1).restart();
}
var chargeForce = d3.forceManyBody().strength(-5)
var centerXForce = d3.forceX(width/2);
var centerYForce = d3.forceY(height/2);
var forceCollide = d3.forceCollide()
.strength(1)
.radius(d => countScale(d.Count) + 1)
.iterations(2);
var simulation = d3.forceSimulation()
.force('charge', chargeForce)
.force('collide', forceCollide)
.force('x', centerXForce)
.force('y', centerYForce)
var node = svg.selectAll('circle')
.data(data)
.enter().append('circle')
.attr('r', d => countScale(d.Count))
.attr('fill', d => nodeScale(d.Node));
simulation.nodes(data)
.on('tick', () => {
node.attr('cx', d => d.x)
.attr('cy', d => d.y);
});
function nodeLeg () {
var nodeLegend = svg.append('g')
.attr('transform', 'translate(' + (width - margin.right*5) + ',' + height/2 + ')')
.selectAll('g')
.data(nodeScale.domain())
.enter().append('g')
.attr('transform', (d,i) => 'translate(' + [0, i*20] + ')')
nodeLegend.append('text')
.text(d => d)
nodeLegend.append('circle')
.attr('fill', d => nodeScale(d))
.attr('cx', -10)
.attr('cy', -5)
.attr('r', 7)
}
function countLeg () {
var countLegend = svg.append('g')
.attr('transform', 'translate(' + (width - margin.right*5) + ',' + height*(3/4) + ')')
.selectAll('g')
.data(countScale.domain())
.enter().append('g')
countLegend.append('circle')
.attr('cx', 0)
.attr('cy', d => -countScale(d)/2)
.attr('r', d => countScale(d))
.attr('fill', 'none')
.attr('stroke', 'black')
.attr('stroke-width', 2)
}
});
</script>
</body>
https://d3js.org/d3.v5.min.js