Skip to content

Commit

Permalink
v1.6.5 Finished Multi Series Line chart.
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesleesaunders committed Sep 17, 2017
1 parent 93b5125 commit 050231b
Show file tree
Hide file tree
Showing 11 changed files with 164 additions and 407 deletions.
3 changes: 2 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ JS_FILES := src/js/header.js \
src/js/tabularHeatChart.js \
src/js/donutChart.js \
src/js/punchCard.js \
src/js/timeSeriesChart.js \
src/js/multiSeriesLineChart.js \
src/js/htmlTable.js \
src/js/htmlList.js \
src/js/reusableComponents.js
Expand All @@ -21,6 +21,7 @@ CSS_FILES := src/css/global.css \
src/css/tabularHeatChart.css \
src/css/donutChart.css \
src/css/punchCard.css \
src/css/multiSeriesLineChart.css \
src/css/htmlList.css \
src/css/htmlTable.css

Expand Down
41 changes: 22 additions & 19 deletions d3.ez.css
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,27 @@
}


/* === Multi Series Line Chart Styles === */
.multiSeriesLineChart .line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
@keyframes circleTransition {
from {
transform: scale(1);
}
to {
transform: scale(1.5);
}
}
.multiSeriesLineChart circle:hover {
animation-duration: 0.2s;
animation-name: circleTransition;
transform-origin: center center;
}


/* === HTML List Styles === */
.htmlList, .htmlList ul {
margin: 0;
Expand Down Expand Up @@ -217,22 +238,4 @@ table.htmlTable {
background-color: #eeeeee;
}

/* === Multi Series Line Chart Styles === */
.multiSeriesLineChart .line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
@keyframes circleTransition {
from {
transform: scale(1);
}
to {
transform: scale(1.5);
}
}
.multiSeriesLineChart circle:hover {
animation-duration: 0.2s;
animation-name: circleTransition;
transform-origin: center center;
}

194 changes: 103 additions & 91 deletions d3.ez.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,6 @@ d3.ez.base = function module() {
function init(data) {
canvasW = width - (margin.left + margin.right);
canvasH = height - (margin.top + margin.bottom);
// Init Data
if (!data[0]) {
// TODO: Can this be done better?
// If 1 dimensional data
categories = d3.values(data)[1];
} else {
// If 2 dimensional data
categories = data.map(function(d) {
return d.values;
})[0];
}
categoryNames = categories.map(function(d) {
return d.key;
});
// Init Chart
chart.dispatch(dispatch).width(canvasW).height(canvasH);
// Init Legend
Expand Down Expand Up @@ -1647,84 +1633,82 @@ d3.ez.punchCard = function module() {
};

/**
* Time Series Chart
* Multi Series Line Chart
*
* @example
* var formatDate = d3.time.format("%b %Y");
* var myChart = d3.ez.timeSeriesChart()
* .x(function(d) { return formatDate.parse(d.date); })
* .y(function(d) { return +d.price; })
* .width(600)
* .height(350);
* var myChart = d3.ez.multiSeriesLineChart()
* .width(400)
* .height(300);
* d3.select("#chartholder")
* .datum(data)
* .call(myChart);
* .datum(data)
* .call(myChart);
*/
d3.ez.timeSeriesChart = function module() {
d3.ez.multiSeriesLineChart = function module() {
// SVG and Chart containers (Populated by 'my' function)
var svg;
var chart;
// Default Options (Configurable via setters)
var width = 400;
var height = 300;
var margin = {
top: 50,
right: 40,
bottom: 50,
top: 20,
right: 20,
bottom: 30,
left: 40
};
var transition = {
ease: "bounce",
duration: 500
};
var classed = "timeSeriesChart";
var color = "steelblue";
var xValue = function(d) {
return d[0];
};
var yValue = function(d) {
return d[1];
};
var classed = "multiSeriesLineChart";
var colors = d3.ez.colors.categorical(3);
var yAxisLabel = null;
var groupType = "clustered";
// Data Options (Populated by 'init' function)
var chartW = 0;
var chartH = 0;
var minValue = 0;
var maxValue = 0;
var maxGroupTotal = undefined;
var xScale = undefined;
var yScale = undefined;
var xAxis = undefined;
var yAxis = undefined;
var colorScale = undefined;
// Dispatch (Custom events)
var dispatch = d3.dispatch("customMouseOver", "customMouseOut", "customClick");
// Other functions
var line = undefined;
var cities;
function init(data) {
chartW = width - margin.left - margin.right;
chartH = height - margin.top - margin.bottom;
// Group and Category Names
seriesNames = data.map(function(d) {
return d.key;
});
// Convert dates and calculate min / max
data.forEach(function(d, i) {
d.values.forEach(function(b, j) {
data[i].values[j].key = new Date(b.key * 1e3);
var value = data[i].values[j].value;
minValue = value < minValue ? value : minValue;
maxValue = value > maxValue ? value : maxValue;
});
});
// X & Y Scales
dateDomain = d3.extent(data[0].values, function(d) {
return d.key;
});
xScale = d3.time.scale().range([ 0, chartW ]).domain(dateDomain);
yScale = d3.scale.linear().range([ chartH, 0 ]).domain([ minValue, maxValue + 10 ]);
// X & Y Axis
xAxis = d3.svg.axis().scale(xScale).orient("bottom").tickFormat(d3.time.format("%d-%b"));
yAxis = d3.svg.axis().scale(yScale).orient("left");
// Colour Scale
colorScale = d3.scale.ordinal().range(colors).domain(seriesNames);
}
function my(selection) {
selection.each(function(data) {
// Initialise Data
init(data);
// Convert data to standard representation greedily;
// this is needed for nondeterministic accessors.
data = data.map(function(d, i) {
return [ xValue.call(data, d, i), yValue.call(data, d, i) ];
});
// X & Y Scales
var xScale = d3.time.scale().domain(d3.extent(data, function(d) {
return d[0];
})).range([ 0, chartW ]);
var yScale = d3.scale.linear().domain([ 0, d3.max(data, function(d) {
return d[1];
}) ]).range([ chartH, 0 ]);
// X & Y Axis
var xAxis = d3.svg.axis().scale(xScale).orient("bottom").tickSize(6, 0);
var yAxis = d3.svg.axis().scale(yScale).orient("left").tickSize(6, 6);
// Setup the Line and Area
var area = d3.svg.area().x(function(d) {
return xScale(d[0]);
}).y1(function(d) {
return yScale(d[1]);
});
var line = d3.svg.line().x(function(d) {
return xScale(d[0]);
}).y(function(d) {
return yScale(d[1]);
});
// Create SVG element (if it does not exist already)
// Create SVG and Chart containers (if they do not already exist)
if (!svg) {
svg = function(selection) {
var el = selection[0][0];
Expand All @@ -1738,30 +1722,43 @@ d3.ez.timeSeriesChart = function module() {
width: width,
height: height
});
var chart = svg.append("g").classed("chart", true);
chart.append("path").classed("chart-area-path", true);
chart.append("path").classed("chart-line-path", true);
chart.append("g").classed("x-axis-group axis", true);
chart.append("g").classed("y-axis-group axis", true);
chart = svg.append("g").classed("chart", true);
chart.append("g").classed("x-axis axis", true);
chart.append("g").classed("y-axis axis", true).append("text").attr("transform", "rotate(-90)").attr("y", -35).attr("dy", ".71em").style("text-anchor", "end").text(yAxisLabel);
} else {
chart = svg.select(".chart");
chart = selection.select(".chart");
}
// Update the chart dimensions
chart.classed(classed, true).attr({
width: chartW,
height: chartH
width: width,
height: height
}).attr({
transform: "translate(" + margin.left + "," + margin.top + ")"
});
// Add axis to chart
chart.select(".x-axis-group.axis").attr({
transform: "translate(0," + yScale.range()[0] + ")"
}).call(xAxis);
chart.select(".y-axis-group.axis").call(yAxis);
// Update the area path
chart.select(".chart-area-path").data([ data ]).attr("d", area.y0(yScale.range()[0])).attr("fill", color);
// Update the line path
chart.select(".chart-line-path").data([ data ]).attr("d", line).attr("fill", "none");
chart.select(".x-axis").attr("transform", "translate(0," + chartH + ")").call(xAxis).selectAll("text").style("text-anchor", "end").attr("dx", "-.8em").attr("dy", ".15em").attr("transform", "rotate(-65)");
chart.select(".y-axis").call(yAxis);
var series = chart.selectAll(".series").data(data).enter().append("g").attr("class", "series");
// Line Generator
line = d3.svg.line().x(function(d) {
return xScale(d.key);
}).y(function(d) {
return yScale(d.value);
});
series.append("path").attr("class", "line").attr("d", function(d) {
return line(d.values);
}).style("stroke", function(d) {
return colorScale(d.key);
});
series.selectAll("circle").data(function(d) {
return d.values;
}).enter().append("circle").attr("r", 3).attr("cx", function(d) {
return xScale(d.key);
}).attr("cy", function(d) {
return yScale(d.value);
}).style("fill", function(d, i, j) {
return colorScale(data[j].key);
}).on("mouseover", dispatch.customMouseOver);
});
}
// Configuration Getters & Setters
Expand All @@ -1780,19 +1777,34 @@ d3.ez.timeSeriesChart = function module() {
margin = _;
return this;
};
my.x = function(_) {
if (!arguments.length) return xValue;
xValue = _;
my.yAxisLabel = function(_) {
if (!arguments.length) return yAxisLabel;
yAxisLabel = _;
return this;
};
my.groupType = function(_) {
if (!arguments.length) return groupType;
groupType = _;
return this;
};
my.y = function(_) {
if (!arguments.length) return yValue;
yValue = _;
my.transition = function(_) {
if (!arguments.length) return transition;
transition = _;
return this;
};
my.color = function(_) {
if (!arguments.length) return color;
color = _;
my.colors = function(_) {
if (!arguments.length) return colors;
colors = _;
return this;
};
my.colorScale = function(_) {
if (!arguments.length) return colorScale;
colorScale = _;
return this;
};
my.dispatch = function(_) {
if (!arguments.length) return dispatch();
dispatch = _;
return this;
};
d3.rebind(my, dispatch, "on");
Expand Down
2 changes: 1 addition & 1 deletion d3.ez.min.js

Large diffs are not rendered by default.

Binary file modified d3.ez.zip
Binary file not shown.
44 changes: 14 additions & 30 deletions examples/MultiSeriesLineChart.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,37 +20,21 @@
return dateUnix;
}

d3.tsv("data/data.tsv", function(error, data) {
// console.log(data);

var data2 = d3.nest()
.key(function(d) { return d.date; })
.entries(data)
.map(function(group) {
series = group.values[0];
return {
key: group['key'],
values: [
{key: "New York", value: series['New York']},
{key: "San Francisco", value: series['San Francisco']},
{key: "Austin", value: series['Austin']},
]
};
});
console.log(data2);

data3 = [ {key: "New York", values: []}, {key: "San Francisco", values: []}, {key: "Austin", values: []} ];
d3.map(data).values().forEach(function(d) {
data3[0].values.push({key: dateConvert(d.date), value: parseInt(d['New York'])});
data3[1].values.push({key: dateConvert(d.date), value: parseInt(d['San Francisco'])});
data3[2].values.push({key: dateConvert(d.date), value: parseInt(d['Austin'])});
d3.tsv("data/data.tsv", function(error, tsv) {
// Convert tsv to d3.ez data format
data = [ {key: "New York", values: []}, {key: "San Francisco", values: []}, {key: "Austin", values: []} ];
d3.map(tsv).values().forEach(function(d) {
data[0].values.push({key: dateConvert(d.date), value: parseInt(d['New York'])});
data[1].values.push({key: dateConvert(d.date), value: parseInt(d['San Francisco'])});
data[2].values.push({key: dateConvert(d.date), value: parseInt(d['Austin'])});
});
console.log(data3);

var colors = d3.ez.colors.categorical(3);
var chart = d3.ez.multiSeriesLineChart().colors(colors);
var legend = d3.ez.legend().title('Cities Count');
var title = d3.ez.title().mainText("Cities").subText("Count");
var chart = d3.ez.multiSeriesLineChart()
.colors(colors)
.yAxisLabel('Temperature (°F)');
var legend = d3.ez.legend().title('City');
var title = d3.ez.title().mainText("Average Temperatures").subText("Per City");

// Create chart object
var myChart = d3.ez.base()
Expand All @@ -60,11 +44,11 @@
.legend(legend)
.title(title)
.on("customMouseOver", function(d, i) {
d3.select("#message").text(d.temperature);
d3.select("#message").text(d.value);
});

d3.select('#chartholder')
.datum(data3)
.datum(data)
.call(myChart);
});
</script>
Expand Down
Loading

0 comments on commit 050231b

Please sign in to comment.