diff --git a/lib/torque/leaflet/torque.js b/lib/torque/leaflet/torque.js index 358eba3..dce0534 100644 --- a/lib/torque/leaflet/torque.js +++ b/lib/torque/leaflet/torque.js @@ -72,7 +72,6 @@ L.TorqueLayer = L.CanvasLayer.extend({ this.setDuration = this.animator.duration.bind(this.animator); this.isRunning = this.animator.isRunning.bind(this.animator); - L.CanvasLayer.prototype.initialize.call(this, options); this.options.renderer = this.options.renderer || 'point'; @@ -103,26 +102,32 @@ L.TorqueLayer = L.CanvasLayer.extend({ this.renderer.on("allIconsLoaded", this.render.bind(this)); - // for each tile shown on the map request the data this.on('tileAdded', function(t) { - var successCallback = function (tileData) { - // don't load tiles that are not being shown - if (t.zoom !== self._map.getZoom()) return; - self._tileLoaded(t, tileData); - self._clearTileCaches(); - if (tileData) { - self.redraw(); + var callback = function (tileData, error) { + self._onTileAdded(t, tileData); + + if (error) { + self.fire('tileError', error); } + self.fire('tileLoaded'); }; - var errorCallback = function (error) { - self.fire('tileError', error); - } - var tileData = this.provider.getTileData(t, t.zoom, successCallback, errorCallback); + var tileData = this.provider.getTileData(t, t.zoom, callback); }, this); + }, + _onTileAdded: function(t, tileData) { + // don't load tiles that are not being shown + if (t.zoom !== this._map.getZoom()) return; + + this._tileLoaded(t, tileData); + this._clearTileCaches(); + + if (tileData) { + this.redraw(); + } }, _clearTileCaches: function() { diff --git a/lib/torque/provider/windshaft.js b/lib/torque/provider/windshaft.js index 17d346a..ecb68e1 100644 --- a/lib/torque/provider/windshaft.js +++ b/lib/torque/provider/windshaft.js @@ -186,6 +186,17 @@ }; }, + proccessTileError: function(error, coord, zoom) { + return { + error: error, + coord: { + x: coord.x, + y: coord.y, + z: zoom + } + }; + }, + /*setCartoCSS: function(c) { this.options.cartocss = c; },*/ @@ -281,7 +292,7 @@ * `coord` object like {x : tilex, y: tiley } * `zoom` quadtree zoom level */ - _getTileData: function(coord, zoom, successCallback, errorCallback) { + _getTileData: function(coord, zoom, callback) { var self = this; var prof_fetch_time = Profiler.metric('torque.provider.windshaft.tile.fetch').start(); var subdomains = this.options.subdomains || '0123'; @@ -300,9 +311,13 @@ if (response && response.responseText) { var body = JSON.parse(response.responseText); - response.status === 429 - ? errorCallback(body.errors_with_context[0]) - : successCallback(self.proccessTile(body, coord, zoom)); + if (response.status === 429) { + var error = body.errors_with_context[0]; + + callback(self.proccessTileError(error, coord, zoom), error); + } else { + callback(self.proccessTile(body, coord, zoom)); + } } else { Profiler.metric('torque.provider.windshaft.tile.error').inc(); successCallback(null); diff --git a/lib/torque/renderer/point.js b/lib/torque/renderer/point.js index dacf183..4b82e37 100644 --- a/lib/torque/renderer/point.js +++ b/lib/torque/renderer/point.js @@ -6,7 +6,8 @@ var Filters = require('./torque_filters'); var turbocarto = require('turbo-carto'); var CartoDatasource = require('./datasource'); - var TAU = Math.PI * 2; + var ERROR_IMG_URL = 'http://matataonboarding.localhost.lan:3000/assets/4.10.67/images/error.svg'; + var DEFAULT_CARTOCSS = [ '#layer {', ' marker-fill: #662506;', @@ -120,6 +121,10 @@ var CartoDatasource = require('./datasource'); if (PointRenderer.isTurboCarto(cartocss)) { var datasource = new CartoDatasource(self.layer._tiles); turbocarto(cartocss, datasource, function (err, parsedCartoCSS) { + if (err) { + return callback(err, null); + } + self.setShader(new carto.RendererJS().render(parsedCartoCSS)); self.layer.redraw(); self.layer.animator.start(); @@ -137,6 +142,8 @@ var CartoDatasource = require('./datasource'); this._shader = shader; this._Map = this._shader.getDefault().getStyle({}, { zoom: 0 }); var img_names = this._shader.getImageURLs(); + img_names.push(ERROR_IMG_URL); + this._preloadIcons(img_names); }, @@ -212,6 +219,12 @@ var CartoDatasource = require('./datasource'); // renders all the layers (and frames for each layer) from cartocss // renderTile: function(tile, keys, callback) { + if (tile.error) { + this._renderErrorTile(tile); + + return false; + } + if (this._iconsToLoad > 0) { this.on('allIconsLoaded', function() { this.renderTile.apply(this, [tile, keys, callback]); @@ -283,6 +296,11 @@ var CartoDatasource = require('./datasource'); } }, + _renderErrorTile: function(tile) { + var img = this._icons[ERROR_IMG_URL]; + img && this._ctx.drawImage(img, 0, 0, this.TILE_SIZE, this.TILE_SIZE); + }, + // // renders a tile in the canvas for key defined in // the torque tile @@ -464,47 +482,47 @@ var CartoDatasource = require('./datasource'); } else { this.fire("allIconsLoaded"); } - }, + }, - applyFilters: function(){ - if(this._style){ - if(this._style['image-filters']){ - function gradientKey(imf){ - var hash = "" - for(var i = 0; i < imf.args.length; i++){ - var rgb = imf.args[i].rgb; - hash += rgb[0] + ":" + rgb[1] + ":" + rgb[2]; + applyFilters: function(){ + if(this._style){ + if(this._style['image-filters']){ + function gradientKey(imf){ + var hash = "" + for(var i = 0; i < imf.args.length; i++){ + var rgb = imf.args[i].rgb; + hash += rgb[0] + ":" + rgb[1] + ":" + rgb[2]; + } + return hash; } - return hash; + var gradient = this._gradients[gradientKey(this._style['image-filters'])]; + if(!gradient){ + function componentToHex(c) { + var hex = c.toString(16); + return hex.length == 1 ? "0" + hex : hex; + } + + function rgbToHex(r, g, b) { + return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b); + } + gradient = {}; + var colorize = this._style['image-filters'].args; + + var increment = 1/colorize.length; + for (var i = 0; i < colorize.length; i++){ + var key = increment * i + increment; + var rgb = colorize[i].rgb; + var formattedColor = rgbToHex(rgb[0], rgb[1], rgb[2]); + gradient[key] = formattedColor; + } + this._gradients[gradientKey(this._style['image-filters'])] = gradient; + } + this._filters.gradient(gradient); + this._filters.draw(); } - var gradient = this._gradients[gradientKey(this._style['image-filters'])]; - if(!gradient){ - function componentToHex(c) { - var hex = c.toString(16); - return hex.length == 1 ? "0" + hex : hex; - } - - function rgbToHex(r, g, b) { - return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b); - } - gradient = {}; - var colorize = this._style['image-filters'].args; - - var increment = 1/colorize.length; - for (var i = 0; i < colorize.length; i++){ - var key = increment * i + increment; - var rgb = colorize[i].rgb; - var formattedColor = rgbToHex(rgb[0], rgb[1], rgb[2]); - gradient[key] = formattedColor; - } - this._gradients[gradientKey(this._style['image-filters'])] = gradient; - } - this._filters.gradient(gradient); - this._filters.draw(); } } - } -}); + }); PointRenderer.isTurboCarto = function (cartocss) { var reservedWords = ['ramp', 'colorbrewer', 'buckets']