From 0209c52acfb006a2ad1f204b442581e997a04629 Mon Sep 17 00:00:00 2001 From: Andrew Hill Date: Wed, 17 Apr 2013 18:35:15 -0400 Subject: [PATCH] added "istime" parameter to the options, now numeric columns should work as the sort, will fubar any clock though as a lot of the internals still think they are dates --- examples/osm.html | 3 ++- src/grid_layer.js | 23 +++++++++++++++------ src/torque.js | 10 ++++++++- template/css/time-dataview.css | 25 ++++++++++++++++++----- template/time-dataview.html | 37 ++++++++++++++++++++++++++++------ 5 files changed, 79 insertions(+), 19 deletions(-) diff --git a/examples/osm.html b/examples/osm.html index 7f19b40..fb2e366 100644 --- a/examples/osm.html +++ b/examples/osm.html @@ -69,7 +69,8 @@ var TorqueOptions = { user: "viz2", table: "madrid_osm_line", - column: "fake_date", + column: "osm_id", + istime: false, cumulative: false, resolution: 2, steps: 750, diff --git a/src/grid_layer.js b/src/grid_layer.js index 1f99ee4..d758e01 100644 --- a/src/grid_layer.js +++ b/src/grid_layer.js @@ -157,6 +157,17 @@ TimePlayer.prototype.get_time_data = function (tile, coord, zoom) { // take se and sd as a matrix [se|sd] var numTiles = 1 << zoom; var sql = "" + var column_conv = ""; + var expir_conv = ""; + + if (this.options.istime == true){ + column_conv = "date_part('epoch',{0})".format(this.t_column); + expir_conv = "date_part('epoch',{0})".format(this.options.expiration_column); + } else { + column_conv = this.t_column; + expir_conv = this.options.expiration_column; + } + if ( this.options.cumulative_expires == true) { sql = "WITH hgrid AS ( " + " SELECT CDB_RectangleGrid( " + @@ -172,16 +183,16 @@ TimePlayer.prototype.get_time_data = function (tile, coord, zoom) { " round(CAST (st_xmax(hgrid.cell) AS numeric),4) x, " + " round(CAST (st_ymax(hgrid.cell) AS numeric),4) y, " + " {0} c, ".format(this.countby) + - " floor((date_part('epoch',{0})- {1})/{2}) d, ".format(this.t_column, this.MIN_DATE, this.step) + - " floor((date_part('epoch',{0})- {1})/{2}) de ".format(this.options.expiration_column, this.MIN_DATE, this.step) + + " floor(({0}- {1})/{2}) d, ".format(column_conv, this.MIN_DATE, this.step) + + " floor(({0}- {1})/{2}) de ".format(expir_conv, this.MIN_DATE, this.step) + " FROM " + " hgrid, {0} i ".format(this.table) + " WHERE " + " ST_Intersects(i.the_geom_webmercator, hgrid.cell) " + " GROUP BY " + " hgrid.cell, " + - " floor((date_part('epoch',{0})- {1})/{2}), ".format(this.t_column, this.MIN_DATE, this.step) + - " floor((date_part('epoch',{0})- {1})/{2})".format(this.options.expiration_column, this.MIN_DATE, this.step) + + " floor(({0}- {1})/{2}), ".format(column_conv, this.MIN_DATE, this.step) + + " floor(({0}- {1})/{2})".format(expir_conv, this.MIN_DATE, this.step) + " ) f GROUP BY x, y"; } else { sql = "WITH hgrid AS ( " + @@ -196,13 +207,13 @@ TimePlayer.prototype.get_time_data = function (tile, coord, zoom) { " FROM ( " + " SELECT " + " round(CAST (st_xmax(hgrid.cell) AS numeric),4) x, round(CAST (st_ymax(hgrid.cell) AS numeric),4) y, " + - " {0} c, floor((date_part('epoch',{1})- {2})/{3}) d ".format(this.countby, this.t_column, this.MIN_DATE, this.step) + + " {0} c, floor(({1}- {2})/{3}) d ".format(this.countby, column_conv, this.MIN_DATE, this.step) + " FROM " + " hgrid, {0} i ".format(this.table) + " WHERE " + " ST_Intersects(i.the_geom_webmercator, hgrid.cell) " + " GROUP BY " + - " hgrid.cell, floor((date_part('epoch',{0})- {1})/{2})".format(this.t_column, this.MIN_DATE, this.step) + + " hgrid.cell, floor(({0} - {1})/{2})".format(column_conv, this.MIN_DATE, this.step) + " ) f GROUP BY x, y"; } diff --git a/src/torque.js b/src/torque.js index 8f5b108..087c5b1 100644 --- a/src/torque.js +++ b/src/torque.js @@ -76,6 +76,7 @@ Torque.modules.layer = function (torque) { user:'viz2', table:'ny_bus', column:'timestamp', + istime: true, steps:250, resolution:3, cumulative:false, @@ -185,7 +186,14 @@ Torque.modules.layer = function (torque) { }, getDeltas:function (options) { var that = this; - var sql = "SELECT st_xmax(st_envelope(st_collect(the_geom))) xmax,st_ymax(st_envelope(st_collect(the_geom))) ymax, st_xmin(st_envelope(st_collect(the_geom))) xmin, st_ymin(st_envelope(st_collect(the_geom))) ymin, date_part('epoch',max({0})) max, date_part('epoch',min({0})) min FROM {1}".format(this.options.column, this.options.table); + if (this.options.istime == true){ + var max_col = "date_part('epoch',max({0}))".format(this.options.column); + var min_col = "date_part('epoch',min({0}))".format(this.options.column); + } else { + var max_col = "max({0})".format(this.options.column); + var min_col = "min({0})".format(this.options.column); + } + var sql = "SELECT st_xmax(st_envelope(st_collect(the_geom))) xmax,st_ymax(st_envelope(st_collect(the_geom))) ymax, st_xmin(st_envelope(st_collect(the_geom))) xmin, st_ymin(st_envelope(st_collect(the_geom))) ymin, {0} max, {1} min FROM {2}".format(max_col, min_col, this.options.table); var timeExtents = this._cartodb.CartoDBCollection.extend({ sql:sql diff --git a/template/css/time-dataview.css b/template/css/time-dataview.css index 67449a1..8f0de97 100644 --- a/template/css/time-dataview.css +++ b/template/css/time-dataview.css @@ -33,25 +33,40 @@ body { } #slider-spark .head { position: relative; - background: transparent; + background: steelblue; border: 2px solid steelblue; width: 10px; height: 10px; border-radius: 6px; cursor: pointer; + z-index: 5; } #slider-spark .pin { position: relative; - background: rgba(255,191,0,0.5); + background: rgba(255,191,0,0.2); + margin-top: -3px; border: 0px; - margin-left: 6px; + margin-left: 3px; + margin-right: 3px; + padding-left: 3px; + padding-right: 3px; width: 2px; - height: 180px; + height: 183px; } path { stroke: steelblue; - stroke-width: 1; + stroke-width: 2; fill: none; } +circle { + stroke: steelblue; +} +text { + font-family: Arial; + font-size: 9pt; + font-color: white; + stroke-weight: 300; + stroke: rgba(255,255,255,0.45); +} .axis { shape-rendering: crispEdges; } diff --git a/template/time-dataview.html b/template/time-dataview.html index f849951..a30dbab 100644 --- a/template/time-dataview.html +++ b/template/time-dataview.html @@ -38,7 +38,9 @@ var sql = new cartodb.SQL({ user: user_name}); var table_name = 'ow'; var date_col = 'date'; + var date_format = 'year' //year, time or date var steps = 750; + var wm = 10; //left/right margins var map = new google.maps.Map(document.getElementById('map'), { center:new google.maps.LatLng(30.95940879245423, -0.609375), @@ -78,29 +80,30 @@ - var wm = 10; //left/right margins - sql.execute("WITH extents AS (SELECT max({{date_col}}) mx, min({{date_col}}) mn FROM {{table_name}} WHERE the_geom IS NOT NULL) SELECT count(*) count, mn + i*(mx - mn)/{{steps}} frame FROM {{table_name}}, extents, GENERATE_SERIES(1,{{steps}}) i WHERE mn + (i-1)*(mx - mn)/{{steps}} < {{date_col}} AND {{date_col}} < mn + (i)*(mx - mn)/{{steps}} GROUP BY mn + i*(mx - mn)/{{steps}} ORDER BY mn + i*(mx - mn)/{{steps}} ASC", {table_name: table_name, date_col: date_col, steps: steps}) - .error(function(e){console.log(e)}) + .error(function(e){ }) .done(function(data){ - console.log(data) var m = 20; var w = $('#slider-container').width(); var h = $('#slider-container').height()-2*m; data = data.rows; + + var mxX = new Date(data[data.length-1].frame); var mnX = new Date(data[0].frame); var mxY = data[0].count, mnY = data[0].count; + $.each(data,function(i,d){ if (d.count < mnY) mnY = d.count; if (mxY < d.count) mxY = d.count; }) - var x = d3.scale.linear().domain([0, data.length]).range([0, w - 2*wm ]); + var x = d3.scale.linear().domain([mnX, mxX]).range([0, w - 2*wm ]); + // var x = d3.scale.linear().domain([0, data.length]).range([0, w - 2*wm ]); var y = d3.scale.linear().domain([mnY, mxY]).range([h, 0]); var line = d3.svg.line() .x(function(d,i) { - return x(i); + return x(new Date(d.frame)); }) .y(function(d) { return y(d.count); @@ -112,6 +115,28 @@ .attr("height", h + m) .append("svg:g"); + graph.selectAll(".xLabel") + .data(x.ticks(10)) + .enter().append("svg:text") + .attr("class", "xLabel") + .text(function(i, d) { + // if (d==0) {return null} + if (date_format == 'time'){ + return new Date(i).toTimeString().split(' ')[0]; + } + else if (date_format == 'year') { + return new Date(i).getFullYear(); + } + else { + var d = new Date(i).toDateString().split(' '); + return d.slice(1, 4).join(' ') + } + }) + .attr("x", function(d) { return x(new Date(d)) }) + .attr("y", h+18) + .attr("text-anchor", "middle") + + graph.append("svg:path").attr("d", line(data)); var TorqueOptions = {