heavyai-charting/example/example2.html
2016-02-26 12:50:42 -08:00

307 lines
10 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<title>MapD</title>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css" />
<link rel="stylesheet" type="text/css" href="../mapdc.min.css" />
<link rel="stylesheet" type="text/css" href="../chart.min.css" />
<link href='https://fonts.googleapis.com/css?family=Roboto:400,700,300' rel='stylesheet' type='text/css'>
<style>
.title {
font-weight: bold;
text-align:center;
}
.mapd {
position: relative;
top: 2px;
}
.data-count {
padding-right:20px;
}
.filter-count {
font-weight: bold;
color: #45B1E8;
}
</style>
</head>
<body>
<nav class="navbar navbar-default">
<div class="container-fluid">
<div class="navbar-header" style="margin-top:10px">
<img alt="Brand" src="images/favicon.png" height="30" width="30">
<span class="mapd">MapD Demo</span>
</div>
<div class="navbar-text navbar-right">
<div class="data-count">
<span class="total"><span><span class="filter-count"></span></span>
<span>of <span class="total-count"></span> flights</span>
</div>
</div>
</div>
</nav>
<div class="main-container">
<div class="col-xs-12">
<div class="title">Point Map with Backend Rendering</div>
<div id="chart1-example"></div>
</div>
<div class="col-xs-12">
<div class="title"># of Tweets per 5 Minutes</div>
<div class="chart2-example"></div>
</div>
</div>
<script src="node_modules/lodash/lodash.js"></script>
<script src="node_modules/jquery/dist/jquery.min.js"></script>
<script src="node_modules/d3/d3.min.js"></script>
<script src="node_modules/@mapd/mapd-con/dist/thrift.js"></script>
<script src="node_modules/@mapd/mapd-con/dist/mapd.thrift.js"></script>
<script src="node_modules/@mapd/mapd-con/dist/mapd_types.js"></script>
<script src="node_modules/@mapd/mapd-con/dist/MapdCon.js"></script>
<script src="node_modules/@mapd/mapd-crossfilter/mapd-crossfilter.js"></script>
<script src="../mapdc.js"></script>
<script src="node_modules/@mapd/mapd-mapbox-gl-js/dist/mapbox-gl.js"></script>
<script src="node_modules/@mapd/mapd-mapbox-gl-js/dist/mapboxgl-overrides.js"></script>
<script>
/*
* This is example code that shows how to make 3 cross-filtered charts with the
* mapdc.js API. This example is not meant to be a replacement for dc.js
* documentation. For the dc.js API docs, see here
* - https://github.com/dc-js/dc.js/blob/master/web/docs/api-latest.md.
* For an annotated example of using dc.js - see here:
* https://dc-js.github.io/dc.js/docs/stock.html.
*/
function createCharts(crossFilter) {
var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0) - 50;
var h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0) - 200;
/*---------------------BASIC COUNT ON CROSSFILTER--------------------------*/
/*
* A basic operation is getting the filtered count and total count
* of crossFilter. This performs that operation. It is built into DC.
* Note that for the count we use crossFilter itself as the dimension.
*/
var countGroup = crossFilter.groupAll();
var dataCount = dc.dataCount(".data-count")
.dimension(crossFilter)
.group(countGroup);
/*----------------BACKEND RENDERED POINT MAP EXAMPLE-----------------------*/
/*
*
* TODO
*
*/
var langDomain = ['en', 'pt', 'es', 'in', 'und', 'ja', 'tr', 'fr', 'tl', 'ru', 'ar', 'th', 'it', 'nl', 'sv', 'ht', 'de', 'et', 'pl', 'sl', 'ko', 'fi', 'lv', 'sk', 'uk', 'da', 'zh', 'ro', 'no', 'cy', 'iw', 'hu', 'bg', 'lt', 'bs', 'vi', 'el', 'is', 'hi', 'hr', 'fa', 'ur', 'ne', 'ta', 'sr', 'bn', 'si', 'ml', 'hy', 'lo', 'iu', 'ka', 'ps', 'te', 'pa', 'am', 'kn', 'chr', 'my', 'gu', 'ckb', 'km', 'ug', 'sd', 'bo', 'dv'];
var langOriginColors = ["#27aeef", "#ea5545", "#87bc45", "#b33dc6", "#f46a9b", "#ede15b", "#bdcf32", "#ef9b20", "#4db6ac", "#edbf33", "#7c4dff"]
var langColors = [];
var pointMapDim = crossFilter.dimension(null).projectOn(["goog_x as x", "goog_y as y", "lang as color"]);
var xDim = crossFilter.dimension("goog_x");
var yDim = crossFilter.dimension("goog_y");
var parent = document.getElementById("chart1-example");
mapLangColors(40);
var pointMapChart = dc.bubbleRasterChart(parent, true)
.height(h/1.5)
.width(w)
.dimension(pointMapDim)
.group(pointMapDim)
.tableName("tweets")
.mapUpdateInterval(750)
.popupSearchRadius(2)
.cap(1500000)
.sampling(true)
.r(1)
.dynamicR(d3.scale.sqrt().domain([20000,0]).range([1.0,7.0]).clamp(true))
.othersGrouper(false)
.xDim(xDim)
.yDim(yDim)
.colorBy('lang')
.popupColumns(['tweet_text', 'sender_name', 'tweet_time', 'lang', 'origin'])
.colors(d3.scale.ordinal().domain(langDomain).range(langColors))
.defaultColor("#80DEEA");
function mapLangColors(n) {
langDomain = langDomain.slice(0, n);
for (var i = 0; i < langDomain.length; i++) {
langColors.push(langOriginColors[i%langOriginColors.length]);
}
}
/*---------------------TIME CHART EXAMPLE----------------------------------*/
/*
* First we want to determine the extent (min,max) of the time variable so we
* can set the bounds on the time chart appropriately.
*
* If you know the bounds a priori you can do this manually but here we will
* do it dymaically via a query sent to the backend through the crossfilter
* api.
*
* We create a reduceMulti expression that will get the min and max of the
* variable dep_timestamp.
*
*/
var timeChartMeasures = [
{
expression: "tweet_time",
agg_mode:"min",
name: "min"
},
{
expression: "tweet_time",
agg_mode:"max",
name: "max"}
]
/* Note than when we are doing aggregations over the entire dataset we use
* the crossfilter object itself as the dimension with the groupAll method
*
* values(true) gets the values for our groupAll measure (here min and max
* of dep_timestamp) - true means to ignore currently set filters - i.e.
* get a global min and max
*/
var timeChartBounds = crossFilter
.groupAll()
.reduce(timeChartMeasures)
.values(true);
var timeChartDimension = crossFilter.dimension("tweet_time");
/* We would like to bin or histogram the time values. We do this by
* invoking setBinParams on the group. Here we are asking for 400 equal
* sized bins from the min to the max of the time range
*/
var timeChartGroup = timeChartDimension
.group()
.reduceCount('*')
.setBinParams({
numBins: 288, // 288 * 5 = number of minutes in a day
binBounds: [timeChartBounds.min, timeChartBounds.max]
});
/* We create the time chart as a line chart
* with the following parameters:
*
* Width and height - as above
*
* elasticY(true) - cause the y-axis to scale as filters are changed
*
* renderHorizontalGridLines(true) - add grid lines to the chart
*
* brushOn(true) - Request a filter brush to be added to the chart - this
* will allow users to drag a filter window along the time chart and filter
* the rest of the data accordingly
*
*/
var dcTimeChart = dc.lineChart('.chart2-example')
.width(w)
.height(h/2.5)
.elasticY(true)
.renderHorizontalGridLines(true)
.brushOn(true)
.xAxisLabel('Time of Day')
.yAxisLabel('Number of Tweets')
.dimension(timeChartDimension)
.group(timeChartGroup);
/* Set the x and y axis formatting with standard d3 functions */
dcTimeChart
.x(d3.time.scale.utc().domain([timeChartBounds.min, timeChartBounds.max]))
.yAxis().ticks(5);
dcTimeChart
.xAxis().orient('top');
/* Calling dc.renderAll() will render all of the charts we set up. Any
* filters applied by the user (via clicking the bar chart, scatter plot or dragging the time brush) will automagically call redraw on the charts without any intervention from us
*/
dc.renderAll()
/*--------------------------RESIZE EVENT------------------------------*/
/* Here we listen to any resizes of the main window. On resize we resize the corresponding widgets and call dc.renderAll() to refresh everything */
window.addEventListener("resize", debounce(reSizeAll, 100));
function reSizeAll(){
var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0) - 50
var h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0) - 200
pointMapChart._map.resize();
pointMapChart.isNodeAnimate = false;
pointMapChart
.width(w)
.height(h/1.5)
.render();
dcTimeChart
.width(w)
.height(h/2.5)
dc.renderAll();
}
}
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
function init() {
// Get a table from the database
var tables = con.getTables();
var tableName = tables[0].name;
var label = "tweets";
// A CrossFilter instance is used for generating the raw query strings for your MapdCon.
var crossFilter = crossfilter(con, tableName, label);
// Pass instance of crossfilter into our CreateCharts.
createCharts(crossFilter);
}
document.addEventListener('DOMContentLoaded', init, false);
// A MapdCon instance is used for performing raw queries on a MapD GPU database.
var con = new MapdCon()
.protocol("http")
.host("kali.mapd.com")
.port("9092")
.dbName("mapd")
.user("mapd")
.password("HyperInteractive");
// Establish a connection
con.connect();
</script>
</body>
</html>