2016-08-16 09:25:19 -07:00

159 lines
5.5 KiB
JavaScript

document.addEventListener("DOMContentLoaded", function init() {
// var config = {
// table: "tweets_nov_feb",
// valueColumn: "tweets_nov_feb.tweet_count",
// joinColumn: "tweets_nov_feb.state_abbr",
// polyTable: "states",
// polyJoinColumn: "STATE_ABBR",
// timeColumn: "tweet_time",
// timeLabel: "Number of Tweets",
// domainBoundMin: 12196,
// domainBoundMax: 32586,
// numTimeBins: 288 // 288 * 5 = number of minutes in a day.
// }
var config = {
table: "contributions",
valueColumn: "contributions.amount",
joinColumn: "contributions.contributor_zipcode",
polyTable: "zipcodes",
polyJoinColumn: "ZCTA5CE10",
timeColumn: "contrib_date",
timeLabel: "Number of Contributions",
domainBoundMin: 0,
domainBoundMax: 2600,
numTimeBins: 423
}
new MapdCon()
.protocol("http")
.host("kali.mapd.com")
.port("9092")
.dbName("mapd")
.user("mapd")
.password("HyperInteractive")
.connect(function(error, con) {
crossfilter.crossfilter(con, config.table).then(function(cf) {
createPolyMap(cf, con, dc, config)
createTimeChart(cf, dc, config)
})
})
function createPolyMap(crossFilter, con, dc, config) {
var parent = document.getElementById("polymap")
// The values in the table and column specified in crossFilter.dimension
// must correspond to values in the table and keysColumn specified in polyRasterChart.polyJoin.
var dim = crossFilter.dimension(config.joinColumn) // Values to join on.
var grp = dim.group().reduceAvg(config.valueColumn) // Values to color on.
// var dim = crossFilter.dimension("tweets_nov_feb.state_abbr") // Values to join on.
// var grp = dim.group().reduceAvg("tweets_nov_feb.tweet_count") // Values to color on.
// Can use getDomainBounds to dynamically find min and max of values that will be colored,
// or the domain [min, max] can be set directly
// (in which case nesting chart creation inside this callback is unnecessary).
getDomainBounds(config.valueColumn, dim.groupAll(), function(domainBounds){
// Can set colorDomain directly or use domainFromBoundsAndRange to generate a .
var colorRange = ["#115f9a","#1984c5","#22a7f0","#48b5c4","#76c68f","#a6d75b","#c9e52f","#d0ee11","#d0f400"]
var colorDomain = domainFromBoundsAndRange(config.domainBoundMin, config.domainBoundMax, colorRange)
// var colorDomain = domainFromBoundsAndRange(domainBounds.minimum, domainBounds.maximum, colorRange)
var polyMap = dc
.polyRasterChart(parent, true)
.con(con)
.height(height()/1.5)
.width(width())
.dimension(dim)
.group(grp)
.tableName(config.table)
.mapUpdateInterval(750) // ms
.othersGrouper(false)
.opacity(0.90)
.mapStyle("mapbox://styles/mapbox/light-v8")
.polyJoin({table: config.polyTable, keysColumn: config.polyJoinColumn})
.colors(d3.scale.linear().domain(colorDomain).range(colorRange))
.borderColor("white")
polyMap.borderWidth(zoomToBorderWidth(polyMap.map().getZoom()))
// Keeps the border widths reasonable regardless of zoom level.
polyMap.map().on("zoom", function() {
polyMap.borderWidth(zoomToBorderWidth(polyMap.map().getZoom()))
})
dc.renderAllAsync()
window.addEventListener("resize", _.debounce(function(){ resizeChart(polyMap, 1.5) }, 500))
})
}
function getDomainBounds (column, groupAll, callback) {
groupAll.reduce([
{expression: column, agg_mode: "min", name: "minimum"},
{expression: column, agg_mode: "max", name: "maximum"}
]).valuesAsync(true).then(callback)
}
function domainFromBoundsAndRange (min, max, range) {
return _.range(0, range.length).map((_, i) => min + Math.round(i * max / (range.length - 1)))
}
function zoomToBorderWidth (zoomLevel) {
var MIN_ZOOM = 0.8626373575587937
var ZOOM_BORDER_DIVISOR = 20
return zoomLevel / ZOOM_BORDER_DIVISOR - MIN_ZOOM / ZOOM_BORDER_DIVISOR
}
function createTimeChart(crossFilter, dc, config) {
getDomainBounds(config.timeColumn, crossFilter.groupAll(), function(timeChartBounds){
var timeChartDimension = crossFilter.dimension(config.timeColumn)
var timeChartGroup = timeChartDimension
.group()
.reduceCount("*")
.setBinParams({
numBins: config.numTimeBins,
binBounds: [timeChartBounds.minimum, timeChartBounds.maximum]
})
var timeChart = dc.lineChart("#timechart")
.width(width())
.height(height()/2.5)
.elasticY(true)
.renderHorizontalGridLines(true)
.brushOn(true)
.xAxisLabel("Time")
.yAxisLabel(config.timeLabel)
.dimension(timeChartDimension)
.group(timeChartGroup)
timeChart.x(d3.time.scale.utc().domain([timeChartBounds.minimum, timeChartBounds.maximum]))
timeChart.yAxis().ticks(5)
timeChart.xAxis().orient("top")
dc.renderAllAsync()
window.addEventListener("resize", _.debounce(function () { resizeChart(timeChart, 2.5) }, 500))
})
}
function width () {
return document.documentElement.clientWidth - 30
}
function height () {
return (Math.max(document.documentElement.clientHeight, window.innerHeight || 0) - 200)
}
function resizeChart (chart, heightDivisor) {
if(typeof chart.map === "function"){
chart.map().resize()
chart.isNodeAnimate = false
}
chart
.width(width())
.height(height()/heightDivisor)
.renderAsync()
dc.renderAllAsync()
}
function noop () {}
})