Built with blockbuilder.org
forked from romsson's block: simple line chart from dataset
forked from romsson's block: TP3-InClass-2-Stock
forked from keikhcheung's block: TP3-InClass-2-Stock
forked from keikhcheung's block: TP3-InClass-2-Stock-20171128
forked from keikhcheung's block: TP3-Rendu-Multiple-Area-Chart-20171128
forked from keikhcheung's block: TP3-Rendu-Small-Multiples-Chart-20171128
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
svg { font: 10px sans-serif; }
.area {
stroke: black;
stroke-width: 1.5px;
}
</style>
</head>
<body>
<!-- ATTEMPT 1 <script>
/*** DEMO end of TP3 https://blockbuilder.org/romsson/57eb273e01761b829aaa95b28c8193c1 ***/
// Feel free to change or delete any of the code you see in this editor!
/**********
PREDEFINITION Start
*******/
// Size of the 'body' space containing the svg
var margin = {top: 40, right: 35, bottom: 20, left: 70},
width = 900 - margin.left - margin.right,
height = 110 - margin.top - margin.bottom;
// https://bl.ocks.org/zanarmstrong/raw/05c1e95bf7aa16c4768e/
// %b shows month in abbreviated written name; %Y shows year in numbers
// Formats: https://github.com/d3/d3-time-format
var parseDate = d3.timeParse("%b %Y");
// OBSOLETE var parseDate = d3.timeFormat("%Y-%m");
// OBSOLETE var displayDate = d3.timeFormat("%b %Y");
// OBSOLETE var displayValue = d3.format(",.0f");
// Ordinal scale
// d3.scaleOrdinal() changed to d3.scaleTime()
var x = d3.scaleTime()
.range([0, width]);
var y = d3.scaleLinear()
.range([height, 0]);
// For legends; .schemeCategory10 is a preset of categorical colours
// https://bl.ocks.org/aaizemberg/78bd3dade9593896a59d
var c = d3.scaleOrdinal(d3.schemeCategory10);
/**********
PREDEFINITION End
*******/
/*** OBSOLETE
// Make path to be painted
var line = d3.line()
// .curve(d3.curveBasis) allows smoothing of the curve
.curve(d3.curveBasis)
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.price); });
***/
// Make area to be painted
var area = d3.area()
// = .interpolate("basis") in d3.v3
.curve(d3.curveBasis)
.x(function(d) { return x(d.date); })
.y0(height)
.y1(function(d) { return y(d.price); });
/**********
DATA TREATMENT Start
*******/
d3.text('dataset.csv', function(error, raw) {
/*** OBSOLETE
LOADED NEW 'dataset.csv' file instead of pulling 'dataset.json'
// Replacing "dataset.json" with Data CSV file URL: https://gist.githubusercontent.com/mbostock/1256572/raw/44c086a6019de56dce35a47197a19468b3e4ad57/stocks.csv
// Parsing the CSV file is preliminary
// d3.csv exists as a function but the flexibility in coding a CSV file makes it difficult to adopt directly this function.
// Manual parsing is hence recommended.
// function(error, raw) allows console.log(raw) to observe raw data
d3.json("https://gist.githubusercontent.com/mbostock/1256572/raw/44c086a6019de56dce35a47197a19468b3e4ad57/stocks.csv", function(error, raw) {
console.log(raw)
***/
// Parsing starts here
var dsv = d3.dsvFormat(',');
var data = dsv.parse(raw);
// Nesting
// Pull data and nest them under nested_data (§ 'symbols' as in DEMO)
// Make as many nests as as many grouped data
var nested_data = d3.nest()
.key(function(d) { return d.symbol; })
.entries(data);
/*** OBSOLETE
// .rollup show 'value' in console in one numeric value instead of value content
.rollup(function(leaves) {
return d3.sum(leaves, function(d) {
return d.price;
});
})
.entries(data);
console.log(nested_data)
***/
// Pre-processing
// In fact, not pre-processing anymore, as now shifted after 'Nesting'
// ¿¿Cannot really understand what these lines are for??
nested_data.forEach(function(s) {
s.values.forEach(function(d) {
// The following line puts date ticks on x-axis
d.date = parseDate(d.date);
// The following line seems to affect the fluctuation of drawn paths
d.price = +d.price;
});
// The following line gives values to the lines and is primordial to the display of ticks on y-axis
s.maxPrice = d3.max(s.values, function(d) { return d.price; });
// ¿¿??
s.sumPrice = d3.sum(s.values, function(d) { return d.price; });
console.log(data)
});
/**********
DATA TREATMENT End
*******/
/**********
GRAPH-DRAWING Start
*******/
x.domain(d3.extent(data, function(d) { return d.date; }));
// OBSOLETE x.domain(data.map(function(d) { return d.name; }));
y.domain([0, d3.max(nested_data.map(function(d) { return d.maxPrice; }))]);
// NOT USEFUL area.y0(y(0));
// OBSOLETE FROM TP3 20171128 y.domain([0, d3.max(nested_data.map(function(d) { return d.maxPrice; }))]);
// OBSOLETE FROM TP3 CLASS y.domain([0, d3.max(nested_data.map(function(d) { return d.value; }))]);
/*** REMOVED CODE CONVERNTING TEXT AND VALUE (talking about from 'simple line chart from dataset' https://blockbuilder.org/romsson/855207ac5fb5c170de59b9c69ea56012) ***/
// Path-/line-drawing
// nested_data is a table of a table (in replacement of [data] in general)
// Definition of 'svg' moved here so that each element can have its own seperate graph
var svg = d3.select("body").selectAll(".area")
// Size of the svg 'canvas' showing the drawn graph
.data(nested_data)
.enter().append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
var g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
// Add a path element for each 'symbol' in nested_data, i.e. each stock
// with the desired style
g.append("path")
.attr("class", "area")
// Draw values of 'd'
.attr("d", function(d) { y.domain([0, d.maxPrice]); return area(d.values); })
.style("stroke", function(d) { return c(d.key); })
.style("fill", function(d) { return c(d.key); })
.style("opacity", 0.4);
g.append("g")
.attr("class", "axis axis--x")
// x-axis position
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
g.append("g")
.attr("class", "axis axis--y");
/*** OBSOLETE
// .ticks(n) allows number of labels on the y-axis scale
.call(d3.axisLeft(y).ticks(0));
***/
/*** OBSOLETE
// Adding labels and placing them in a certain position
var legend = svg.selectAll("svg").data(c.domain()).enter()
.append("g")
.attr("id", "label")
// Positioning of the legends
.attr("transform", function(d, i) { console.log(c.domain());
return "translate(0, " + (i * 20 ) + ")"
});
***/
/*** OBSOLETE
// Coloured squares in legends
legend.append("rect")
.attr("x", 30)
.attr("width", 18)
.attr("height", 18)
// 'c' contains the colour scheme for the legend squares
.style("fill", c)
***/
// legend.append("text") changed to svg.append("text")
// as 'legend' does not exist as a defined variable anymore
g.append("text")
.attr("x", width + 7)
.attr("y", height / 2)
.attr("dy", ".35em")
.style("text-anchor", "start")
.text(function(d) { console.log(d.key) ; return d.key; })
});
/**********
GRAPH-DRAWING End
*******/
</script> -->
<!-- ATTEMPT 2 -->
<script>
/*** DEMO end of TP3 https://blockbuilder.org/romsson/57eb273e01761b829aaa95b28c8193c1 ***/
// Feel free to change or delete any of the code you see in this editor!
/**********
PREDEFINITION Start
*******/
// Size of the 'body' space containing the svg
var margin = {top: 40, right: 35, bottom: 20, left: 70},
width = 900 - margin.left - margin.right,
height = 450 - margin.top - margin.bottom;
// https://bl.ocks.org/zanarmstrong/raw/05c1e95bf7aa16c4768e/
// %b shows month in abbreviated written name; %Y shows year in numbers
// Formats: https://github.com/d3/d3-time-format
var parseDate = d3.timeParse("%b %Y");
// OBSOLETE var parseDate = d3.timeFormat("%Y-%m");
// OBSOLETE var displayDate = d3.timeFormat("%b %Y");
// OBSOLETE var displayValue = d3.format(",.0f");
// Ordinal scale
// d3.scaleOrdinal() changed to d3.scaleTime()
var x = d3.scaleTime()
.range([0, width]);
var y = d3.scaleLinear()
.range([height, 0]);
// For legends; .schemeCategory10 is a preset of categorical colours
// https://bl.ocks.org/aaizemberg/78bd3dade9593896a59d
var c = d3.scaleOrdinal(d3.schemeCategory10);
/**********
PREDEFINITION End
*******/
/*** OBSOLETE FROM TP3 IN-CLASS MULTIPLE LINE CHART
var line = d3.line()
// .curve(d3.curveBasis) allows smoothing of the curve
.curve(d3.curveBasis)
.x(function(d) { return x(d.date); })
.y(function(d) { return y(d.price); });
***/
// .stack() reference:
// https://d3-wiki.readthedocs.io/zh_CN/master/Stack-Layout/
var stack = d3.stack();
// Make area to be painted
var area = d3.area()
// = .interpolate("basis") in d3.v3
.curve(d3.curveBasis)
.x(function(d) { return x(d.date); })
.y0(function(d) { return y(0); })
// ++ .y1(function(d) { return y(d[1]); });
.y1(function(d) { return y(d.price); });
/**********
DATA TREATMENT Start
*******/
d3.text('dataset.csv', function(error, raw) {
/*** OBSOLETE
LOADED NEW 'dataset.csv' file instead of pulling 'dataset.json'
// Replacing "dataset.json" with Data CSV file URL: https://gist.githubusercontent.com/mbostock/1256572/raw/44c086a6019de56dce35a47197a19468b3e4ad57/stocks.csv
// Parsing the CSV file is preliminary
// d3.csv exists as a function but the flexibility in coding a CSV file makes it difficult to adopt directly this function.
// Manual parsing is hence recommended.
// function(error, raw) allows console.log(raw) to observe raw data
d3.json("https://gist.githubusercontent.com/mbostock/1256572/raw/44c086a6019de56dce35a47197a19468b3e4ad57/stocks.csv", function(error, raw) {
console.log(raw)
***/
// Parsing starts here
var dsv = d3.dsvFormat(',');
var data = dsv.parse(raw);
// ++
var keys = data.columns.slice(1);
// Nesting
// Pull data and nest them under nested_data (§ 'symbols' as in DEMO)
// Make as many nests as as many grouped data
var nested_data = d3.nest()
.key(function(d) { return d.symbol; })
.entries(data);
/*** OBSOLETE
// .rollup show 'value' in console in one numeric value instead of value content
.rollup(function(leaves) {
return d3.sum(leaves, function(d) {
return d.price;
});
})
.entries(data);
console.log(nested_data)
***/
// Pre-processing
// In fact, not pre-processing anymore, as now shifted after 'Nesting'
// ¿¿Cannot really understand what these lines are for??
nested_data.forEach(function(s) {
s.values.forEach(function(d) {
// The following line puts date ticks on x-axis
d.date = parseDate(d.date);
// The following line seems to affect the fluctuation of drawn paths
d.price = +d.price;
});
// The following line gives values to the lines and is primordial to the display of ticks on y-axis
s.maxPrice = d3.max(s.values, function(d) { return d.price; });
// ¿¿??
s.sumPrice = d3.sum(s.values, function(d) { return d.price; });
console.log(data)
});
/**********
DATA TREATMENT End
*******/
/**********
GRAPH-DRAWING Start
*******/
x.domain(d3.extent(data, function(d) { return d.date; }));
// OBSOLETE x.domain(data.map(function(d) { return d.name; }));
y.domain([0, d3.max(nested_data.map(function(d) { return d.maxPrice; }))]);
// NOT USEFUL area.y0(y(0));
// OBSOLETE FROM TP3 20171128 y.domain([0, d3.max(nested_data.map(function(d) { return d.maxPrice; }))]);
// OBSOLETE FROM TP3 CLASS y.domain([0, d3.max(nested_data.map(function(d) { return d.value; }))]);
// +- c.domain(keys); // This change the colour scheme if active.
// ++
stack.keys(keys);
/*** REMOVED CODE CONVERNTING TEXT AND VALUE (talking about from 'simple line chart from dataset' https://blockbuilder.org/romsson/855207ac5fb5c170de59b9c69ea56012) ***/
// Path-/line-drawing
// nested_data is a table of a table (in replacement of [data] in general)
// Definition of 'svg' moved here so that each element can have its own seperate graph
var svg = d3.select("body")/*.selectAll(".area")*/
// Size of the svg 'canvas' showing the drawn graph
// -- .data(nested_data)
/* -- .enter()*/.append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.attr("class", "canvas");
var g = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
var layer = g.selectAll(".layer")
.data(stack(nested_data))
.enter().append("g")
.attr("class", "layer");
// Add a path element for each 'symbol' in nested_data, i.e. each stock
// with the desired style
layer.selectAll(".canvas").data(nested_data).enter()
.append("path")
.attr("class", "area")
// Draw values of 'd'
.attr("d", function(d) { return area(d.values); })
.style("stroke", function(d) { return c(d.key); })
.style("fill", function(d) { return c(d.key); })
.style("opacity", 0.4)
layer.filter(function(d) { return d[d.length - 1][1] - d[d.length - 1][0] > 0.01; })
.append("text")
.attr("x", width - 7)
.attr("y", function(d) { return y((d[d.length - 1][0] + d[d.length - 1][1]) / 2); })
.attr("dy", ".35em")
.style("text-anchor", "end")
.text(function(d) { console.log(d.key); return d.key; })
g.append("g")
.attr("class", "axis axis--x")
// x-axis position
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
g.append("g")
.attr("class", "axis axis--y")
// .ticks(n) allows number of labels on the y-axis scale
.call(d3.axisLeft(y).ticks(20));
/*** OBSOLETE
// Adding labels and placing them in a certain position
var legend = svg.selectAll("svg").data(c.domain()).enter()
.append("g")
.attr("id", "label")
// Positioning of the legends
.attr("transform", function(d, i) { console.log(c.domain());
return "translate(0, " + (i * 20 ) + ")"
});
***/
/*** OBSOLETE
// Coloured squares in legends
legend.append("rect")
.attr("x", 30)
.attr("width", 18)
.attr("height", 18)
// 'c' contains the colour scheme for the legend squares
.style("fill", c)
***/
// legend.append("text") changed to svg.append("text")
// as 'legend' does not exist as a defined variable anymore
});
/**********
GRAPH-DRAWING End
*******/
</script>
</body>
https://d3js.org/d3.v4.min.js