Merge pull request #1 from F1Vis/Init_Diagram
First Visualization of Race Data
This commit is contained in:
commit
582e31f82a
|
@ -31,3 +31,9 @@ body {
|
||||||
top: 0; /* not 10px, but 0 instead */
|
top: 0; /* not 10px, but 0 instead */
|
||||||
left: 0;
|
left: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.line {
|
||||||
|
fill: none;
|
||||||
|
stroke: steelblue;
|
||||||
|
stroke-width: 2px;
|
||||||
|
}
|
||||||
|
|
11
index.html
11
index.html
|
@ -50,12 +50,19 @@
|
||||||
|
|
||||||
|
|
||||||
<div class="content-box">
|
<div class="content-box">
|
||||||
<h1>Hallo F1-Fan!</h1>
|
<h1>Rennen, Brumm, Brumm!</h1>
|
||||||
<p class="lead">
|
<p class="lead">
|
||||||
Hier ist noch viel zutun ...
|
Eingerückt wird mit 2 Leerzeichen pro Einrückungsebene.<br>
|
||||||
|
Charset ist UTF-8.<br>
|
||||||
|
TODO
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="content-box chart-box">
|
||||||
|
<p>Hier erscheint gleich ein Diagramm.</p>
|
||||||
|
<div id="lineGraphBox"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="content-box chart-box">
|
<div class="content-box chart-box">
|
||||||
<p>Hier erscheint gleich ein Test-Diagramm.</p>
|
<p>Hier erscheint gleich ein Test-Diagramm.</p>
|
||||||
<div id="testchartbox"></div>
|
<div id="testchartbox"></div>
|
||||||
|
|
118
js/diagrams.js
118
js/diagrams.js
|
@ -1,80 +1,58 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
/*
|
// https://bl.ocks.org/mbostock/3884955
|
||||||
* This may be restructured in the future - code to create diagrams will live here.
|
function createLineGraph(containerId, raceData){
|
||||||
*/
|
|
||||||
|
|
||||||
function createTestPieChart(containerId, dataset) {
|
|
||||||
var width = 1000;
|
|
||||||
var height = 1000;
|
var height = 1000;
|
||||||
// Build the basic container for the chart
|
var width = 1000;
|
||||||
var svg = d3.select(containerId)
|
|
||||||
.append("div")
|
// set the dimensions and margins of the graph
|
||||||
.classed("svg-container", true)
|
var margin = {top: 20, right: 20, bottom: 30, left: 50},
|
||||||
.append("svg")
|
width = width - margin.left - margin.right,
|
||||||
.attr("preserveAspectRatio", "xMinYMin meet")
|
height = height - margin.top - margin.bottom;
|
||||||
.attr("viewBox", "0 0 " + width + " " + height + "")
|
|
||||||
.classed("svg-content-responsive", true)
|
// set the ranges
|
||||||
|
var x = d3.scaleLinear().range([0, width]);
|
||||||
|
var y = d3.scaleLinear().range([height, 0]);
|
||||||
|
|
||||||
|
var allLineData = raceDataToLineData(raceData);
|
||||||
|
|
||||||
|
// defines how the passed in Data, at "svg.append" shall be interpreted
|
||||||
|
var lineDataDefinition = d3.line()
|
||||||
|
.x(function(d) { return x(d.lap); })
|
||||||
|
.y(function(d) { return y(d.position); });
|
||||||
|
|
||||||
|
// append the svg obgect to the body of the page
|
||||||
|
// appends a 'group' element to 'svg'
|
||||||
|
// moves the 'group' element to the top left margin
|
||||||
|
var svg = d3.select(containerId).append("svg")
|
||||||
|
.attr("width", width + margin.left + margin.right)
|
||||||
|
.attr("height", height + margin.top + margin.bottom)
|
||||||
.append("g")
|
.append("g")
|
||||||
.classed("main-group", true)
|
.attr("transform",
|
||||||
.attr("transform", "translate(" + (width / 2) + "," + (height / 2) + ")");
|
"translate(" + margin.left + "," + margin.top + ")");
|
||||||
|
|
||||||
var arcs = svg.append("g").classed("pie-chart-arcs", true);
|
// Scale the range of the data
|
||||||
var labels = svg.append("g").classed("pie-chart-labels", true);
|
x.domain([0, raceData.lapTimes.size]);
|
||||||
var lines = svg.append("g").classed("pie-chart-lines", true);
|
y.domain([raceData.drivers.length, 1]);
|
||||||
|
|
||||||
// Preparations are done, now let's build the pie chart
|
// Adds all lines
|
||||||
var maxRadius = Math.min(width, height) / 2;
|
allLineData.forEach((singleLineData) => {
|
||||||
var radius = maxRadius * 0.4;
|
svg.append("path")
|
||||||
var color = d3.scaleOrdinal(d3.schemeCategory10);
|
.data([singleLineData])
|
||||||
|
.attr("class", "line")
|
||||||
|
.attr("d", lineDataDefinition);
|
||||||
|
});
|
||||||
|
|
||||||
var arc = d3.arc()
|
// Add the X Axis
|
||||||
.innerRadius(radius*0.4)
|
svg.append("g")
|
||||||
.outerRadius(radius);
|
.attr("transform", "translate(0," + height + ")")
|
||||||
|
.call(d3.axisBottom(x));
|
||||||
var pie = d3.pie()
|
|
||||||
.sort(function(a, b) { return b.count - a.count })
|
|
||||||
.value(function(d) { return d.count; });
|
|
||||||
|
|
||||||
arcs.selectAll("path")
|
|
||||||
.data(pie(dataset))
|
|
||||||
.enter()
|
|
||||||
.append("path")
|
|
||||||
.attr("d", arc)
|
|
||||||
.attr("fill", function(d, i) {
|
|
||||||
return color(d.data.label);
|
|
||||||
});
|
|
||||||
|
|
||||||
labels.selectAll("text")
|
|
||||||
.data(pie(dataset))
|
|
||||||
.enter()
|
|
||||||
.append("text")
|
|
||||||
.attr("dy", ".35em")
|
|
||||||
.text(function(d) {
|
|
||||||
console.log(d);
|
|
||||||
return d.data.label;
|
|
||||||
});
|
|
||||||
|
|
||||||
function midAngle(d) {
|
|
||||||
return d.startAngle + (d.endAngle - d.startAngle) / 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
lines.selectAll("polyline")
|
|
||||||
.data(pie(dataset))
|
|
||||||
.enter()
|
|
||||||
.append("polyline")
|
|
||||||
.transition()
|
|
||||||
.duration(1000)
|
|
||||||
.attrTween("points", function(d) {
|
|
||||||
this._current = this._current || d;
|
|
||||||
var interpolate = d3.interpolate(this._current, d);
|
|
||||||
this._current = interpolate(0);
|
|
||||||
return function(t) {
|
|
||||||
var d2 = interpolate(t);
|
|
||||||
var pos = outerArc.centroid(d2);
|
|
||||||
pos[0] = radius * 0.95 * (midAngle(d2) < Math.PI ? 1 : -1);
|
|
||||||
return [arc.centroid(d2), outerArc.centroid(d2), pos];
|
|
||||||
};
|
|
||||||
})
|
|
||||||
|
|
||||||
|
// Add the Y Axis on both sides
|
||||||
|
svg.append("g")
|
||||||
|
.call(d3.axisLeft(y));
|
||||||
|
svg.append("g")
|
||||||
|
.call(d3.axisRight(y))
|
||||||
|
.attr("transform", "translate( " + (width) + ", 0 )");
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,5 @@ preprocessor.load(function(data) {
|
||||||
var seasons = preprocessor.getResults().seasons;
|
var seasons = preprocessor.getResults().seasons;
|
||||||
for(var year in seasons) yearSelector.append("<option>" + year + "</option>");
|
for(var year in seasons) yearSelector.append("<option>" + year + "</option>");
|
||||||
|
|
||||||
// No more test chart
|
createLineGraph("#lineGraphBox", processor.getRace(1));
|
||||||
//createTestPieChart("#testchartbox", queries.getDriversByNationality());
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
29
js/util.js
29
js/util.js
|
@ -1,6 +1,6 @@
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This file contains utility functions, data structures and
|
* This file contains utility functions, data structures and
|
||||||
* stuff not related to what this project actually does.
|
* stuff not related to what this project actually does.
|
||||||
*/
|
*/
|
||||||
|
@ -34,6 +34,31 @@ var loadingDialog = {
|
||||||
var percentage = (this.progressItemsDone / this.progressItems) * 100;
|
var percentage = (this.progressItemsDone / this.progressItems) * 100;
|
||||||
if(percentage < 0 || isNaN(percentage)) percentage = 0;
|
if(percentage < 0 || isNaN(percentage)) percentage = 0;
|
||||||
if(percentage > 100) percentage = 100;
|
if(percentage > 100) percentage = 100;
|
||||||
$(this.id + " .progress-bar").attr("style", "width: " + percentage + "%;");
|
$(this.id + " .progress-bar").attr("style", "width: " + percentage + "%;");
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//Gets the position of Driver with driverid in specific lap
|
||||||
|
function getPositionOfDriver(driver, lap, defaultReturn){
|
||||||
|
var lapEntryWithDrivId =lap.filter( drivLap => drivLap.driverId == driver.driverId );
|
||||||
|
if(lapEntryWithDrivId.length > 0){
|
||||||
|
return lapEntryWithDrivId[0].position;
|
||||||
|
}else{
|
||||||
|
return defaultReturn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// transforms the raceData to a format, with which lineDataDefinition can work
|
||||||
|
function raceDataToLineData(raceData){
|
||||||
|
// define the lines
|
||||||
|
var lineData = [];
|
||||||
|
raceData.drivers.forEach((driver, drivIn)=>{
|
||||||
|
lineData.push();
|
||||||
|
var lapsOfDriverInLineDataFormat = [];
|
||||||
|
raceData.lapTimes.forEach((lap, lapIn) => {
|
||||||
|
lapsOfDriverInLineDataFormat.push({ 'lap': lapIn, 'position': getPositionOfDriver(driver, lap, raceData.drivers.length)});
|
||||||
|
});
|
||||||
|
lineData.splice(drivIn, 0, lapsOfDriverInLineDataFormat);
|
||||||
|
});
|
||||||
|
return lineData;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue