cartodb-4.42/lib/assets/javascripts/dashboard/views/public-dataset/map-view/map-view.js
2024-04-06 05:25:13 +00:00

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();
}
});