149 lines
4.1 KiB
JavaScript
149 lines
4.1 KiB
JavaScript
const Backbone = require('backbone');
|
|
const $ = require('jquery');
|
|
const carto = require('@carto/carto.js');
|
|
const L = require('leaflet');
|
|
const CoreView = require('backbone/core-view');
|
|
const checkAndBuildOpts = require('builder/helpers/required-opts');
|
|
const template = require('./map-view.tpl');
|
|
const { simple: styles } = require('builder/data/default-cartography.json');
|
|
|
|
const REQUIRED_OPTS = [
|
|
'username',
|
|
'serverUrl',
|
|
'sqlUrl',
|
|
'vizjson',
|
|
'dataset'
|
|
];
|
|
|
|
module.exports = CoreView.extend({
|
|
events: {
|
|
'click .js-bounds': '_changeBounds'
|
|
},
|
|
|
|
className: 'map',
|
|
|
|
initialize: function (opts) {
|
|
checkAndBuildOpts(opts, REQUIRED_OPTS, this);
|
|
|
|
this.model = new Backbone.Model();
|
|
|
|
this.model.on('change:bounds', this._boundsClick, this);
|
|
},
|
|
|
|
_changeBounds: function () {
|
|
this.model.set('bounds', !this.model.get('bounds'));
|
|
},
|
|
|
|
_boundsClick: function () {
|
|
this.trigger('boundsChanged', { bounds: this.model.get('bounds') });
|
|
this.$('.js-bounds .Checkbox-input').toggleClass('is-checked', !!this.model.get('bounds'));
|
|
},
|
|
|
|
render: function () {
|
|
this.$el.html(template());
|
|
const mapEl = this.$el.find('.carto-map')[0];
|
|
this.map = L.map(mapEl).setView([0, 0], 0);
|
|
|
|
this.map.on('zoomend moveend', () => {
|
|
this.trigger('mapBoundsChanged', {
|
|
bounds: this.map.getBounds(),
|
|
center: this.map.getCenter(),
|
|
zoom: this.map.getZoom()
|
|
});
|
|
});
|
|
|
|
L.tileLayer('https://{s}.basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png', {
|
|
maxZoom: 18
|
|
}).addTo(this.map);
|
|
|
|
this.client = new carto.Client({
|
|
apiKey: 'default_public',
|
|
serverUrl: this._serverUrl,
|
|
username: this._username
|
|
});
|
|
|
|
this.dataset = new carto.source.Dataset(this._dataset);
|
|
const cartocss = new carto.style.CartoCSS('#layer {}');
|
|
|
|
this.cartoLayer = new carto.layer.Layer(this.dataset, cartocss);
|
|
|
|
this.client.addLayer(this.cartoLayer);
|
|
|
|
this.client.getLeafletLayer().addTo(this.map);
|
|
|
|
this._fetchBounds();
|
|
|
|
return this;
|
|
},
|
|
|
|
enableMap: function () {
|
|
this.map.invalidateSize();
|
|
},
|
|
|
|
setGeometry: function ([geom]) {
|
|
let style;
|
|
|
|
switch (geom) {
|
|
case 'ST_Linestring':
|
|
style = `#layer {
|
|
line-color: ${styles.line.stroke.color.fixed};
|
|
line-width: ${styles.line.stroke.size.fixed};
|
|
line-opacity: ${styles.line.stroke.color.opacity};
|
|
}
|
|
`;
|
|
break;
|
|
case 'ST_Point':
|
|
style = `#layer {
|
|
marker-width: ${styles.point.fill.size.fixed};
|
|
marker-fill: ${styles.point.fill.color.fixed};
|
|
marker-fill-opacity: ${styles.point.fill.color.opacity};
|
|
marker-line-color: ${styles.point.stroke.color.fixed};
|
|
marker-line-width: ${styles.point.stroke.size.fixed};
|
|
marker-line-opacity: ${styles.point.stroke.color.opacity};
|
|
marker-placement: point;
|
|
marker-type: ellipse;
|
|
marker-allow-overlap: true;
|
|
}`;
|
|
break;
|
|
case 'ST_Polygon':
|
|
style = `#layer {
|
|
polygon-fill: ${styles.polygon.fill.color.fixed};
|
|
polygon-opacity: ${styles.polygon.fill.color.opacity};
|
|
::outline {
|
|
line-color: ${styles.polygon.stroke.color.fixed};
|
|
line-width: ${styles.polygon.stroke.size.fixed};
|
|
line-opacity: ${styles.polygon.stroke.color.opacity};
|
|
}
|
|
}`;
|
|
break;
|
|
default:
|
|
style = `#layer {}`;
|
|
break;
|
|
}
|
|
|
|
this.cartoLayer.setStyle(new carto.style.CartoCSS(style));
|
|
},
|
|
|
|
_fetchBounds: function () {
|
|
$.ajax({
|
|
type: 'GET',
|
|
data: 'q=' + encodeURIComponent(`SELECT ST_Extent(the_geom) as extent FROM ${this._dataset}`) + '&api_key=default_public',
|
|
url: this._sqlUrl,
|
|
success: (data) => {
|
|
const bounds = data.rows[0].extent;
|
|
const parsedBounds = /BOX\((.+) (.+),(.+) (.+)\)/.exec(bounds)
|
|
.splice(1, 4)
|
|
.map(e => parseFloat(e));
|
|
this.map.fitBounds([
|
|
[parsedBounds[1], parsedBounds[0]], [parsedBounds[3], parsedBounds[2]]
|
|
]);
|
|
},
|
|
error: () => {}
|
|
});
|
|
},
|
|
|
|
invalidateMap: function () {
|
|
this.map.invalidateSize();
|
|
}
|
|
});
|