-
Notifications
You must be signed in to change notification settings - Fork 0
Frontend D3
aneahgi edited this page May 22, 2018
·
32 revisions
- That we can use the D3 Data Visualization Framework we needed to import D3 in the index.html and the angular-cli.json file
- The scripts that we use in the Javascript files we downloaded that we can access them directly from the assets folder
- All scripts and styles that are loaded in the index.html are globally accessible in the whole Frontend
"scripts": [
"../node_modules/jquery/dist/jquery.min.js",
"../node_modules/popper.js/dist/umd/popper.min.js",
"../node_modules/bootstrap/dist/js/bootstrap.min.js",
"assets/mapInitializer.js",
"assets/d3.min.js",
"assets/leaflet.js",
"assets/leafletAdd.js"
],
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
<script src="http://labratrevenge.com/d3-tip/javascripts/d3.tip.v0.6.3.js"></script>
- D3.js is a JavaScript library for manipulating documents based on data. D3 helps you bring data to life using HTML, SVG, and CSS. D3’s emphasis on web standards gives you the full capabilities of modern browsers without tying yourself to a proprietary framework, combining powerful visualization components and a data-driven approach to DOM manipulation.
- Examples and a documentation is found here: https://d3js.org/
- Creating the map is explained in the Frontend Map Documentation: https://github.com/eonum/geopitalsuisse/wiki/Frontend-map
- That we can work on the map we put a Leaflet layer on it (see Frontend Map documentation)
- The D3 part is now on a new layer on this Leaflet layer, called the SVG
// add SVG element to leaflet's overlay pane (group layers)
svg = d3.select(map.getPanes().overlayPane).append("svg").attr('id', 'circleSVG');
- We need the SVG element to adapt to our hospitals, that the range of the visible part is right
- This is the function where we calculate the bounds of the SVG Layer
function calculateSVGBounds(hospitals) {
var xMax = 0;
var yMax = 0;
var heightPadding = 100;
var widthPadding = 300;
hospitals.forEach(function(d) {
xMax = Math.max(projectPoint(d.longitude, d.latitude).x, xMax);
yMax = Math.max(projectPoint(d.longitude, d.latitude).y, yMax);
});
svg
.style("left", 0)
.style("width", xMax + widthPadding)
.style("top", 0)
.style("height", yMax + heightPadding);
}
- This tool-tip is shown when the users gets on a circle on the map
- It then shows the name of the hospital that is there
- This code snippet shows how the div for the tooltip is created (inital it's hidden)
// Define the div for the tooltip (used for mouseover functionality)
div = d3.select("body").append("div")
.attr("class", "tooltip")
.style("opacity", 0.0);
- Here you have the code for the transition from hidden to visible
/**
* Displays tooltip when hovering over a marker
* @param d data which is displayed as a circle
*/
function showTooltip(d) {
div.transition()
.duration(1)
.style("opacity", .98);
div.html(d.name)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 0) + "px");
}
- Here the code for the transition from visible to hidden
/**
* Let's the tooltip disappear when hovering out of a marker
* @param d data which is displayed as a circle
*/
function removeTooltip(d) {
div.transition()
.duration(500)
.style("opacity", 0);
}
- The inital circle color is given by the hospital types
- A part of this logic is implemented in the Navbar Component. See:https://github.com/eonum/geopitalsuisse/wiki/Frontend-angular
- This is the code example to give the circles its fill color
/**
* Gives markers different color according to its type attribute
* @param d data which is displayed as a circle
* @returns {string} color of the marker (according to type)
*/
function getCircleColour(d) {
if (d.Typ == "K111") // Universitätspitäler
return ('#a82a2a');
if (d.Typ == "K112") // Zentrumsspitäler
return ('#a89f2a');
if (d.Typ == "K121" || d.Typ == "K122" || d.Typ == "K123") // Grundversorgung
return ('#2ca82a');
if (d.Typ == "K211" || d.Typ == "K212") // Psychiatrische Kliniken
return ('#2a8ea8');
if (d.Typ == "K221") // Rehabilitationskliniken
return ('#2c2aa8');
if (d.Typ == "K231" || d.Typ == "K232" || d.Typ == "K233" || d.Typ == "K234" || d.Typ == "K235") //Spezialkliniken
return ('#772aa8');
else
return ('#d633ff');
}
- For the circle size we first need the max. value that we have in the numerical variables we use
- To calculate this we have a for-loop that goes through the whole data
/**
* Returns the maximal value of the chosen numerical attribute
* @param hospitalData data which is displayed as a circle
* @returns {number} maximal radius of the chosen attribute
*/
function getMaxValue(hospitalData) {
var maxValue = 0;
// get max value of radius attribute (to calculate radius of circles)
for(var i=0; i<hospitalData.length; i++){
if(hospitalData[i]!=null && hospitalData[i].radius!=null){
if(hospitalData[i].radius>maxValue){
maxValue = hospitalData[i].radius;
}
else{
continue;
}
}
}
return maxValue;
}
- Then we use this max. value to define the circle radius
/**
* Gives markers different radius according to the numerical attribute
* @param d data which is displayed as a circle
* @returns {number} radius of the marker (according numerical attribute)
*/
function getCircleRadius(d, maxValue) {
var zoomLevel = map.getZoom();
if (d.radius == null) {
return 1*zoomLevel*zoomLevel/100; // circles with value 0 or without data have radius 2
} else {
return (Math.sqrt(d.radius/maxValue)*10+5)*zoomLevel*zoomLevel/100;
}
}
Ohne Dokumentation wären wir alle Tiere.