Skip to content
Snippets Groups Projects
Commit 337a34c8 authored by anonymous's avatar anonymous
Browse files

try usging projections with map

parent 67f06997
Branches
Tags
No related merge requests found
(function (ckan, jQuery) {
/* Returns a Leaflet map to use on the different spatial widgets
*
* All Leaflet based maps should use this constructor to provide consistent
* look and feel and avoid duplication.
*
* container - HTML element or id of the map container
* mapConfig - (Optional) CKAN config related to the base map.
* These are defined in the config ini file (eg
* map type, API keys if necessary, etc).
* leafletMapOptions - (Optional) Options to pass to the Leaflet Map constructor
* leafletBaseLayerOptions - (Optional) Options to pass to the Leaflet TileLayer constructor
*
* Examples
*
* // Will return a map with attribution control
* var map = ckan.commonLeafletMap('map', mapConfig);
*
* // For smaller maps where the attribution is shown outside the map, pass
* // the following option:
* var map = ckan.commonLeafletMap('map', mapConfig, {attributionControl: false});
*
* Returns a Leaflet map object.
*/
ckan.commonLeafletMap = function (container,
mapConfig,
leafletMapOptions,
leafletBaseLayerOptions) {
var isHttps = window.location.href.substring(0, 5).toLowerCase() === 'https';
var mapConfig = mapConfig || {type: 'stamen'};
var leafletMapOptions = leafletMapOptions || {};
var leafletBaseLayerOptions = jQuery.extend(leafletBaseLayerOptions, {
maxZoom: 18
});
var baseLayer;
map = new L.Map(container, leafletMapOptions);
if (mapConfig.type == 'mapbox') {
// MapBox base map
if (!mapConfig['mapbox.map_id'] || !mapConfig['mapbox.access_token']) {
throw '[CKAN Map Widgets] You need to provide a map ID ([account].[handle]) and an access token when using a MapBox layer. ' +
'See http://www.mapbox.com/developers/api-overview/ for details';
}
baseLayerUrl = '//{s}.tiles.mapbox.com/v4/' + mapConfig['mapbox.map_id'] + '/{z}/{x}/{y}.png?access_token=' + mapConfig['mapbox.access_token'];
leafletBaseLayerOptions.handle = mapConfig['mapbox.map_id'];
leafletBaseLayerOptions.subdomains = mapConfig.subdomains || 'abcd';
leafletBaseLayerOptions.attribution = mapConfig.attribution || 'Data: <a href="http://osm.org/copyright" target="_blank">OpenStreetMap</a>, Design: <a href="http://mapbox.com/about/maps" target="_blank">MapBox</a>';
baseLayer = new L.TileLayer(baseLayerUrl, leafletBaseLayerOptions);
} else if (mapConfig.type == 'custom') {
// Custom XYZ layer
baseLayerUrl = mapConfig['custom.url'];
if (mapConfig.subdomains) leafletBaseLayerOptions.subdomains = mapConfig.subdomains;
if (mapConfig.tms) leafletBaseLayerOptions.tms = mapConfig.tms;
leafletBaseLayerOptions.attribution = mapConfig.attribution;
baseLayer = new L.TileLayer(baseLayerUrl, leafletBaseLayerOptions);
} else if (mapConfig.type == 'wms') {
baseLayerUrl = mapConfig['wms.url'];
wmsOptions = {}
wmsOptions['layers'] = mapConfig['wms.layers'];
wmsOptions['styles'] = mapConfig['wms.styles'] || '';
wmsOptions['format'] = mapConfig['wms.format'] || 'image/png';
if(mapConfig['wms.srs'] || mapConfig['wms.crs']) {
wmsOptions['crs'] = mapConfig['wms.srs'] || mapConfig['wms.crs'];
}
wmsOptions['version'] = mapConfig['wms.version'] || '1.1.1';
baseLayer = new L.TileLayer.WMS(baseLayerUrl, wmsOptions);
} else {
// Default to Stamen base map
baseLayerUrl = 'https://stamen-tiles-{s}.a.ssl.fastly.net/terrain/{z}/{x}/{y}.png';
leafletBaseLayerOptions.subdomains = mapConfig.subdomains || 'abcd';
leafletBaseLayerOptions.attribution = mapConfig.attribution || 'Map tiles by <a href="http://stamen.com">Stamen Design</a> (<a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>). Data by <a href="http://openstreetmap.org">OpenStreetMap</a> (<a href="http://creativecommons.org/licenses/by-sa/3.0">CC BY SA</a>)';
baseLayer = new L.TileLayer(baseLayerUrl, leafletBaseLayerOptions);
}
map.addLayer(baseLayer);
return map;
}
})(this.ckan, this.jQuery);
This diff is collapsed.
ckan.module('odsh-map', function ($)
{
return {
initialize: function ()
{
console.log('ini')
$('.leaflet-control-zoom-in').prop('title', 'your new title');
}
};
});
\ No newline at end of file
/* Module for handling the spatial querying
*/
this.ckan.module('odsh-spatial-query', function ($, _)
{
return {
options: {
i18n: {
},
style: {
color: '#F06F64',
weight: 2,
opacity: 1,
fillColor: '#F06F64',
fillOpacity: 0.1,
clickable: false
},
default_extent: [[90, 180], [-90, -180]]
},
template: {
buttons: [
'<div id="dataset-map-edit-buttons">',
'<a href="javascript:;" class="btn cancel">Cancel</a> ',
'<a href="javascript:;" class="btn apply disabled">Apply</a>',
'</div>'
].join('')
},
initialize: function ()
{
var module = this;
$.proxyAll(this, /_on/);
console.log(module)
var user_default_extent = this.el.data('default_extent');
if (user_default_extent)
{
if (user_default_extent instanceof Array)
{
// Assume it's a pair of coords like [[90, 180], [-90, -180]]
this.options.default_extent = user_default_extent;
} else if (user_default_extent instanceof Object)
{
// Assume it's a GeoJSON bbox
this.options.default_extent = new L.GeoJSON(user_default_extent).getBounds();
}
}
this.el.ready(this._onReady);
},
_getParameterByName: function (name)
{
var match = RegExp('[?&]' + name + '=([^&]*)')
.exec(window.location.search);
return match ?
decodeURIComponent(match[1].replace(/\+/g, ' '))
: null;
},
_drawExtentFromCoords: function (xmin, ymin, xmax, ymax)
{
if ($.isArray(xmin))
{
var coords = xmin;
xmin = coords[0]; ymin = coords[1]; xmax = coords[2]; ymax = coords[3];
}
return new L.Rectangle([[ymin, xmin], [ymax, xmax]],
this.options.style);
},
_drawExtentFromGeoJSON: function (geom)
{
return new L.GeoJSON(geom, { style: this.options.style });
},
_onReady: function ()
{
var module = this;
var map;
var extentLayer;
var previous_box;
var previous_extent;
var is_exanded = false;
var should_zoom = true;
var form = $("#dataset-search");
// CKAN 2.1
if (!form.length)
{
form = $(".search-form");
}
var buttons;
// Add necessary fields to the search form if not already created
$(['ext_bbox', 'ext_prev_extent']).each(function (index, item)
{
if ($("#" + item).length === 0)
{
$('<input type="hidden" />').attr({ 'id': item, 'name': item }).appendTo(form);
}
});
// OK map time
// var crs = L.CRS.project('EPSG:25832', '+proj=utm +zone=32 +ellps=GRS80 +units=m +no_defs', new L.Transformation(0.5 / (Math.PI * L.Projection.Mercator.R_MAJOR), 0.5, -0.5 / (Math.PI * L.Projection.Mercator.R_MINOR), 0.5));
// var crs = L.Proj.CRS('EPSG:25832', '+proj=utm +zone=32 +ellps=GRS80 +units=m +no_defs', new L.Transformation(0.5 / (Math.PI * L.Projection.Mercator.R_MAJOR), 0.5, -0.5 / (Math.PI * L.Projection.Mercator.R_MINOR), 0.5));
// var crs = new L.Proj.CRS('EPSG:25832',
// '+proj=utm +zone=32 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs',
// {
// resolutions: [2000, 1100, 550, 275, 100, 50, 25, 10, 5, 2, 1, 0.5, 0.25]//,
// //origin: [0, 0]
// }),
map = ckan.commonLeafletMap(
'dataset-map-container',
this.options.map_config,
{
attributionControl: false,
drawControlTooltips: false,
// crs: crs
}
);
// Initialize the draw control
map.addControl(new L.Control.Draw({
position: 'topright',
draw: {
polyline: false,
polygon: false,
circle: false,
marker: false,
rectangle: { shapeOptions: module.options.style }
}
}));
// OK add the expander
$('a.leaflet-draw-draw-rectangle', module.el).on('click', function (e)
{
if (!is_exanded)
{
$('body').addClass('dataset-map-expanded');
if (should_zoom && !extentLayer)
{
map.zoomIn();
}
resetMap();
is_exanded = true;
}
});
// Setup the expanded buttons
buttons = $(module.template.buttons).insertBefore('#dataset-map-attribution');
// Handle the cancel expanded action
$('.cancel', buttons).on('click', function ()
{
$('body').removeClass('dataset-map-expanded');
if (extentLayer)
{
map.removeLayer(extentLayer);
}
setPreviousExtent();
setPreviousBBBox();
resetMap();
is_exanded = false;
});
// Handle the apply expanded action
$('.apply', buttons).on('click', function ()
{
if (extentLayer)
{
$('body').removeClass('dataset-map-expanded');
is_exanded = false;
resetMap();
// Eugh, hacky hack.
setTimeout(function ()
{
map.fitBounds(extentLayer.getBounds());
submitForm();
}, 200);
}
});
// When user finishes drawing the box, record it and add it to the map
map.on('draw:created', function (e)
{
if (extentLayer)
{
map.removeLayer(extentLayer);
}
extentLayer = e.layer;
$('#ext_bbox').val(extentLayer.getBounds().toBBoxString());
map.addLayer(extentLayer);
$('.apply', buttons).removeClass('disabled').addClass('btn-primary');
});
// Record the current map view so we can replicate it after submitting
map.on('moveend', function (e)
{
$('#ext_prev_extent').val(map.getBounds().toBBoxString());
});
// Ok setup the default state for the map
var previous_bbox;
setPreviousBBBox();
setPreviousExtent();
// OK, when we expand we shouldn't zoom then
map.on('zoomstart', function (e)
{
should_zoom = false;
});
// Is there an existing box from a previous search?
function setPreviousBBBox()
{
previous_bbox = module._getParameterByName('ext_bbox');
if (previous_bbox)
{
$('#ext_bbox').val(previous_bbox);
extentLayer = module._drawExtentFromCoords(previous_bbox.split(','))
map.addLayer(extentLayer);
map.fitBounds(extentLayer.getBounds());
}
}
// Is there an existing extent from a previous search?
function setPreviousExtent()
{
previous_extent = module._getParameterByName('ext_prev_extent');
if (previous_extent)
{
coords = previous_extent.split(',');
map.fitBounds([[coords[1], coords[0]], [coords[3], coords[2]]]);
} else
{
if (!previous_bbox)
{
map.fitBounds(module.options.default_extent);
}
}
}
// Reset map view
function resetMap()
{
L.Util.requestAnimFrame(map.invalidateSize, map, !1, map._container);
}
// Add the loading class and submit the form
function submitForm()
{
setTimeout(function ()
{
form.submit();
}, 800);
}
}
}
});
This diff is collapsed.
(function (factory) {
var L, proj4;
if (typeof define === 'function' && define.amd) {
// AMD
define(['leaflet', 'proj4'], factory);
} else if (typeof module === 'object' && typeof module.exports === "object") {
// Node/CommonJS
L = require('leaflet');
proj4 = require('proj4');
module.exports = factory(L, proj4);
} else {
// Browser globals
if (typeof window.L === 'undefined' || typeof window.proj4 === 'undefined')
throw 'Leaflet and proj4 must be loaded first';
factory(window.L, window.proj4);
}
}(function (L, proj4) {
L.Proj = {};
L.Proj._isProj4Obj = function(a) {
return (typeof a.inverse !== 'undefined' &&
typeof a.forward !== 'undefined');
};
L.Proj.ScaleDependantTransformation = function(scaleTransforms) {
this.scaleTransforms = scaleTransforms;
};
L.Proj.ScaleDependantTransformation.prototype.transform = function(point, scale) {
return this.scaleTransforms[scale].transform(point, scale);
};
L.Proj.ScaleDependantTransformation.prototype.untransform = function(point, scale) {
return this.scaleTransforms[scale].untransform(point, scale);
};
L.Proj.Projection = L.Class.extend({
initialize: function(a, def) {
if (L.Proj._isProj4Obj(a)) {
this._proj = a;
} else {
var code = a;
if (def) {
proj4.defs(code, def);
} else if (proj4.defs[code] === undefined) {
var urn = code.split(':');
if (urn.length > 3) {
code = urn[urn.length - 3] + ':' + urn[urn.length - 1];
}
if (proj4.defs[code] === undefined) {
throw 'No projection definition for code ' + code;
}
}
this._proj = proj4(code);
}
},
project: function (latlng) {
var point = this._proj.forward([latlng.lng, latlng.lat]);
return new L.Point(point[0], point[1]);
},
unproject: function (point, unbounded) {
var point2 = this._proj.inverse([point.x, point.y]);
return new L.LatLng(point2[1], point2[0], unbounded);
}
});
L.Proj.CRS = L.Class.extend({
includes: L.CRS,
options: {
transformation: new L.Transformation(1, 0, -1, 0)
},
initialize: function(a, b, c) {
var code, proj, def, options;
if (L.Proj._isProj4Obj(a)) {
proj = a;
code = proj.srsCode;
options = b || {};
this.projection = new L.Proj.Projection(proj);
} else {
code = a;
def = b;
options = c || {};
this.projection = new L.Proj.Projection(code, def);
}
L.Util.setOptions(this, options);
this.code = code;
this.transformation = this.options.transformation;
if (this.options.origin) {
this.transformation =
new L.Transformation(1, -this.options.origin[0],
-1, this.options.origin[1]);
}
if (this.options.scales) {
this._scales = this.options.scales;
} else if (this.options.resolutions) {
this._scales = [];
for (var i = this.options.resolutions.length - 1; i >= 0; i--) {
if (this.options.resolutions[i]) {
this._scales[i] = 1 / this.options.resolutions[i];
}
}
}
},
scale: function(zoom) {
var iZoom = Math.floor(zoom),
baseScale,
nextScale,
scaleDiff,
zDiff;
if (zoom === iZoom) {
return this._scales[zoom];
} else {
// Non-integer zoom, interpolate
baseScale = this._scales[iZoom];
nextScale = this._scales[iZoom + 1];
scaleDiff = nextScale - baseScale;
zDiff = (zoom - iZoom);
return baseScale + scaleDiff * zDiff;
}
},
getSize: function(zoom) {
var b = this.options.bounds,
s,
min,
max;
if (b) {
s = this.scale(zoom);
min = this.transformation.transform(b.min, s);
max = this.transformation.transform(b.max, s);
return L.point(Math.abs(max.x - min.x), Math.abs(max.y - min.y));
} else {
// Backwards compatibility with Leaflet < 0.7
s = 256 * Math.pow(2, zoom);
return L.point(s, s);
}
}
});
L.Proj.CRS.TMS = L.Proj.CRS.extend({
options: {
tileSize: 256
},
initialize: function(a, b, c, d) {
var code,
def,
proj,
projectedBounds,
options;
if (L.Proj._isProj4Obj(a)) {
proj = a;
projectedBounds = b;
options = c || {};
options.origin = [projectedBounds[0], projectedBounds[3]];
L.Proj.CRS.prototype.initialize.call(this, proj, options);
} else {
code = a;
def = b;
projectedBounds = c;
options = d || {};
options.origin = [projectedBounds[0], projectedBounds[3]];
L.Proj.CRS.prototype.initialize.call(this, code, def, options);
}
this.projectedBounds = projectedBounds;
this._sizes = this._calculateSizes();
},
_calculateSizes: function() {
var sizes = [],
crsBounds = this.projectedBounds,
projectedTileSize,
i,
x,
y;
for (i = this._scales.length - 1; i >= 0; i--) {
if (this._scales[i]) {
projectedTileSize = this.options.tileSize / this._scales[i];
// to prevent very small rounding errors from causing us to round up,
// cut any decimals after 3rd before rounding up.
x = Math.ceil(parseFloat((crsBounds[2] - crsBounds[0]) / projectedTileSize).toPrecision(3)) *
projectedTileSize * this._scales[i];
y = Math.ceil(parseFloat((crsBounds[3] - crsBounds[1]) / projectedTileSize).toPrecision(3)) *
projectedTileSize * this._scales[i];
sizes[i] = L.point(x, y);
}
}
return sizes;
},
getSize: function(zoom) {
return this._sizes[zoom];
}
});
L.Proj.TileLayer = {};
// Note: deprecated and not necessary since 0.7, will be removed
L.Proj.TileLayer.TMS = L.TileLayer.extend({
options: {
continuousWorld: true
},
initialize: function(urlTemplate, crs, options) {
var boundsMatchesGrid = true,
scaleTransforms,
upperY,
crsBounds,
i;
if (!(crs instanceof L.Proj.CRS.TMS)) {
throw 'CRS is not L.Proj.CRS.TMS.';
}
L.TileLayer.prototype.initialize.call(this, urlTemplate, options);
// Enabling tms will cause Leaflet to also try to do TMS, which will
// break (at least prior to 0.7.0). Actively disable it, to prevent
// well-meaning users from shooting themselves in the foot.
this.options.tms = false;
this.crs = crs;
crsBounds = this.crs.projectedBounds;
// Verify grid alignment
for (i = this.options.minZoom; i < this.options.maxZoom && boundsMatchesGrid; i++) {
var gridHeight = (crsBounds[3] - crsBounds[1]) /
this._projectedTileSize(i);
boundsMatchesGrid = Math.abs(gridHeight - Math.round(gridHeight)) > 1e-3;
}
if (!boundsMatchesGrid) {
scaleTransforms = {};
for (i = this.options.minZoom; i < this.options.maxZoom; i++) {
upperY = crsBounds[1] + Math.ceil((crsBounds[3] - crsBounds[1]) /
this._projectedTileSize(i)) * this._projectedTileSize(i);
scaleTransforms[this.crs.scale(i)] = new L.Transformation(1, -crsBounds[0], -1, upperY);
}
this.crs = new L.Proj.CRS.TMS(this.crs.projection._proj, crsBounds, this.crs.options);
this.crs.transformation = new L.Proj.ScaleDependantTransformation(scaleTransforms);
}
},
getTileUrl: function(tilePoint) {
var zoom = this._map.getZoom(),
gridHeight = Math.ceil(
(this.crs.projectedBounds[3] - this.crs.projectedBounds[1]) /
this._projectedTileSize(zoom));
return L.Util.template(this._url, L.Util.extend({
s: this._getSubdomain(tilePoint),
z: this._getZoomForUrl(),
x: tilePoint.x,
y: gridHeight - tilePoint.y - 1
}, this.options));
},
_projectedTileSize: function(zoom) {
return (this.options.tileSize / this.crs.scale(zoom));
}
});
L.Proj.GeoJSON = L.GeoJSON.extend({
initialize: function(geojson, options) {
this._callLevel = 0;
L.GeoJSON.prototype.initialize.call(this, null, options);
if (geojson) {
this.addData(geojson);
}
},
addData: function(geojson) {
var crs;
if (geojson) {
if (geojson.crs && geojson.crs.type === 'name') {
crs = new L.Proj.CRS(geojson.crs.properties.name);
} else if (geojson.crs && geojson.crs.type) {
crs = new L.Proj.CRS(geojson.crs.type + ':' + geojson.crs.properties.code);
}
if (crs !== undefined) {
this.options.coordsToLatLng = function(coords) {
var point = L.point(coords[0], coords[1]);
return crs.projection.unproject(point);
};
}
}
// Base class' addData might call us recursively, but
// CRS shouldn't be cleared in that case, since CRS applies
// to the whole GeoJSON, inluding sub-features.
this._callLevel++;
try {
L.GeoJSON.prototype.addData.call(this, geojson);
} finally {
this._callLevel--;
if (this._callLevel === 0) {
delete this.options.coordsToLatLng;
}
}
}
});
L.Proj.geoJson = function(geojson, options) {
return new L.Proj.GeoJSON(geojson, options);
};
L.Proj.ImageOverlay = L.ImageOverlay.extend({
initialize: function(url, bounds, options) {
L.ImageOverlay.prototype.initialize.call(this, url, null, options);
this._projBounds = bounds;
},
/* Danger ahead: overriding internal methods in Leaflet.
I've decided to do this rather than making a copy of L.ImageOverlay
and making very tiny modifications to it. Future will tell if this
was wise or not. */
_animateZoom: function (e) {
var northwest = L.point(this._projBounds.min.x, this._projBounds.max.y),
southeast = L.point(this._projBounds.max.x, this._projBounds.min.y),
topLeft = this._projectedToNewLayerPoint(northwest, e.zoom, e.center),
size = this._projectedToNewLayerPoint(southeast, e.zoom, e.center).subtract(topLeft),
origin = topLeft.add(size._multiplyBy((1 - 1 / e.scale) / 2));
this._image.style[L.DomUtil.TRANSFORM] =
L.DomUtil.getTranslateString(origin) + ' scale(' + this._map.getZoomScale(e.zoom) + ') ';
},
_reset: function() {
var zoom = this._map.getZoom(),
pixelOrigin = this._map.getPixelOrigin(),
bounds = L.bounds(this._transform(this._projBounds.min, zoom)._subtract(pixelOrigin),
this._transform(this._projBounds.max, zoom)._subtract(pixelOrigin)),
size = bounds.getSize(),
image = this._image;
L.DomUtil.setPosition(image, bounds.min);
image.style.width = size.x + 'px';
image.style.height = size.y + 'px';
},
_projectedToNewLayerPoint: function (point, newZoom, newCenter) {
var topLeft = this._map._getNewTopLeftPoint(newCenter, newZoom).add(this._map._getMapPanePos());
return this._transform(point, newZoom)._subtract(topLeft);
},
_transform: function(p, zoom) {
var crs = this._map.options.crs,
transformation = crs.transformation,
scale = crs.scale(zoom);
return transformation.transform(p, scale);
}
});
L.Proj.imageOverlay = function(url, bounds, options) {
return new L.Proj.ImageOverlay(url, bounds, options);
};
if (typeof L.CRS !== 'undefined') {
// This is left here for backwards compatibility
L.CRS.proj4js = (function () {
return function (code, def, transformation, options) {
options = options || {};
if (transformation) {
options.transformation = transformation;
}
return new L.Proj.CRS(code, def, options);
};
}());
}
return L.Proj;
}));
{% ckan_extends %} {% ckan_extends %}
{% block styles %} {% block styles %}
{{ super() }} {{ super() }}
{% resource 'odsh/odsh.js' %} {% resource 'odsh/odsh.js' %}
......
<section id="dataset-map" class="module-narrow module-shallow"> <section id="dataset-map" class="module-narrow module-shallow" data-module="odsh-map">
<h2 class="module-heading"> <h2 class="module-heading">
{{_('map')}}: {{_('map')}}:
</h2> </h2>
{% set map_config = h.get_common_map_config() %} {% set map_config = h.get_common_map_config() %}
<div class="dataset-map" data-module="spatial-query" data-default_extent="{{ default_extent }}" data-module-map_config="{{ h.dump_json(map_config) }}"> <div class="dataset-map" data-module="spatial-query" data-default_extent="{{ default_extent }}" data-module-map_config="{{ h.dump_json(map_config) }}" data-template='sdf'>
<div id="dataset-map-container"></div> <div id="dataset-map-container"></div>
</div> </div>
<div id="dataset-map-attribution"> <div id="dataset-map-attribution">
...@@ -13,3 +13,4 @@ ...@@ -13,3 +13,4 @@
</section> </section>
{% resource 'ckanext-spatial/spatial_query' %} {% resource 'ckanext-spatial/spatial_query' %}
{% resource 'odsh/odsh_map.js' %}
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment