|
<!DOCTYPE html> |
|
<html lang="en"> |
|
<head> |
|
<title>Shanghai SSE Composite Index 1990/12/19-2013/05/22</title> |
|
|
|
<meta charset="UTF-8"> |
|
|
|
<link href="http://jun9.github.io/dc.js/css/bootstrap.min.css" rel="stylesheet"> |
|
<link rel="stylesheet" type="text/css" href="http://jun9.github.io/dc.js/css/dc.css"/> |
|
|
|
<link href='http://jun9.github.io/dc.js/highlighter/shCore.css' rel='stylesheet' type='text/css'/> |
|
<link href='http://jun9.github.io/dc.js/highlighter/shThemeDefault.css' rel='stylesheet' type='text/css'/> |
|
</head> |
|
<body> |
|
|
|
<script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script> |
|
<script type="text/javascript" src="http://jun9.github.io/dc.js/js/crossfilter.js"></script> |
|
<script type="text/javascript" src="http://jun9.github.io/dc.js/js/dc.js"></script> |
|
|
|
<script src='http://jun9.github.io/dc.js/highlighter/shCore.js' type='text/javascript'></script> |
|
<script src="http://jun9.github.io/dc.js/highlighter/shAutoloader.js" type="text/javascript"></script> |
|
<script src='http://jun9.github.io/dc.js/highlighter/shBrushJScript.js' type='text/javascript'></script> |
|
<script src='http://jun9.github.io/dc.js/highlighter/shBrushXml.js' type='text/javascript'></script> |
|
|
|
|
|
<div class="container"> |
|
<h2>Shanghai SSE Composite Index 1990/12/19-2013/05/22</h2> |
|
|
|
<div class="row"> |
|
<div id="yearly-bubble-chart" class="dc-chart"> |
|
<strong>Yearly Performance</strong> (x: index gain, y: index gain(%), radius: fluctuation/index ratio, color: |
|
gain/loss) |
|
<a class="reset" href="javascript:yearlyBubbleChart.filterAll();dc.redrawAll();" |
|
style="display: none;">reset</a> |
|
|
|
<div class="clearfix"></div> |
|
</div> |
|
</div> |
|
|
|
<div class="row"> |
|
<div id="gain-loss-chart"> |
|
<strong>Days by Gain/Loss</strong> |
|
<a class="reset" href="javascript:gainOrLossChart.filterAll();dc.redrawAll();" style="display: none;">reset</a> |
|
|
|
<div class="clearfix"></div> |
|
</div> |
|
|
|
<div id="quarter-chart"> |
|
<strong>Quarters</strong> |
|
<a class="reset" href="javascript:quarterChart.filterAll();dc.redrawAll();" style="display: none;">reset</a> |
|
|
|
<div class="clearfix"></div> |
|
</div> |
|
|
|
<div id="day-of-week-chart"> |
|
<strong>Day of Week</strong> |
|
<a class="reset" href="javascript:dayOfWeekChart.filterAll();dc.redrawAll();" style="display: none;">reset</a> |
|
|
|
<div class="clearfix"></div> |
|
</div> |
|
|
|
<div id="fluctuation-chart"> |
|
<strong>Days by Fluctuation(%)</strong> |
|
<a class="reset" href="javascript:fluctuationChart.filterAll();dc.redrawAll();" style="display: none;">reset</a> |
|
|
|
<div class="clearfix"></div> |
|
</div> |
|
</div> |
|
|
|
<div class="row"> |
|
<div id="monthly-move-chart"> |
|
<strong>Monthly Index Abs Move & Volume/500,000 Chart</strong> (Blue Line: Avg Index, Green Line: Index |
|
Fluctuation) |
|
<a class="reset" href="javascript:volumeChart.filterAll();dc.redrawAll();" |
|
style="display: none;">reset</a> |
|
|
|
<div class="clearfix"></div> |
|
</div> |
|
</div> |
|
|
|
<div class="row"> |
|
<div id="monthly-volume-chart"> |
|
</div> |
|
<p class="muted pull-right" style="margin-right: 15px;">select a time range to zoom in</p> |
|
</div> |
|
|
|
<div class="row"> |
|
<div> |
|
<div class="dc-data-count"> |
|
<span class="filter-count"></span> selected out of <span class="total-count"></span> records | <a |
|
href="javascript:dc.filterAll(); dc.renderAll();">Reset All</a> |
|
</div> |
|
</div> |
|
<table class="table table-hover dc-data-table"> |
|
<thead> |
|
<tr class="header"> |
|
<th>Date</th> |
|
<th>Open</th> |
|
<th>Close</th> |
|
<th>Change</th> |
|
<th>Volume</th> |
|
</tr> |
|
</thead> |
|
</table> |
|
</div> |
|
|
|
<script type="text/javascript"> |
|
var gainOrLossChart = dc.pieChart("#gain-loss-chart"); |
|
var fluctuationChart = dc.barChart("#fluctuation-chart"); |
|
var quarterChart = dc.pieChart("#quarter-chart"); |
|
var dayOfWeekChart = dc.rowChart("#day-of-week-chart"); |
|
var moveChart = dc.compositeChart("#monthly-move-chart"); |
|
var volumeChart = dc.barChart("#monthly-volume-chart"); |
|
var yearlyBubbleChart = dc.bubbleChart("#yearly-bubble-chart"); |
|
|
|
// set dc.js version in title |
|
d3.selectAll("#version").text(dc.version); |
|
|
|
// load data from a csv file |
|
d3.csv("ndx.csv", function (data) { |
|
// since its a csv file we need to format the data a bit |
|
var dateFormat = d3.time.format("%m/%d/%Y"); |
|
var numberFormat = d3.format(".2f"); |
|
|
|
data.forEach(function (e) { |
|
e.dd = dateFormat.parse(e.date); |
|
e.month = d3.time.month(e.dd); // pre-calculate month for better performance |
|
}); |
|
|
|
// feed it through crossfilter |
|
var ndx = crossfilter(data); |
|
var all = ndx.groupAll(); |
|
|
|
var yearlyDimension = ndx.dimension(function (d) { |
|
return d3.time.year(d.dd); |
|
}); |
|
var yearlyPerformanceGroup = yearlyDimension.group().reduce( |
|
//add |
|
function (p, v) { |
|
++p.count; |
|
p.absGain += +v.close - +v.open; |
|
p.fluctuation += Math.abs(+v.close - +v.open); |
|
p.sumIndex += (+v.open + +v.close) / 2; |
|
p.avgIndex = p.sumIndex / p.count; |
|
p.percentageGain = (p.absGain / p.avgIndex) * 100; |
|
p.fluctuationPercentage = (p.fluctuation / p.avgIndex) * 100; |
|
return p; |
|
}, |
|
//remove |
|
function (p, v) { |
|
--p.count; |
|
p.absGain -= +v.close - +v.open; |
|
p.fluctuation -= Math.abs(+v.close - +v.open); |
|
p.sumIndex -= (+v.open + +v.close) / 2; |
|
p.avgIndex = p.sumIndex / p.count; |
|
p.percentageGain = (p.absGain / p.avgIndex) * 100; |
|
p.fluctuationPercentage = (p.fluctuation / p.avgIndex) * 100; |
|
return p; |
|
}, |
|
//init |
|
function () { |
|
return {count: 0, absGain: 0, fluctuation: 0, fluctuationPercentage: 0, sumIndex: 0, avgIndex: 0, percentageGain: 0}; |
|
} |
|
); |
|
|
|
var dateDimension = ndx.dimension(function (d) { |
|
return d.dd; |
|
}); |
|
|
|
// monthly index avg fluctuation in percentage |
|
var moveMonths = ndx.dimension(function (d) { |
|
return d.month; |
|
}); |
|
var monthlyMoveGroup = moveMonths.group().reduceSum(function (d) { |
|
return Math.abs(+d.close - +d.open); |
|
}); |
|
var volumeByMonthGroup = moveMonths.group().reduceSum(function (d) { |
|
return d.volume / 500000; |
|
}); |
|
var indexAvgByMonthGroup = moveMonths.group().reduce( |
|
function (p, v) { |
|
++p.days; |
|
p.total += (+v.open + +v.close) / 2; |
|
p.avg = Math.round(p.total / p.days); |
|
return p; |
|
}, |
|
function (p, v) { |
|
--p.days; |
|
p.total -= (+v.open + +v.close) / 2; |
|
p.avg = p.days == 0 ? 0 : Math.round(p.total / p.days); |
|
return p; |
|
}, |
|
function () { |
|
return {days: 0, total: 0, avg: 0}; |
|
} |
|
); |
|
|
|
var gainOrLoss = ndx.dimension(function (d) { |
|
return +d.open > +d.close ? "Loss" : "Gain"; |
|
}); |
|
var gainOrLossGroup = gainOrLoss.group(); |
|
|
|
var fluctuation = ndx.dimension(function (d) { |
|
return Math.round((d.close - d.open) / d.open * 100); |
|
}); |
|
var fluctuationGroup = fluctuation.group(); |
|
|
|
var quarter = ndx.dimension(function (d) { |
|
var month = d.dd.getMonth(); |
|
if (month <= 3) |
|
return "Q1"; |
|
else if (month > 3 && month <= 5) |
|
return "Q2"; |
|
else if (month > 5 && month <= 7) |
|
return "Q3"; |
|
else |
|
return "Q4"; |
|
}); |
|
var quarterGroup = quarter.group().reduceSum(function (d) { |
|
return d.volume; |
|
}); |
|
|
|
var dayOfWeek = ndx.dimension(function (d) { |
|
var day = d.dd.getDay(); |
|
switch (day) { |
|
case 0: |
|
return "0.Sun"; |
|
case 1: |
|
return "1.Mon"; |
|
case 2: |
|
return "2.Tue"; |
|
case 3: |
|
return "3.Wed"; |
|
case 4: |
|
return "4.Thu"; |
|
case 5: |
|
return "5.Fri"; |
|
case 6: |
|
return "6.Sat"; |
|
} |
|
}); |
|
var dayOfWeekGroup = dayOfWeek.group(); |
|
|
|
yearlyBubbleChart.width(990) |
|
.height(250) |
|
.margins({top: 10, right: 50, bottom: 30, left: 40}) |
|
.dimension(yearlyDimension) |
|
.group(yearlyPerformanceGroup) |
|
.transitionDuration(1500) |
|
.colors(["#a60000", "#ff0000", "#ff4040", "#ff7373", "#67e667", "#39e639", "#00cc00"]) |
|
.colorDomain([-12000, 12000]) |
|
.colorAccessor(function (d) { |
|
return d.value.absGain; |
|
}) |
|
.keyAccessor(function (p) { |
|
return p.value.absGain; |
|
}) |
|
.valueAccessor(function (p) { |
|
return p.value.percentageGain; |
|
}) |
|
.radiusValueAccessor(function (p) { |
|
return p.value.fluctuationPercentage; |
|
}) |
|
.maxBubbleRelativeSize(0.3) |
|
.x(d3.scale.linear().domain([-2500, 2500])) |
|
.y(d3.scale.linear().domain([-100, 100])) |
|
.r(d3.scale.linear().domain([0, 4000])) |
|
.elasticY(true) |
|
.yAxisPadding(100) |
|
.elasticX(true) |
|
.xAxisPadding(500) |
|
.renderHorizontalGridLines(true) |
|
.renderVerticalGridLines(true) |
|
.renderLabel(true) |
|
.renderTitle(true) |
|
.label(function (p) { |
|
return p.key.getFullYear(); |
|
}) |
|
.title(function (p) { |
|
return p.key.getFullYear() |
|
+ "\n" |
|
+ "Index Gain: " + numberFormat(p.value.absGain) + "\n" |
|
+ "Index Gain in Percentage: " + numberFormat(p.value.percentageGain) + "%\n" |
|
+ "Fluctuation / Index Ratio: " + numberFormat(p.value.fluctuationPercentage) + "%"; |
|
}) |
|
.yAxis().tickFormat(function (v) { |
|
return v + "%"; |
|
}); |
|
|
|
gainOrLossChart.width(180) |
|
.height(180) |
|
.radius(80) |
|
.dimension(gainOrLoss) |
|
.group(gainOrLossGroup) |
|
.label(function (d) { |
|
return d.data.key + "(" + Math.floor(d.data.value / all.value() * 100) + "%)"; |
|
}); |
|
|
|
quarterChart.width(180) |
|
.height(180) |
|
.radius(80) |
|
.innerRadius(30) |
|
.dimension(quarter) |
|
.group(quarterGroup); |
|
|
|
dayOfWeekChart.width(180) |
|
.height(180) |
|
.margins({top: 20, left: 10, right: 10, bottom: 20}) |
|
.group(dayOfWeekGroup) |
|
.dimension(dayOfWeek) |
|
.colors(['#3182bd', '#6baed6', '#9ecae1', '#c6dbef', '#dadaeb']) |
|
.label(function (d){ |
|
return d.key.split(".")[1]; |
|
}) |
|
.xAxis().ticks(4); |
|
|
|
fluctuationChart.width(420) |
|
.height(180) |
|
.margins({top: 10, right: 50, bottom: 30, left: 40}) |
|
.dimension(fluctuation) |
|
.group(fluctuationGroup) |
|
.elasticY(true) |
|
.centerBar(true) |
|
.gap(1) |
|
.round(dc.round.floor) |
|
.x(d3.scale.linear().domain([-25, 25])) |
|
.renderHorizontalGridLines(true) |
|
.xAxis() |
|
.tickFormat(function (v) { |
|
return v + "%"; |
|
}); |
|
|
|
moveChart.width(990) |
|
.height(180) |
|
.transitionDuration(1000) |
|
.margins({top: 10, right: 50, bottom: 25, left: 40}) |
|
.dimension(moveMonths) |
|
.group(indexAvgByMonthGroup) |
|
.valueAccessor(function (d) { |
|
return d.value.avg; |
|
}) |
|
.x(d3.time.scale().domain([new Date(1990, 12, 1), new Date(2013, 5, 31)])) |
|
.round(d3.time.month.round) |
|
.xUnits(d3.time.months) |
|
.elasticY(true) |
|
.renderHorizontalGridLines(true) |
|
.brushOn(false) |
|
.compose([ |
|
dc.lineChart(moveChart).group(indexAvgByMonthGroup) |
|
.valueAccessor(function (d) { |
|
return d.value.avg; |
|
}) |
|
.renderArea(true) |
|
.stack(monthlyMoveGroup, function (d) { |
|
return d.value; |
|
}) |
|
.title(function (d) { |
|
var value = d.value.avg ? d.value.avg : d.value; |
|
if (isNaN(value)) value = 0; |
|
return dateFormat(d.key) + "\n" + numberFormat(value); |
|
}) |
|
]) |
|
.xAxis(); |
|
|
|
volumeChart.width(990) |
|
.height(40) |
|
.margins({top: 0, right: 50, bottom: 20, left: 40}) |
|
.dimension(moveMonths) |
|
.group(volumeByMonthGroup) |
|
.centerBar(true) |
|
.gap(0) |
|
.x(d3.time.scale().domain([new Date(1990, 12, 1), new Date(2013, 5, 31)])) |
|
.round(d3.time.month.round) |
|
.xUnits(d3.time.months) |
|
.renderlet(function (chart) { |
|
chart.select("g.y").style("display", "none"); |
|
moveChart.filter(chart.filter()); |
|
}) |
|
.on("filtered", function (chart) { |
|
dc.events.trigger(function () { |
|
moveChart.focus(chart.filter()); |
|
}); |
|
}); |
|
|
|
|
|
dc.dataCount(".dc-data-count") |
|
.dimension(ndx) |
|
.group(all); |
|
|
|
dc.dataTable(".dc-data-table") |
|
.dimension(dateDimension) |
|
.group(function (d) { |
|
var format = d3.format("02d"); |
|
return d.dd.getFullYear() + "/" + format((d.dd.getMonth() + 1)); |
|
}) |
|
.size(10) |
|
.columns([ |
|
function (d) { |
|
return d.date; |
|
}, |
|
function (d) { |
|
return d.open; |
|
}, |
|
function (d) { |
|
return d.close; |
|
}, |
|
function (d) { |
|
return numberFormat(d.close - d.open); |
|
}, |
|
function (d) { |
|
return d.volume; |
|
} |
|
]) |
|
.sortBy(function (d) { |
|
return d.dd; |
|
}) |
|
.order(d3.ascending) |
|
.renderlet(function (table) { |
|
table.selectAll(".dc-table-group").classed("info", true); |
|
}); |
|
|
|
dc.renderAll(); |
|
} |
|
); |
|
</script> |
|
|
|
<div class="clearfix"></div> |
|
<h2>Built on dc.js - Dimensional Charting Javascript Library v<span id="version">1.3.0</span></h2> |
|
|
|
<p> |
|
dc.js is a javascript charting library with native <a |
|
href="http://square.github.com/crossfilter/">crossfilter</a> |
|
support and allowing highly efficient exploration on large multi-dimensional dataset (inspired by crossfilter's |
|
demo). It leverages <a href="http://d3js.org/">d3</a> engine to render charts in css friendly svg format. Charts |
|
rendered using dc.js are naturally data driven and reactive therefore providing instant feedback on user's |
|
interaction. The main objective of this project is to provide an easy yet powerful javascript library which can be |
|
utilized to perform data visualization and analysis in browser as well as on mobile device. This example page is forked from <a href="https://github.com/NickQiZhu/dc.js">https://github.com/NickQiZhu/dc.js</a> and for more information please check out original <a href="https://github.com/NickQiZhu/dc.js/wiki">Wiki</a> and |
|
<a href="https://github.com/NickQiZhu/dc.js/wiki/API">API Reference</a>. For your questions and answers please |
|
try <a href="https://groups.google.com/forum/?fromgroups#!forum/dc-js-user-group">dc.js user group</a>. |
|
</p> |
|
|
|
<p> |
|
The following charts provide a live example of dc.js used against Shanghai SSE Composite Index (000001.SS) for the last 23 years. (You |
|
can run this example completely off-line). Although it is just an example, using it you can |
|
already ask some quite interesting questions. If I am going to gamble whether Shanghai SSE Composite Index will gain or lose |
|
tomorrow what is my chance? Is Friday or Monday the most unlucky day for investors? Is spring better than winter to |
|
invest? Can you find the outliers? When did the outliers occur? |
|
|
|
Public data source |
|
<a href="http://quotes.money.163.com/trade/lsjysj_zhishu_000001.html" target="_blank">money.163.com</a>. |
|
</p> |
|
|
|
<p> |
|
Try it out or checkout other examples. |
|
|
|
<ul> |
|
<li><a href="http://jun9.github.io/dc.js/vc/index.html">US Venture Capital Landscape 2011 (choropleth chart, bubble chart)</a></li> |
|
<li><a href="http://jun9.github.io/dc.js/crime/index.html">Major Canadian City Crime Stats 1998-2011 (bubble overlay, bar chart, line chart)</a> |
|
</li> |
|
<li><a href="http://jeroenooms.github.io/dashboard/snack/">Snack Dashboard by Jeroen Ooms</a> |
|
</li> |
|
</ul> |
|
</p> |
|
|
|
<h2>Quick 5 Mins How-To Guide (<a href="https://github.com/NickQiZhu/dc.js/wiki/API">API Reference</a>)</h2> |
|
|
|
<div> |
|
<h3>Load your data</h3> |
|
|
|
<pre class="brush:js"> |
|
/* |
|
* data can be loaded through regular means with your |
|
* favorite javascript library |
|
*/ |
|
d3.csv("data.csv", function(data) {...}; |
|
d3.json("data.json", function(data) {...}; |
|
jQuery.getJson("data.json", function(data){...}); |
|
</pre> |
|
|
|
<h3>Generate dimension and group</h3> |
|
|
|
<pre class="brush:js"> |
|
// since its a csv file we need to format the data a bit |
|
var dateFormat = d3.time.format("%m/%d/%Y"); |
|
data.forEach(function(e) { e.dd = dateFormat.parse(e.date); }); |
|
|
|
// feed it through crossfilter |
|
var ndx = crossfilter(data); |
|
|
|
// define group all for counting |
|
var all = ndx.groupAll(); |
|
|
|
// define a dimension |
|
var volumeByMonth = ndx.dimension(function(d) { return d3.time.month(d.dd); }); |
|
// map/reduce to group sum |
|
var volumeByMonthGroup = volumeByMonth.group().reduceSum(function(d) { return d.volume; }); |
|
</pre> |
|
|
|
<h3>Anchor Div for Charts</h3> |
|
|
|
<pre class="brush:xml"> |
|
<!-- A div anchor that can be identified by id --> |
|
<div id="your-chart"> |
|
<!-- Title or anything you want to add above the chart --> |
|
<span>Days by Gain or Loss</span> |
|
<!-- |
|
if a link with css class "reset" is present then the chart |
|
will automatically turn it on/off based on whether there is filter |
|
set on this chart (slice selection for pie chart and brush |
|
selection for bar chart) |
|
--> |
|
<a class="reset" href="javascript:gainOrLossChart.filterAll();dc.redrawAll();" |
|
style="display: none;">reset</a> |
|
<!-- |
|
dc.js will also automatically inject applied current filter value into |
|
any html element with css class set to "filter" |
|
--> |
|
<span class="reset" style="display: none;">Current filter: <span class="filter"></span></span> |
|
</div> |
|
</pre> |
|
|
|
<h3>Pie/Donut Chart</h3> |
|
|
|
<pre class="brush:js"> |
|
/* Create a pie chart and use the given css selector as anchor. You can also specify |
|
* an optional chart group for this chart to be scoped within. When a chart belongs |
|
* to a specific group then any interaction with such chart will only trigger redraw |
|
* on other charts within the same chart group. */ |
|
dc.pieChart("#gain-loss-chart", "chartGroup") |
|
.width(200) // (optional) define chart width, :default = 200 |
|
.height(200) // (optional) define chart height, :default = 200 |
|
.transitionDuration(500) // (optional) define chart transition duration, :default = 350 |
|
// (optional) define color array for slices |
|
.colors(['#3182bd', '#6baed6', '#9ecae1', '#c6dbef', '#dadaeb']) |
|
// (optional) define color domain to match your data domain if you want to bind data or color |
|
.colorDomain([-1750, 1644]) |
|
// (optional) define color value accessor |
|
.colorAccessor(function(d, i){return d.value;}) |
|
.radius(90) // define pie radius |
|
// (optional) if inner radius is used then a donut chart will |
|
// be generated instead of pie chart |
|
.innerRadius(40) |
|
.dimension(gainOrLoss) // set dimension |
|
.group(gainOrLossGroup) // set group |
|
// (optional) by default pie chart will use group.key as it's label |
|
// but you can overwrite it with a closure |
|
.label(function(d) { return d.data.key + "(" + Math.floor(d.data.value / all.value() * 100) + "%)"; }) |
|
// (optional) whether chart should render labels, :default = true |
|
.renderLabel(true) |
|
// (optional) by default pie chart will use group.key and group.value as its title |
|
// you can overwrite it with a closure |
|
.title(function(d) { return d.data.key + "(" + Math.floor(d.data.value / all.value() * 100) + "%)"; }) |
|
// (optional) whether chart should render titles, :default = false |
|
.renderTitle(true); |
|
</pre> |
|
|
|
<h3>Bar Chart</h3> |
|
|
|
<pre class="brush:js"> |
|
/* Create a bar chart and use the given css selector as anchor. You can also specify |
|
* an optional chart group for this chart to be scoped within. When a chart belongs |
|
* to a specific group then any interaction with such chart will only trigger redraw |
|
* on other charts within the same chart group. */ |
|
dc.barChart("#volume-month-chart") |
|
.width(990) // (optional) define chart width, :default = 200 |
|
.height(250) // (optional) define chart height, :default = 200 |
|
.transitionDuration(500) // (optional) define chart transition duration, :default = 500 |
|
// (optional) define margins |
|
.margins({top: 10, right: 50, bottom: 30, left: 40}) |
|
.dimension(volumeByMonth) // set dimension |
|
.group(volumeByMonthGroup) // set group |
|
// (optional) whether chart should rescale y axis to fit data, :default = false |
|
.elasticY(true) |
|
// (optional) when elasticY is on whether padding should be applied to y axis domain, :default=0 |
|
.yAxisPadding(100) |
|
// (optional) whether chart should rescale x axis to fit data, :default = false |
|
.elasticX(true) |
|
// (optional) when elasticX is on whether padding should be applied to x axis domain, :default=0 |
|
.xAxisPadding(500) |
|
// define x scale |
|
.x(d3.time.scale().domain([new Date(1990, 12, 1), new Date(2013, 5, 31)])) |
|
// (optional) set filter brush rounding |
|
.round(d3.time.month.round) |
|
// define x axis units |
|
.xUnits(d3.time.months) |
|
// (optional) whether bar should be center to its x value, :default=false |
|
.centerBar(true) |
|
// (optional) set gap between bars manually in px, :default=2 |
|
.barGap(1) |
|
// (optional) render horizontal grid lines, :default=false |
|
.renderHorizontalGridLines(true) |
|
// (optional) render vertical grid lines, :default=false |
|
.renderVerticalGridLines(true) |
|
// (optional) add stacked group and custom value retriever |
|
.stack(monthlyMoveGroup, function(d){return d.value;}) |
|
// (optional) you can add multiple stacked group with or without custom value retriever |
|
// if no custom retriever provided base chart's value retriever will be used |
|
.stack(monthlyMoveGroup) |
|
// (optional) whether this chart should generate user interactive brush to allow range |
|
// selection, :default=true. |
|
.brushOn(true) |
|
// (optional) whether svg title element(tooltip) should be generated for each bar using |
|
// the given function, :default=no |
|
.title(function(d) { return "Value: " + d.value; }) |
|
// (optional) whether chart should render titles, :default = false |
|
.renderTitle(true); |
|
</pre> |
|
|
|
<h3>Row Chart</h3> |
|
|
|
<pre class="brush:js"> |
|
/* Create a row chart and use the given css selector as anchor. You can also specify |
|
* an optional chart group for this chart to be scoped within. When a chart belongs |
|
* to a specific group then any interaction with such chart will only trigger redraw |
|
* on other charts within the same chart group. */ |
|
dc.rowChart("#days-of-week-chart", "chartGroup") |
|
.width(180) // (optional) define chart width, :default = 200 |
|
.height(180) // (optional) define chart height, :default = 200 |
|
.group(dayOfWeekGroup) // set group |
|
.dimension(dayOfWeek) // set dimension |
|
// (optional) define margins |
|
.margins({top: 20, left: 10, right: 10, bottom: 20}) |
|
// (optional) define color array for slices |
|
.colors(['#3182bd', '#6baed6', '#9ecae1', '#c6dbef', '#dadaeb']) |
|
// (optional) set gap between rows, default is 5 |
|
gap(7) |
|
// (optional) set x offset for labels, default is 10 |
|
labelOffSetX(5) |
|
// (optional) set y offset for labels, default is 15 |
|
labelOffSetY(10) |
|
// (optional) whether chart should render labels, :default = true |
|
.renderLabel(true) |
|
// (optional) by default pie chart will use group.key and group.value as its title |
|
// you can overwrite it with a closure |
|
.title(function(d) { return d.data.key + "(" + Math.floor(d.data.value / all.value() * 100) + "%)"; }) |
|
// (optional) whether chart should render titles, :default = false |
|
.renderTitle(true); |
|
// (optional) specify the number of ticks for the X axis |
|
.xAxis().ticks(4); |
|
</pre> |
|
|
|
<h3>Line Chart</h3> |
|
|
|
<pre class="brush:js"> |
|
/* Create a line chart and use the given css selector as anchor. You can also specify |
|
* an optional chart group for this chart to be scoped within. When a chart belongs |
|
* to a specific group then any interaction with such chart will only trigger redraw |
|
* on other charts within the same chart group. */ |
|
dc.lineChart("#monthly-move-chart", "chartGroup") |
|
.width(990) // (optional) define chart width, :default = 200 |
|
.height(200) // (optional) define chart height, :default = 200 |
|
.transitionDuration(500) // (optional) define chart transition duration, :default = 500 |
|
// (optional) define margins |
|
.margins({top: 10, right: 50, bottom: 30, left: 40}) |
|
.dimension(monthlyMove) // set dimension |
|
.group(monthlyMoveGroup) // set group |
|
// (optional) whether chart should rescale y axis to fit data, :default = false |
|
.elasticY(true) |
|
// (optional) when elasticY is on whether padding should be applied to y axis domain, :default=0 |
|
.yAxisPadding(100) |
|
// (optional) whether chart should rescale x axis to fit data, :default = false |
|
.elasticX(true) |
|
// (optional) when elasticX is on whether padding should be applied to x axis domain, :default=0 |
|
.xAxisPadding(500) |
|
// define x scale |
|
.x(d3.time.scale().domain([new Date(1985, 0, 1), new Date(2013, 11, 31)])) |
|
// (optional) set filter brush rounding |
|
.round(d3.time.month.round) |
|
// define x axis units |
|
.xUnits(d3.time.months) |
|
// (optional) render horizontal grid lines, :default=false |
|
.renderHorizontalGridLines(true) |
|
// (optional) render vertical grid lines, :default=false |
|
.renderVerticalGridLines(true) |
|
// (optional) render as area chart, :default = false |
|
.renderArea(true) |
|
// (optional) add stacked group and custom value retriever |
|
.stack(monthlyMoveGroup, function(d){return d.value;}) |
|
// (optional) you can add multiple stacked group with or without custom value retriever |
|
// if no custom retriever provided base chart's value retriever will be used |
|
.stack(monthlyMoveGroup) |
|
// (optional) whether this chart should generate user interactive brush to allow range |
|
// selection, :default=true. |
|
.brushOn(true) |
|
// (optional) whether dot and title should be generated on the line using |
|
// the given function, :default=no |
|
.title(function(d) { return "Value: " + d.value; }) |
|
// (optional) whether chart should render titles, :default = false |
|
.renderTitle(true) |
|
// (optional) radius used to generate title dot, :default = 5 |
|
.dotRadius(10); |
|
</pre> |
|
|
|
<h3>Composite Chart</h3> |
|
|
|
<pre class="brush:js"> |
|
/* Create a composite chart and use the given css selector as anchor. You can also specify |
|
* an optional chart group for this chart to be scoped within. When a chart belongs |
|
* to a specific group then any interaction with such chart will only trigger redraw |
|
* on other charts within the same chart group. */ |
|
dc.compositeChart("#montly-move-chart", "chartGroup") |
|
.width(990) // (optional) define chart width, :default = 200 |
|
.height(200) // (optional) define chart height, :default = 200 |
|
.transitionDuration(500) // (optional) define chart transition duration, :default = 500 |
|
// (optional) define margins |
|
.margins({top: 10, right: 50, bottom: 30, left: 40}) |
|
.dimension(monthlyMove) // set dimension |
|
.group(monthlyMoveGroup) // set group |
|
// (optional) whether chart should rescale y axis to fit data, :default = false |
|
.elasticY(true) |
|
// (optional) when elasticY is on whether padding should be applied to y axis domain, :default=0 |
|
.yAxisPadding(100) |
|
// (optional) whether chart should rescale x axis to fit data, :default = false |
|
.elasticX(true) |
|
// (optional) when elasticX is on whether padding should be applied to x axis domain, :default=0 |
|
.xAxisPadding(500) |
|
// define x scale |
|
.x(d3.time.scale().domain([new Date(1985, 0, 1), new Date(2013, 11, 31)])) |
|
// (optional) set filter brush rounding |
|
.round(d3.time.month.round) |
|
// define x axis units |
|
.xUnits(d3.time.months) |
|
// (optional) render horizontal grid lines, :default=false |
|
.renderHorizontalGridLines(true) |
|
// (optional) render vertical grid lines, :default=false |
|
.renderVerticalGridLines(true) |
|
// compose sub charts, currently composite chart only supports line chart & bar chart |
|
.compose([ |
|
/* Pass the parent chart instance to sub-chart function instead of css selector. |
|
* Sub-charts can have it's own group and dimension however usually it should |
|
* share parent chart's dimension. If sub-chart's dimension or group is not |
|
* explicitly defined here then it will simply inherent from it's parent. */ |
|
dc.barChart(volumeMoveChart).group(volumeByMonthGroup), |
|
// you can even include stacked bar chart or line chart in a composite chart |
|
dc.lineChart(volumeMoveChart).group(indexAvgByMonthGroup).valueAccessor(function(d){return d.value.avg;}).renderArea(true).stack(monthlyMoveGroup, function(d){return d.value;}) |
|
]) |
|
// (optional) whether this chart should generate user interactive brush to allow range |
|
// selection, :default=true. |
|
.brushOn(true); |
|
</pre> |
|
|
|
<h3>Bubble Chart</h3> |
|
|
|
<pre class="brush:js"> |
|
/* Create a bubble chart and use the given css selector as anchor. You can also specify |
|
* an optional chart group for this chart to be scoped within. When a chart belongs |
|
* to a specific group then any interaction with such chart will only trigger redraw |
|
* on other charts within the same chart group. */ |
|
dc.bubbleChart("#yearly-bubble-chart", "chartGroup") |
|
.width(990) // (optional) define chart width, :default = 200 |
|
.height(250) // (optional) define chart height, :default = 200 |
|
.transitionDuration(1000) // (optional) define chart transition duration, :default = 1000 |
|
// (optional) define margins |
|
.margins({top: 10, right: 50, bottom: 30, left: 40}) |
|
.dimension(yearlyDimension) // set dimension |
|
/* Bubble chart expect the groups are reduced to multiple values which would then be used |
|
* to generate x, y, and radius for each key (bubble) in the group */ |
|
.group(yearlyPerformanceGroup) |
|
// (optional) define color function or array for bubbles |
|
.colors(["red", "#ccc","steelblue","green"]) |
|
// (optional) define color domain to match your data domain if you want to bind data or color |
|
.colorDomain([-1750, 1644]) |
|
// (optional) define color value accessor |
|
.colorAccessor(function(d, i){return d.value.absGain;}) |
|
// closure used to retrieve x value from multi-value group |
|
.keyAccessor(function(p) {return p.value.absGain;}) |
|
// closure used to retrieve y value from multi-value group |
|
.valueAccessor(function(p) {return p.value.percentageGain;}) |
|
// closure used to retrieve radius value from multi-value group |
|
.radiusValueAccessor(function(p) {return p.value.fluctuationPercentage;}) |
|
// set x scale |
|
.x(d3.scale.linear().domain([-2500, 2500])) |
|
// set y scale |
|
.y(d3.scale.linear().domain([-100, 100])) |
|
// (optional) whether chart should rescale y axis to fit data, :default = false |
|
.elasticY(true) |
|
// (optional) when elasticY is on whether padding should be applied to y axis domain, :default=0 |
|
.yAxisPadding(100) |
|
// (optional) whether chart should rescale x axis to fit data, :default = false |
|
.elasticX(true) |
|
// (optional) when elasticX is on whether padding should be applied to x axis domain, :default=0 |
|
.xAxisPadding(500) |
|
// set radius scale |
|
.r(d3.scale.linear().domain([0, 4000])) |
|
// (optional) whether chart should render labels, :default = true |
|
.renderLabel(true) |
|
// (optional) closure to generate label per bubble, :default = group.key |
|
.label(function(p) {return p.key.getFullYear();}) |
|
// (optional) whether chart should render titles, :default = false |
|
.renderTitle(true) |
|
// (optional) closure to generate title per bubble, :default = d.key + ": " + d.value |
|
.title(function(p) { |
|
return p.key.getFullYear() |
|
+ "\n" |
|
+ "Index Gain: " + numberFormat(p.value.absGain) + "\n" |
|
+ "Index Gain in Percentage: " + numberFormat(p.value.percentageGain) + "%\n" |
|
+ "Fluctuation / Index Ratio: " + numberFormat(p.value.fluctuationPercentage) + "%"; |
|
}) |
|
// (optional) render horizontal grid lines, :default=false |
|
.renderHorizontalGridLines(true) |
|
// (optional) render vertical grid lines, :default=false |
|
.renderVerticalGridLines(true); |
|
</pre> |
|
|
|
<h3>Geo Choropleth Chart</h3> |
|
|
|
<pre class="brush:js"> |
|
/* Create a choropleth chart and use the given css selector as anchor. You can also specify |
|
* an optional chart group for this chart to be scoped within. When a chart belongs |
|
* to a specific group then any interaction with such chart will only trigger redraw |
|
* on other charts within the same chart group. */ |
|
dc.geoChoroplethChart("#us-chart") |
|
.width(990) // (optional) define chart width, :default = 200 |
|
.height(500) // (optional) define chart height, :default = 200 |
|
.transitionDuration(1000) // (optional) define chart transition duration, :default = 1000 |
|
.dimension(states) // set crossfilter dimension, dimension key should match the name retrieved in geo json layer |
|
.group(stateRaisedSum) // set crossfilter group |
|
// (optional) define color function or array for bubbles |
|
.colors(["#ccc", "#E2F2FF","#C4E4FF","#9ED2FF","#81C5FF","#6BBAFF","#51AEFF","#36A2FF","#1E96FF","#0089FF","#0061B5"]) |
|
// (optional) define color domain to match your data domain if you want to bind data or color |
|
.colorDomain([-5, 200]) |
|
// (optional) define color value accessor |
|
.colorAccessor(function(d, i){return d.value;}) |
|
/* Project the given geojson. You can call this function mutliple times with different geojson feed to generate |
|
* multiple layers of geo paths. |
|
* 1st param - geo json data |
|
* 2nd param - name of the layer which will be used to generate css class |
|
* 3rd param - (optional) a function used to generate key for geo path, it should match the dimension key |
|
* in order for the coloring to work properly */ |
|
.overlayGeoJson(statesJson.features, "state", function(d) { |
|
return d.properties.name; |
|
}) |
|
// (optional) closure to generate title for path, :default = d.key + ": " + d.value |
|
.title(function(d) { |
|
return "State: " + d.key + "\nTotal Amount Raised: " + numberFormat(d.value ? d.value : 0) + "M"; |
|
}); |
|
</pre> |
|
|
|
<h3>Bubble Overlay Chart</h3> |
|
|
|
<pre class="brush:js"> |
|
/* Create a overlay bubble chart and use the given css selector as anchor. You can also specify |
|
* an optional chart group for this chart to be scoped within. When a chart belongs |
|
* to a specific group then any interaction with such chart will only trigger redraw |
|
* on other charts within the same chart group. */ |
|
dc.bubbleOverlay("#bubble-overlay") |
|
// bubble overlay chart does not generate it's own svg element but rather resue an existing |
|
// svg to generate it's overlay layer |
|
.svg(d3.select("#bubble-overlay svg")) |
|
.width(990) // (optional) define chart width, :default = 200 |
|
.height(500) // (optional) define chart height, :default = 200 |
|
.transitionDuration(1000) // (optional) define chart transition duration, :default = 1000 |
|
.dimension(states) // set crossfilter dimension, dimension key should match the name retrieved in geo json layer |
|
.group(stateRaisedSum) // set crossfilter group |
|
// closure used to retrieve x value from multi-value group |
|
.keyAccessor(function(p) {return p.value.absGain;}) |
|
// closure used to retrieve y value from multi-value group |
|
.valueAccessor(function(p) {return p.value.percentageGain;}) |
|
// (optional) define color function or array for bubbles |
|
.colors(["#ccc", "#E2F2FF","#C4E4FF","#9ED2FF","#81C5FF","#6BBAFF","#51AEFF","#36A2FF","#1E96FF","#0089FF","#0061B5"]) |
|
// (optional) define color domain to match your data domain if you want to bind data or color |
|
.colorDomain([-5, 200]) |
|
// (optional) define color value accessor |
|
.colorAccessor(function(d, i){return d.value;}) |
|
// closure used to retrieve radius value from multi-value group |
|
.radiusValueAccessor(function(p) {return p.value.fluctuationPercentage;}) |
|
// set radius scale |
|
.r(d3.scale.linear().domain([0, 3])) |
|
// (optional) whether chart should render labels, :default = true |
|
.renderLabel(true) |
|
// (optional) closure to generate label per bubble, :default = group.key |
|
.label(function(p) {return p.key.getFullYear();}) |
|
// (optional) whether chart should render titles, :default = false |
|
.renderTitle(true) |
|
// (optional) closure to generate title per bubble, :default = d.key + ": " + d.value |
|
.title(function(d) { |
|
return "Title: " + d.key; |
|
}) |
|
// add data point to it's layer dimension key that matches point name will be used to |
|
// generate bubble. multiple data points can be added to bubble overlay to generate |
|
// multiple bubbles |
|
.point("California", 100, 120) |
|
.point("Colorado", 300, 120) |
|
// (optional) setting debug flag to true will generate a transparent layer on top of |
|
// bubble overlay which can be used to obtain relative x,y coordinate for specific |
|
// data point, :default = false |
|
.debug(true); |
|
</pre> |
|
|
|
<h3>Data Table</h3> |
|
|
|
<pre class="brush:xml"> |
|
<!-- anchor div for data table --> |
|
<div id="data-table"> |
|
<!-- create a custom header --> |
|
<div class="header"> |
|
<span>Date</span> |
|
<span>Open</span> |
|
<span>Close</span> |
|
<span>Change</span> |
|
<span>Volume</span> |
|
</div> |
|
<!-- data rows will filled in here --> |
|
</div> |
|
</pre> |
|
<pre class="brush:js"> |
|
/* Create a data table widget and use the given css selector as anchor. You can also specify |
|
* an optional chart group for this chart to be scoped within. When a chart belongs |
|
* to a specific group then any interaction with such chart will only trigger redraw |
|
* on other charts within the same chart group. */ |
|
dc.dataTable("#data-table") |
|
// set dimension |
|
.dimension(dateDimension) |
|
// data table does not use crossfilter group but rather a closure |
|
// as a grouping function |
|
.group(function(d) { |
|
return d.dd.getFullYear() + "/" + (d.dd.getMonth() + 1); |
|
}) |
|
// (optional) max number of records to be shown, :default = 25 |
|
.size(10) |
|
// dynamic columns creation using an array of closures |
|
.columns([ |
|
function(d) { return d.date; }, |
|
function(d) { return d.open; }, |
|
function(d) { return d.close; }, |
|
function(d) { return Math.floor((d.close - d.open)/d.open*100) + "%"; }, |
|
function(d) { return d.volume; } |
|
]) |
|
// (optional) sort using the given field, :default = function(d){return d;} |
|
.sortBy(function(d){ return d.dd; }) |
|
// (optional) sort order, :default ascending |
|
.order(d3.ascending); |
|
</pre> |
|
|
|
<h3>Data Count</h3> |
|
|
|
<pre class="brush:xml"> |
|
<div id="data-count"> |
|
<span class="filter-count"></span> selected out of <span class="total-count"></span> records |
|
</div> |
|
</pre> |
|
<pre class="brush:js"> |
|
/* Create a data count widget and use the given css selector as anchor. You can also specify |
|
* an optional chart group for this chart to be scoped within. When a chart belongs |
|
* to a specific group then any interaction with such chart will only trigger redraw |
|
* on other charts within the same chart group. */ |
|
dc.dataCount("#data-count") |
|
.dimension(ndx) // set dimension to all data |
|
.group(all); // set group to ndx.groupAll() |
|
</pre> |
|
|
|
<h3>Rendering</h3> |
|
|
|
<pre class="brush:js"> |
|
// simply call renderAll() to render all charts on the page |
|
dc.renderAll(); |
|
// or you can render charts belong to a specific chart group |
|
dc.renderAll("group"); |
|
|
|
// once rendered you can call redrawAll to update charts incrementally when data |
|
// change without re-rendering everything |
|
dc.redrawAll(); |
|
// or you can choose to redraw only those charts associated with a specific chart group |
|
dc.redrawAll("group"); |
|
</pre> |
|
|
|
<p> |
|
Try dc.js with your own data set and have fun! |
|
</p> |
|
|
|
<a href="https://github.com/jun9/dc.js"><img style="position: absolute; top: 0; right: 0; border: 0;" |
|
src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" |
|
alt="Fork me on GitHub"></a> |
|
</div> |
|
|
|
</div> |
|
|
|
<script src="http://code.jquery.com/jquery-latest.js"></script> |
|
<script src="http://jun9.github.io/dc.js/js/bootstrap.min.js"></script> |
|
|
|
<script type="text/javascript"> |
|
SyntaxHighlighter.all(); |
|
</script> |
|
|
|
</body> |
|
</html> |