Skip to content

Instantly share code, notes, and snippets.

@stevesong
Last active June 7, 2017 15:40
Show Gist options
  • Save stevesong/4c0413987781619cc109c23fa0543924 to your computer and use it in GitHub Desktop.
Save stevesong/4c0413987781619cc109c23fa0543924 to your computer and use it in GitHub Desktop.
spectrum-chart
license: gpl-3.0
scrolling: yes
border: yes
height: 1000
var svg = d3.select("svg"),
margin = {top: 60, right: 50, bottom: 30, left: 90},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom;
var x = d3.scaleLinear().rangeRound([0, width]),
y = d3.scaleBand().rangeRound([0, height]).padding(0.1);
var g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var infoBox = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
var f = d3.format(".1f");
var totSpec = "";
var sumSpec = 0;
/* Load data file */
d3.csv("900MHz.csv", function(d) {
d.freqStart = +d.freqStart;
d.freqEnd = +d.freqEnd;
return d;
}, function(error, data) {
if (error) throw error;
x.domain([d3.min(data, function(d) { return d.freqStart; }), d3.max(data, function(d) { return d.freqEnd; })]);
y.domain(data.map(function(d) { return d.Country; }));
/* Set lower X-axis and legend */
g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).ticks(20).tickSize(-height))
.append("text")
.attr("x", 20)
.attr("y", 30)
.text("Frequency (MHz)");
/* Set X-axis at top and add title/legend */
g.append("g")
.attr("class", "axis axis--x")
.call(d3.axisTop(x).ticks(20).tickSize(-height))
.append("text")
.classed("FreqLegend", true)
.attr("x", 20)
.attr("y", -30)
.text("900 MHz Band");
/* Set Y-axis */
g.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(y).tickSize(5))
.selectAll(".tick text")
.classed("countryName", true)
.call(wrap, margin.left)
/* Mouseover for Y axis elements */
.on("mouseover", function(d) {
})
.on("mouseout", function(d) {
});
d3.xml("https://raw.githubusercontent.com/lipis/flag-icon-css/master/flags/4x3/za.svg").mimeType("image/svg+xml").get(function(error, xml) {
if (error) throw error;
document.body.appendChild(xml.documentElement);
});
/* Iterate through data file */
g.selectAll(".bar")
.data(data)
.enter().append("g")
.attr("class", "bars")
.append("rect")
.attr("class", function(d) { return d.Operator.replace(/\s+/g, '_').replace(/\W/g,'') + " " + d.Country.replace(/\s+/g, '_'); })
.classed("bar", true)
.attr("y", function(d) { return y(d.Country); })
.attr("x", function(d) { return x(d.freqStart); })
.attr("width", function(d) { return x(d.freqEnd) - x(d.freqStart); })
.attr("height", y.bandwidth());
/* Add label to each spectrum assignments */
var bars = svg.selectAll(".bars");
bars.append("text")
.attr("class", "label")
.attr('transform', 'rotate(-90)')
.attr("y", function(d) { return x(d.freqStart) + (x(d.freqEnd) - x(d.freqStart))/2 + 5; })
.attr("x", function(d) { return -y(d.Country) - y.bandwidth() + 10 ; })
.text(function(d) { return d.Operator; })
.call(wrap, y.bandwidth())
/* ToolTip for spectrum assignments */
.on("mouseover", function(d) {
/* calculate total spectrum assigned */
g.selectAll("." + d.Operator.replace(/\s+/g, '_').replace(/\W/g,'') + "." + d.Country.replace(/\s+/g, '_')).each(function(d) {
totSpec = f(d.freqEnd - d.freqStart) + " + " + totSpec;
sumSpec = sumSpec + d.freqEnd - d.freqStart;
});
g.selectAll("." + d.Operator.replace(/\s+/g, '_').replace(/\W/g,'') + "." + d.Country.replace(/\s+/g, '_'))
.classed("selected", true)
infoBox.transition()
.duration(200)
.style("opacity", );
infoBox.html('<div class="tab-row"><div class="cell-right">Country:</div><div class="cell-left">' + d.Country + '</div></div><div class="tab-row"><div class="cell-right">Operator:</div><div class="cell-left">' + d.Operator + '</div></div><div class="tab-row"><div class="cell-right">Band:</div><div class="cell-left">' + d.Band + '</div></div><div class="tab-row"><div class="cell-right">Assignment:</div><div class="cell-left">' + totSpec.replace(/\s\+\s$/, '') + ' MHz</div></div><div class="tab-row"><div class="cell-right">Total:</div><div class="cell-left">' + f(sumSpec) + " MHz</div></div>")
.style("left", x(d.freqStart) - 20 + "px")
.style("top", y(d.Country) + 1.65*y.bandwidth() + "px");
})
.on("mouseout", function(d) {
totSpec = "";
sumSpec = 0;
g.selectAll("." + d.Operator.replace(/\s+/g, '_').replace(/\W/g,'') + "." + d.Country.replace(/\s+/g, '_'))
.classed("selected", false)
infoBox.transition()
.duration(500)
.style("opacity", 0);
});
});
/* Wrap text function */
function wrap (text, width) {
text.each(function() {
var breakChars = ['/', '&', '-'],
text = d3.select(this),
textContent = text.text(),
spanContent;
breakChars.forEach(char => {
// Add a space after each break char for the function to use to determine line breaks
textContent = textContent.replace(char, char + ' ');
});
var words = textContent.split(/\s+/).reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 1.1, // ems
x = text.attr('x'),
y = text.attr('y'),
dy = parseFloat(text.attr('dy') || 0),
tspan = text.text(null).append('tspan').attr('x', x).attr('y', y).attr('dy', dy + 'em');
while (word = words.pop()) {
line.push(word);
tspan.text(line.join(' '));
if (tspan.node().getComputedTextLength() > width) {
line.pop();
spanContent = line.join(' ');
breakChars.forEach(char => {
// Remove spaces trailing breakChars that were added above
spanContent = spanContent.replace(char + ' ', char);
});
tspan.text(spanContent);
line = [word];
tspan = text.append('tspan').attr('x', x).attr('y', y).attr('dy', ++lineNumber * lineHeight + dy + 'em').text(word);
}
}
});
/* Import SVG flag */
function flag (iso) {
}
}
Country Operator Band freqStart freqEnd
Botswana BeMobile 900 906.6 910.6
Botswana BeMobile 900 951.6 955.6
Botswana Government 900 911 914.8
Botswana Government 900 956 959.8
Botswana Mascom 900 890.2 898.2
Botswana Mascom 900 935 943
Botswana Orange 900 898.4 906.2
Botswana Orange 900 943.4 951.2
Burkina Faso Onatel 900 890.2 898.3
Burkina Faso Onatel 900 935.2 943.3
Burkina Faso Orange 900 898.3 906.6
Burkina Faso Orange 900 943.3 951.6
Burkina Faso Telecel 900 906.6 914.8
Burkina Faso Telecel 900 951.6 959.8
Egypt Etisalat 900 902.5 915
Egypt Etisalat 900 947.5 960
Egypt Orange 900 890 902.5
Egypt Orange 900 935 947.5
Egypt Vodafone 900 880 890
Egypt Vodafone 900 925 935
Ghana Airtel 900 885 890
Ghana Airtel 900 930 935
Ghana Glo 900 880 885
Ghana Glo 900 925 930
Ghana MTN 900 907 915
Ghana MTN 900 952 960
Ghana Tigo 900 890 898
Ghana Tigo 900 935 943
Ghana Vodafone 900 898 907
Ghana Vodafone 900 943 952
Kenya Airtel 900 905 915
Kenya Airtel 900 950 960
Kenya Orange 900 880 882.5
Kenya Orange 900 900 905
Kenya Orange 900 925 927.5
Kenya Orange 900 945 950
Kenya Safaricom 900 890 900
Kenya Safaricom 900 935 945
Kenya Yu(Safaricom) 900 882.5 890
Kenya Yu(Safaricom) 900 927.5 935
Namibia MTC 900 890 903
Namibia MTC 900 935 948
Namibia Telecom Namibia 900 905 915
Namibia Telecom Namibia 900 950 960
South Africa CellC 900 880.1 889.9
South Africa CellC 900 903.7 905.9
South Africa CellC 900 925.1 934.9
South Africa CellC 900 948.7 950.9
South Africa MTN 900 901.3 903.7
South Africa MTN 900 905.9 914.7
South Africa MTN 900 946.3 948.7
South Africa MTN 900 950.9 959.7
South Africa Vodacom 900 889.9 901.3
South Africa Vodacom 900 934.9 946.3
Uganda UTL 900 880 885
Uganda UTL 900 925 930
Uganda WARID 900 885 890
Uganda WARID 900 930 935
Uganda Airtel 900 890.2 898.0
Uganda Airtel 900 935.2 943.0
Uganda Africell 900 898.2 903.2
Uganda Africell 900 943.2 948.2
Uganda iTEL 900 903.2 906.4
Uganda iTEL 900 948.2 951.4
Uganda MTN 900 906.6 914.8
Uganda MTN 900 951.6 959.8
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<link rel="stylesheet" href="spectrum-chart.css" />
</head>
<svg width="800" height="1200"></svg>
<script type="text/javascript" src="900byCountry.js"></script>
</body>
.bar {
fill: purple;
stroke: grey;
stroke-width: .5;
}
.bar text {
fill: #fff;
font: 10px sans-serif;
}
/*
.bar:hover {
fill: grey;
}
.label:hover {
fill: black;
}
*/
.FreqLegend {
fill: #144667;
font-family: "Arial Black", Gadget, sans-serif;
font-size: 22px;
}
.label {
fill: white;
font-family: "Arial Black", Gadget, sans-serif;
font-size: 16px;
}
.axis--x path {
display: none;
}
.axis--y {
font-size: 14px;
border: 10px;
}
.axis--y path {
display: none;
}
.countryName {
fill: #144667;
font-family: "Arial Black", Gadget, sans-serif;
font-size: 14px;
}
text {
fill: steelblue;
font-family: sans-serif
}
.axis--x .tick line {
stroke-width: 1;
stroke: rgba(0, 0, 0, 0.5);
}
/* Operator colour assignments based on corporate colours */
.Orange {
fill: #f16e00;
}
.Safaricom {
fill: #61a60e;
}
.Yu(Safaricom) {
fill: #61a60e;
}
.Airtel {
fill: #A7010A;
}
.CellC {
fill: #0b0b0b;
}
.MTN {
fill: #ffbe00;
}
.Vodacom {
fill: #e60000
}
.Vodafone {
fill: #e60000;
}
.Mascom {
fill: #fee100;
}
.BeMobile {
fill: #65BD0F;
}
.Onatel {
fill: #E5418A;
}
.Telecel {
fill: #527B97;
}
.Etisalat {
fill: #719E19;
}
.Tigo {
fill: #162458;
}
.Glo {
fill: #45B649;
}
.MTC {
fill: #00AAF0;
}
.Telecom_Namibia {
fill: #FD8326;
}
.mcel {
fill: #FFCF1D;
}
.Movitel {
fill: #FE9413;
}
.ntel {
fill: #E6077C;
}
.Africell {
fill: #ff6220;
}
.UTL {
fill: #34479B;
}
.selected {
fill: #144667;
}
div.tooltip {
position: absolute;
text-align: left;
width: 320px;
height: 150px;
padding: 5px;
font-family: arial;
font-size: 1em;
line-height: 1.5;
padding: 1.5em;
background: #144667;
border: 2px;
color: white;
border-radius: 3px;
pointer-events: none;
-webkit-transform: translate3d(0,-0.5em,0);
transform: translate3d(0,-0.5em,0);
-webkit-transition: opacity 0.1s, -webkit-transform 0.1s;
transition: opacity 0.1s, transform 0.1s;
}
div.tooltip:hover:before{
border: solid;
border-color: #333 transparent;
border-width: 6px 6px 0 6px;
bottom: 20px;
content: "";
left: 50%;
position: absolute;
z-index: 99;
}
.div-table {
float: left;
padding: 10px;
width: auto;
}
.tab-row {
float: left;
width: 400px;
border-radius: 3px;
}
.cell-left {
border: 1px solid;
float: left;
padding: 3px;
width: 200px;
}
.cell-right {
border: 1px solid;
float: left;
text-align: right;
padding: 3px;
width: 100px;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment