CruisersWiki:Ol3chartlet.js
From CruisersWiki
(Difference between revisions)
Line 12: | Line 12: | ||
return; | return; | ||
} | } | ||
- | |||
- | |||
- | |||
var nx = { | var nx = { | ||
Line 115: | Line 112: | ||
}; | }; | ||
- | function ol3Chartlet() { | + | esri.new_source = function (src_id) { |
+ | return new ol.source.TileArcGISRest({ | ||
+ | url: esri.uris[src_id], | ||
+ | params: { | ||
+ | FORMAT: 'JPG', | ||
+ | TRANSPARENT: false, | ||
+ | }, | ||
+ | attributions: [ | ||
+ | new ol.Attribution({ | ||
+ | html: 'Tiles by ESRI <a href="' + esri.uris[src_id] + '">Acknowledgements</a>' | ||
+ | }) | ||
+ | ] | ||
+ | }) | ||
+ | }; | ||
+ | |||
+ | function ol3Chartlet(chartlet_div) { | ||
console.log('ol3Chartlet'); | console.log('ol3Chartlet'); | ||
- | + | ||
- | + | this.params = parseParams(standalone && location.hash ? location.hash.slice(1) : $(chartlet_div).text()); | |
var iconFeature = new ol.Feature({ | var iconFeature = new ol.Feature({ | ||
Line 175: | Line 187: | ||
title: 'ESRI World Imagery', | title: 'ESRI World Imagery', | ||
type: 'base', | type: 'base', | ||
- | source | + | source: esri.new_source('satellite') |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
}); | }); | ||
Line 194: | Line 195: | ||
}); | }); | ||
- | + | this.map = new ol.Map({ | |
- | target: | + | target: chartlet_div, |
layers: [ | layers: [ | ||
new ol.layer.Group({ | new ol.layer.Group({ | ||
Line 201: | Line 202: | ||
layers: [ | layers: [ | ||
new ol.layer.Tile({ | new ol.layer.Tile({ | ||
- | title: ' | + | title: 'OpenStreetMap', |
type: 'base', | type: 'base', | ||
source: new ol.source.OSM() | source: new ol.source.OSM() | ||
Line 251: | Line 252: | ||
if (standalone) { | if (standalone) { | ||
- | initStandalone ( | + | this.initStandalone(); |
} | } | ||
}; | }; | ||
- | function | + | // add layer to a layer group |
+ | ol3Chartlet.prototype.addNonBaseLayer = function (new_layer) { | ||
+ | this.map.getLayers().forEach( | ||
+ | function(layer) { | ||
+ | if (layer.get('title') === 'Layers') { | ||
+ | layer.getLayers().push(new_layer); | ||
+ | } | ||
+ | } | ||
+ | ); | ||
+ | } | ||
+ | |||
+ | ol3Chartlet.prototype.initStandalone = function () { | ||
+ | |||
+ | var standalone = !! $('#ol3-chartlet-standalone')[0]; | ||
+ | if (!standalone) | ||
+ | return; | ||
+ | |||
+ | this.trackHash() | ||
+ | this.addCoordinateGrid(); | ||
+ | |||
+ | var page = this.params.page; | ||
+ | var _this = this; | ||
+ | |||
+ | if (page) { | ||
+ | loadWikiScript('MediaWiki:GetKml.js', function () { | ||
+ | getKml( | ||
+ | { | ||
+ | page: page, | ||
+ | decorated: true | ||
+ | }, | ||
+ | _this.addPOIs.bind(_this) | ||
+ | ); | ||
+ | }); | ||
+ | |||
+ | loadWikiCss('MediaWiki:Ol3-popup.css'); | ||
+ | loadWikiScript("MediaWiki:Ol3-popup.js", _this.initPopups.bind(_this)); | ||
+ | } | ||
+ | }; | ||
+ | ol3Chartlet.prototype.trackHash = function() { | ||
var doNotTrackHash = false; | var doNotTrackHash = false; | ||
var setHashTimeoutID = null; | var setHashTimeoutID = null; | ||
- | var view = map.getView(); | + | var view = this.map.getView(); |
+ | var params = this.params; | ||
var onChangeCenterZoom = function () { | var onChangeCenterZoom = function () { | ||
Line 277: | Line 317: | ||
//console.log(center, zoom); | //console.log(center, zoom); | ||
- | location.hash= 'lat=' + round(params.lat) + '|lon=' + round(params.lon) + '|zoom=' + params.zoom | + | location.hash = 'lat=' + round(params.lat) + '|lon=' + round(params.lon) |
+ | + '|zoom=' + params.zoom | ||
+ (params.layer ? '|layer=' + params.layer : '') | + (params.layer ? '|layer=' + params.layer : '') | ||
+ (params.page ? '|page=' + params.page : ''); | + (params.page ? '|page=' + params.page : ''); | ||
Line 291: | Line 332: | ||
view.on('change:resolution', onChangeCenterZoom); | view.on('change:resolution', onChangeCenterZoom); | ||
- | + | $(window).hashchange( function () { | |
if (!location.hash || doNotTrackHash) { | if (!location.hash || doNotTrackHash) { | ||
doNotTrackHash = false; | doNotTrackHash = false; | ||
Line 302: | Line 343: | ||
view.setZoom(params.zoom); | view.setZoom(params.zoom); | ||
} | } | ||
- | }; | + | }); |
+ | }; | ||
- | + | // add coordinate grid layer | |
+ | ol3Chartlet.prototype.addCoordinateGrid = function () { // after http://map.openseamap.org/javascript/grid_wgs.js | ||
+ | var gridSteps = [ | ||
+ | // in seconds | ||
+ | 3 / 3600, // 0.05' | ||
+ | 6 / 3600, 12 / 3600, 30 / 3600, // 0.1' 0.2' 0.5' | ||
+ | // in minutes | ||
+ | 1 / 60, 2 / 60, 3 / 60, 5 / 60, 10 / 60, 20 / 60, 30 / 60, | ||
+ | // in degrees | ||
+ | 1, 2, 3, 4, 6, 10, 15, 30, 45]; | ||
- | + | var gridPixelStep = 100; | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | // | + | // Find matching grid step |
- | function | + | var getGridStep = function (distance) { |
- | + | for (var i=0; i<gridSteps.length; i++) { | |
- | + | if (distance < gridSteps[i]) | |
- | + | return gridSteps[i]; | |
- | + | } | |
- | + | return gridSteps[i-1]; | |
- | + | }; | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | } | + | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | // Format label | |
- | + | var zeroPad = function (x, int_places, dec, zero_pad) { | |
- | + | var pad = ' ' // spaces there | |
- | + | var sign = '' | |
- | + | var places = dec > 0 ? int_places+dec+1 : int_places | |
+ | if (zero_pad == null || zero_pad) { | ||
+ | var pad = '00000000000000000000' | ||
+ | if (x < 0) { | ||
+ | x = Math.abs(x) | ||
+ | places-- | ||
+ | sign = '-' | ||
} | } | ||
- | + | } | |
- | + | return sign + (pad + x.toFixed(dec)).slice(-places) | |
+ | }; | ||
- | + | var formatDegrees = function (deg, format, isLon) { | |
- | + | var adeg = Math.abs(deg); | |
- | + | return '' | |
- | + | + zeroPad(Math.floor(adeg), isLon ? 3 : 2) + "°" | |
- | + | + (format == 'd' ? '' : zeroPad((adeg * 60) % 60, 2) + "'") | |
- | + | + (isLon ? (deg < 0 ? 'W' : 'E') : (deg < 0 ? 'S' : 'N')); | |
- | + | }; | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | var view = this.map.getView(); | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | // layer loader | |
- | + | var loader = function(extent, resolution, projection) { | |
- | + | /** | |
- | + | * @param {ol.Extent} extent Extent. | |
- | + | * @param {number} resolution Resolution. | |
- | + | * @param {ol.proj.Projection} projection Projection. | |
- | + | * @this {ol.source.Vector|ol.VectorTile} | |
- | + | */ | |
- | + | var view_proj = view.getProjection(); | |
- | + | var geo_proj = 'EPSG:4326'; | |
- | + | var lonlat_extent = ol.proj.transformExtent(extent, view_proj, geo_proj); | |
- | + | // clip extent to max values | |
- | + | var x1 = Math.max (-180, lonlat_extent[0]); | |
- | + | var x2 = Math.min ( 180, lonlat_extent[2]); | |
- | + | var y1 = Math.max ( -85, lonlat_extent[1]); | |
- | + | var y2 = Math.min ( 85, lonlat_extent[3]); | |
- | + | // grid step | |
- | + | var step = getGridStep((lonlat_extent[3] - lonlat_extent[1]) / map.getSize()[1] * gridPixelStep); | |
- | + | var labelFormat = step % 1 ? 'dm' : 'd'; // round degrees number | |
- | + | var features = []; | |
- | + | // line style | |
- | + | var strokeStyle = new ol.style.Stroke({ | |
- | + | color: [102, 102, 102, 255 * 0.8], // "#666666", | |
- | + | width: 1, | |
- | + | //~ strokeOpacity: 0.8 | |
- | + | }); | |
- | + | // Vertical lines | |
- | + | for (var x = Math.ceil(x1 / step) * step + (x1 == -180 ? step : 0); x <= x2; x += step) { | |
- | + | var l = new ol.geom.LineString([ | |
- | + | ol.proj.transform([x, y1], geo_proj, view_proj), | |
- | + | ol.proj.transform([x, y2], geo_proj, view_proj) | |
- | + | ]); | |
- | + | var f = new ol.Feature(l); | |
- | + | f.setStyle(new ol.style.Style({ | |
- | + | stroke: strokeStyle, | |
- | + | text: new ol.style.Text({ | |
- | + | text: formatDegrees (x, labelFormat, true), | |
- | + | textAlign: 'end', | |
- | + | textBaseline: 'top', | |
- | + | offsetX: 0, | |
- | + | offsetY: - map.getSize()[1] / 2, | |
- | + | rotation: - Math.PI / 2, | |
- | + | scale: 1.5, | |
- | + | // labelAlign: "lt", | |
- | + | }), | |
- | + | })); | |
- | + | f.set('auxiliary', true); | |
- | + | features.push (f); | |
- | + | } | |
- | + | // Horizontal lines | |
- | + | for (var y = Math.ceil(y1 / step) * step; y <= y2; y += step) { | |
- | + | var l = new ol.geom.LineString([ | |
- | + | ol.proj.transform([x1, y], geo_proj, view_proj), | |
- | + | ol.proj.transform([x2, y], geo_proj, view_proj) | |
- | + | ]); | |
- | + | var f = new ol.Feature(l); | |
- | + | f.setStyle(new ol.style.Style({ | |
- | + | stroke: strokeStyle, | |
- | + | text: new ol.style.Text({ | |
- | + | text: formatDegrees (y, labelFormat, false), | |
- | + | textAlign: 'end', | |
- | + | textBaseline: 'top', | |
- | + | offsetX: map.getSize()[0] / 2, | |
- | + | offsetY: 0, | |
- | + | rotation: 0, | |
- | + | scale: 1.5, | |
- | + | //~ labelAlign: "lt", | |
- | + | }), | |
- | + | })); | |
- | + | f.set('auxiliary', true); | |
- | + | features.push (f); | |
- | + | } | |
- | + | this.addFeatures(features); | |
- | + | }; | |
- | + | var coord_grid = new ol.layer.Vector({ | |
- | + | title: 'Coordinate grid', | |
- | + | visible: false, | |
- | + | source: new ol.source.Vector({ | |
- | + | loader: loader, | |
- | + | strategy: ol.loadingstrategy.bbox | |
- | + | }) | |
- | + | }); | |
- | + | // add to the proper layer group | |
- | + | this.addNonBaseLayer(coord_grid); | |
- | + | var onChangeCenterZoom = function () { | |
- | + | coord_grid.getSource().clear(); | |
- | + | ||
- | + | ||
- | + | ||
} | } | ||
+ | view.on('change:center', onChangeCenterZoom); | ||
+ | view.on('change:resolution', onChangeCenterZoom); | ||
+ | }; | ||
- | + | // load kml | |
+ | ol3Chartlet.prototype.addPOIs = function(kml) { | ||
+ | if (!kml) | ||
+ | return; | ||
+ | // kml_uri='http://openlayers.org/en/v3.13.1/examples/data/kml/2012-02-10.kml'; | ||
+ | var format = new ol.format.KML({ | ||
+ | showPointNames: false, | ||
+ | }); | ||
+ | var loader = function(extent, resolution, projection) { | ||
+ | /** | ||
+ | * @param {ol.Extent} extent Extent. | ||
+ | * @param {number} resolution Resolution. | ||
+ | * @param {ol.proj.Projection} projection Projection. | ||
+ | * @this {ol.source.Vector|ol.VectorTile} | ||
+ | */ | ||
+ | var xml_tree = ol.xml.parse(kml); | ||
- | + | var features = format.readFeatures( | |
- | var | + | xml_tree, |
- | + | {featureProjection: projection} | |
+ | ); | ||
- | + | this.addFeatures(features); | |
- | + | }; | |
- | + | var kml_layer = new ol.layer.Vector({ | |
- | + | title: 'POI', | |
- | + | visible:true, | |
- | + | source: new ol.source.Vector({ | |
- | + | loader: loader, | |
- | + | }) | |
- | + | }); | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | // add to the proper layer group | |
- | + | this.addNonBaseLayer(kml_layer); | |
- | + | }; | |
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ||
- | + | ol3Chartlet.prototype.initPopups = function () { | |
- | + | var map = this.map; | |
- | + | ||
- | + | var popup = new ol.Overlay.Popup(); | |
- | + | map.addOverlay(popup); | |
- | + | ||
- | + | // display popup on click | |
- | + | map.on('click', function(evt) { | |
+ | var feature = map.forEachFeatureAtPixel(evt.pixel, | ||
+ | function(feature) { | ||
+ | return feature; | ||
+ | }); | ||
+ | if (feature && ! feature.get('auxiliary')) { | ||
+ | popup.show(evt.coordinate, | ||
+ | '<div class="cw-popup-name">' + feature.get("name") + '</div>' + | ||
+ | '<div class="cw-popup-category">' + feature.get("styleUrl").split('#')[1] + '</div>' + | ||
+ | '<div class="cw-popup-content">' + feature.get("description") + '<div>' | ||
); | ); | ||
- | }); | + | } else { |
+ | popup.hide(); | ||
+ | } | ||
+ | }); | ||
- | + | // change mouse cursor when over marker | |
- | + | map.on('pointermove', function(e) { | |
- | } | + | //~ if (e.dragging) { |
- | } | + | //~ $(element).popover('destroy'); |
+ | //~ return; | ||
+ | //~ } | ||
+ | var pixel = map.getEventPixel(e.originalEvent); | ||
+ | var hit = map.hasFeatureAtPixel(pixel); | ||
+ | map.getTarget().style.cursor = hit ? 'pointer' : ''; | ||
+ | }); | ||
+ | }; | ||
function dmsh2deg(dmsh) { | function dmsh2deg(dmsh) { | ||
Line 625: | Line 637: | ||
}; | }; | ||
- | $chartlets.each(ol3Chartlet); | + | $chartlets.each( function () { |
+ | new ol3Chartlet(this); | ||
+ | }); | ||
}); | }); | ||
}); | }); |
Revision as of 10:33, 29 February 2016
/*
ol3Chartlet.js
Copyright (c) 2016 Vadim Shlyakhov Licensed MIT
- /
addOnloadHook(function() {
var $chartlets = $('.ol3-chartlet'); if ($chartlets.length === 0) { return; }
var nx = { navKey: 'Navionics_webapi_00572', domain: 'www.cruiserswiki.org', navToken: null, BASE_TILE_SERVER: '//backend.navionics.io', TILE_SUFFIX: '/tile/{z}/{x}/{y}', KEY_REQ_SUFFIX: '/tile/get_key', MAX_RESOLUTION: 20480, MIN_RESOLUTION: 0.625, disclaimer_msg: '© Navionics <a href="http://www.navionics.com/en/acknowledgements" target="_new" class="navionics-acknowledgements">Acknowledgements</a> | Not to be used for navigation', };
nx.init = function(callback) { // set location for Navionics images //~ $('body').attr('data-root', 'http://webapiv2.navionics.com/dist/webapi/images');
if ( nx.navToken ) { callback(); } else { // requestNavToken var targetUrl = nx.BASE_TILE_SERVER + nx.KEY_REQ_SUFFIX; $.ajax({ url: targetUrl + '/' + nx.navKey + '/' + nx.domain, async: !!callback, crossDomain: true, dataType: 'text', cache: false, error: function() { return console.log(arguments); }, success: function(data, textStatus, jqXHR) { nx.navToken = data; callback(); } }); } };
nx.formatTileUrl = function (options) { // sonar, overlay, depthUnit, safeDepth, showUGC options = options || {}; sType = options.sonar ? 1 : 0; sAlpha = options.overlay ? 'TRUE' : 'FALSE'; sUgc = options.showUGC ? 'TRUE' : 'FALSE'; sDepthUnit = { 'm': 1, 'metre': 1, 'meter': 1, 'ft': 2, 'feet': 2, 'fathom': 3, } [options.depthUnit] || 1; // sDepthLevel = (options.safeDepth || 10).toFixed(2); sDepthLevel = (options.safeDepth || 20).toFixed(0); params = $.param({ LAYERS: 'config_' + sDepthUnit + '_' + sDepthLevel + '_' + sType, TRANSPARENT: sAlpha, UGC: sUgc, navtoken: nx.navToken }); return nx.BASE_TILE_SERVER + nx.TILE_SUFFIX + '?' + params; };
nx.getTileUrl = function (options, callback) { // sonar, overlay, depthUnit, safeDepth, showUGC nx.init(function () { callback(nx.formatTileUrl(options)) }); };
nx.new_source = function (options) { var source = new ol.source.XYZ({ crossOrigin: 'anonymous', attributions: [ new ol.Attribution({ html: nx.disclaimer_msg }) ], maxResolution: nx.MAX_RESOLUTION, minResolution: nx.MIN_RESOLUTION });
nx.getTileUrl( options, function (url) { source.setUrl(url); } );
return source; };
var esri = {}; esri.uris = { 'satellite': "http://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer", 'topo': "http://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer", 'light-gray': "http://services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Reference/MapServer", 'dark-gray': "http://services.arcgisonline.com/arcgis/rest/services/Canvas/World_Dark_Gray_Base/MapServer", 'streets': "http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer", 'hybrid': "http://services.arcgisonline.com/ArcGIS/rest/services/Reference/World_Boundaries_and_Places/MapServer", 'oceans': "http://server.arcgisonline.com/arcgis/rest/services/Ocean/World_Ocean_Reference/MapServer", 'national-geographic': "http://server.arcgisonline.com/ArcGIS/rest/services/NatGeo_World_Map/MapServer", };
esri.new_source = function (src_id) { return new ol.source.TileArcGISRest({ url: esri.uris[src_id], params: { FORMAT: 'JPG', TRANSPARENT: false, }, attributions: [ new ol.Attribution({ html: 'Tiles by ESRI <a href="' + esri.uris[src_id] + '">Acknowledgements</a>' }) ] }) };
function ol3Chartlet(chartlet_div) { console.log('ol3Chartlet');
this.params = parseParams(standalone && location.hash ? location.hash.slice(1) : $(chartlet_div).text());
var iconFeature = new ol.Feature({ geometry: new ol.geom.Point(ol.proj.transform([params.lon, params.lat], 'EPSG:4326', 'EPSG:3857')), name: 'Test marker', });
iconFeature.setStyle( new ol.style.Style({ image: new ol.style.Icon({ anchor: [0, 1], anchorXUnits: 'fraction', anchorYUnits: 'fraction', // anchorYUnits: 'pixels', opacity: 1, src: '/images/e/e7/Flag_icon.png' }) }) );
var iconLayer = new ol.layer.Vector({ title: 'Icon', source: new ol.source.Vector({ features: [iconFeature] }) });
var openseamap = new ol.layer.Tile({ title: 'OpenSeaMap', visible: false, source: new ol.source.XYZ({ url: 'http://t1.openseamap.org/seamark/{z}/{x}/{y}.png', crossOrigin: null, attributions: [ new ol.Attribution({ html: 'Tiles by <a href="http://www.openseamap.org">OpenSeaMap</a>' }) ], }) });
var nx_layer = new ol.layer.Tile({ title: 'Navionics', type: 'base', source: nx.new_source() });
var nx_layer_ovl = new ol.layer.Tile({ title: 'Navionics', // type: 'base', // visible: false, source: nx.new_source({overlay:true}) });
var esri_layer = new ol.layer.Tile({ title: 'ESRI World Imagery', type: 'base', source: esri.new_source('satellite') });
var view = new ol.View({ center: ol.proj.transform([params.lon, params.lat], 'EPSG:4326', 'EPSG:3857'), zoom: params.zoom });
this.map = new ol.Map({ target: chartlet_div, layers: [ new ol.layer.Group({ 'title': 'Base', layers: [ new ol.layer.Tile({ title: 'OpenStreetMap', type: 'base', source: new ol.source.OSM() }), esri_layer, new ol.layer.Tile({ title: 'Water color', type: 'base', source: new ol.source.Stamen({ layer: 'watercolor' }) }), //~ new ol.layer.Vector({ //~ title: 'Plain background', //~ type: 'base', //~ source: new ol.source.Vector({ //~ }) //~ }), ] }), new ol.layer.Group({ title: 'Layers', layers: [ openseamap, nx_layer_ovl, // iconLayer, ] }) ], view: view, controls: ol.control.defaults({ attributionOptions: /** @type {olx.control.AttributionOptions} */ ({ collapsible: false }) }) });
map.addControl(new ol.control.ScaleLine({ units: 'nautical' }));
loadWikiCss('MediaWiki:Ol3-layerswitcher.css'); loadWikiScript("MediaWiki:Ol3-layerswitcher.js", function () { var layerSwitcher = new ol.control.LayerSwitcher({ // tipLabel: 'Légende' // Optional label for button }); map.addControl(layerSwitcher); });
if (standalone) { this.initStandalone(); } };
// add layer to a layer group ol3Chartlet.prototype.addNonBaseLayer = function (new_layer) { this.map.getLayers().forEach( function(layer) { if (layer.get('title') === 'Layers') { layer.getLayers().push(new_layer); } } ); }
ol3Chartlet.prototype.initStandalone = function () {
var standalone = !! $('#ol3-chartlet-standalone')[0]; if (!standalone) return;
this.trackHash() this.addCoordinateGrid();
var page = this.params.page; var _this = this;
if (page) { loadWikiScript('MediaWiki:GetKml.js', function () { getKml( { page: page, decorated: true }, _this.addPOIs.bind(_this) ); });
loadWikiCss('MediaWiki:Ol3-popup.css'); loadWikiScript("MediaWiki:Ol3-popup.js", _this.initPopups.bind(_this)); } };
ol3Chartlet.prototype.trackHash = function() { var doNotTrackHash = false; var setHashTimeoutID = null;
var view = this.map.getView(); var params = this.params;
var onChangeCenterZoom = function () { var setHashDelay = 1000;
var setHash = function () { var centre = view.getCenter(); var lonlat = ol.proj.transform(centre, view.getProjection(), 'EPSG:4326');
doNotTrackHash = true; setHashTimeoutID = null;
params.lon = lonlat[0]; params.lat = lonlat[1]; params.zoom = view.getZoom(); //console.log(center, zoom);
location.hash = 'lat=' + round(params.lat) + '|lon=' + round(params.lon) + '|zoom=' + params.zoom + (params.layer ? '|layer=' + params.layer : ) + (params.page ? '|page=' + params.page : ); };
if (setHashTimeoutID) { window.clearTimeout(setHashTimeoutID); } setHashTimeoutID = window.setTimeout(setHash, setHashDelay); };
view.on('change:center', onChangeCenterZoom); view.on('change:resolution', onChangeCenterZoom);
$(window).hashchange( function () { if (!location.hash || doNotTrackHash) { doNotTrackHash = false; return; } params = parseParams(location.hash.slice(1)); if (params.lat != null && params.lon != null) { var centre = [params.lon, params.lat]; view.setCenter(ol.proj.transform(centre, 'EPSG:4326', view.getProjection())) view.setZoom(params.zoom); } }); };
// add coordinate grid layer ol3Chartlet.prototype.addCoordinateGrid = function () { // after http://map.openseamap.org/javascript/grid_wgs.js var gridSteps = [ // in seconds 3 / 3600, // 0.05' 6 / 3600, 12 / 3600, 30 / 3600, // 0.1' 0.2' 0.5' // in minutes 1 / 60, 2 / 60, 3 / 60, 5 / 60, 10 / 60, 20 / 60, 30 / 60, // in degrees 1, 2, 3, 4, 6, 10, 15, 30, 45];
var gridPixelStep = 100;
// Find matching grid step var getGridStep = function (distance) { for (var i=0; i<gridSteps.length; i++) { if (distance < gridSteps[i]) return gridSteps[i]; } return gridSteps[i-1]; };
// Format label var zeroPad = function (x, int_places, dec, zero_pad) { var pad = ' ' // spaces there var sign = var places = dec > 0 ? int_places+dec+1 : int_places if (zero_pad == null || zero_pad) { var pad = '00000000000000000000' if (x < 0) { x = Math.abs(x) places-- sign = '-' } } return sign + (pad + x.toFixed(dec)).slice(-places) };
var formatDegrees = function (deg, format, isLon) { var adeg = Math.abs(deg); return + zeroPad(Math.floor(adeg), isLon ? 3 : 2) + "°" + (format == 'd' ? : zeroPad((adeg * 60) % 60, 2) + "'") + (isLon ? (deg < 0 ? 'W' : 'E') : (deg < 0 ? 'S' : 'N')); };
var view = this.map.getView();
// layer loader var loader = function(extent, resolution, projection) { /** * @param {ol.Extent} extent Extent. * @param {number} resolution Resolution. * @param {ol.proj.Projection} projection Projection. * @this {ol.source.Vector|ol.VectorTile} */ var view_proj = view.getProjection(); var geo_proj = 'EPSG:4326';
var lonlat_extent = ol.proj.transformExtent(extent, view_proj, geo_proj);
// clip extent to max values var x1 = Math.max (-180, lonlat_extent[0]); var x2 = Math.min ( 180, lonlat_extent[2]); var y1 = Math.max ( -85, lonlat_extent[1]); var y2 = Math.min ( 85, lonlat_extent[3]);
// grid step var step = getGridStep((lonlat_extent[3] - lonlat_extent[1]) / map.getSize()[1] * gridPixelStep);
var labelFormat = step % 1 ? 'dm' : 'd'; // round degrees number
var features = [];
// line style var strokeStyle = new ol.style.Stroke({ color: [102, 102, 102, 255 * 0.8], // "#666666", width: 1, //~ strokeOpacity: 0.8 });
// Vertical lines for (var x = Math.ceil(x1 / step) * step + (x1 == -180 ? step : 0); x <= x2; x += step) { var l = new ol.geom.LineString([ ol.proj.transform([x, y1], geo_proj, view_proj), ol.proj.transform([x, y2], geo_proj, view_proj) ]); var f = new ol.Feature(l); f.setStyle(new ol.style.Style({ stroke: strokeStyle, text: new ol.style.Text({ text: formatDegrees (x, labelFormat, true), textAlign: 'end', textBaseline: 'top', offsetX: 0, offsetY: - map.getSize()[1] / 2, rotation: - Math.PI / 2, scale: 1.5, // labelAlign: "lt", }), })); f.set('auxiliary', true); features.push (f); }
// Horizontal lines for (var y = Math.ceil(y1 / step) * step; y <= y2; y += step) { var l = new ol.geom.LineString([ ol.proj.transform([x1, y], geo_proj, view_proj), ol.proj.transform([x2, y], geo_proj, view_proj) ]); var f = new ol.Feature(l); f.setStyle(new ol.style.Style({ stroke: strokeStyle, text: new ol.style.Text({ text: formatDegrees (y, labelFormat, false), textAlign: 'end', textBaseline: 'top', offsetX: map.getSize()[0] / 2, offsetY: 0, rotation: 0, scale: 1.5, //~ labelAlign: "lt", }), })); f.set('auxiliary', true); features.push (f); }
this.addFeatures(features); };
var coord_grid = new ol.layer.Vector({ title: 'Coordinate grid', visible: false, source: new ol.source.Vector({ loader: loader, strategy: ol.loadingstrategy.bbox }) });
// add to the proper layer group this.addNonBaseLayer(coord_grid);
var onChangeCenterZoom = function () { coord_grid.getSource().clear(); } view.on('change:center', onChangeCenterZoom); view.on('change:resolution', onChangeCenterZoom); };
// load kml ol3Chartlet.prototype.addPOIs = function(kml) { if (!kml) return; // kml_uri='http://openlayers.org/en/v3.13.1/examples/data/kml/2012-02-10.kml'; var format = new ol.format.KML({ showPointNames: false, }); var loader = function(extent, resolution, projection) { /** * @param {ol.Extent} extent Extent. * @param {number} resolution Resolution. * @param {ol.proj.Projection} projection Projection. * @this {ol.source.Vector|ol.VectorTile} */ var xml_tree = ol.xml.parse(kml);
var features = format.readFeatures( xml_tree, {featureProjection: projection} );
this.addFeatures(features); }; var kml_layer = new ol.layer.Vector({ title: 'POI', visible:true, source: new ol.source.Vector({ loader: loader, }) });
// add to the proper layer group this.addNonBaseLayer(kml_layer); };
ol3Chartlet.prototype.initPopups = function () { var map = this.map;
var popup = new ol.Overlay.Popup(); map.addOverlay(popup);
// display popup on click map.on('click', function(evt) { var feature = map.forEachFeatureAtPixel(evt.pixel, function(feature) { return feature; }); if (feature && ! feature.get('auxiliary')) { popup.show(evt.coordinate,'
' + feature.get("name") + '
' +
'' + feature.get("styleUrl").split('#')[1] + '
' +
'' + feature.get("description") + '
'
); } else { popup.hide(); } });
// change mouse cursor when over marker map.on('pointermove', function(e) { //~ if (e.dragging) { //~ $(element).popover('destroy'); //~ return; //~ } var pixel = map.getEventPixel(e.originalEvent); var hit = map.hasFeatureAtPixel(pixel); map.getTarget().style.cursor = hit ? 'pointer' : ; }); };
function dmsh2deg(dmsh) { var dmsFactors = [1, 60, 3600]; var deg = 0; if (!dmsh) return deg;
var parts = dmsh.split('_'); for (var i=0, li = parts.length; i < li; i++) { var p = parts[i]; if (isNaN(+ p)) { if (p == 'S' || p == 's' || p == 'W' || p == 'w') deg = -deg; break; } else { deg += p / dmsFactors[i]; } } return deg; }
var zoomDelta = 0; // -3; // adjust zoom levels
function parseParams(param_str) { var out = {}; var params = param_str.split('|');
for (var i=0, li = params.length; i < li; i++) { var keyVal = params[i].split('=', 2); var key = keyVal[0].replace(/^\s+|\s+$/g, ).toLowerCase(); var val = keyVal[1].replace(/^\s+|\s+$/g, ); if (key == 'lon') { out.lon = dmsh2deg(val); } else if (key == 'lat') { out.lat = dmsh2deg(val); } else if (key == 'zoom') { out.zoom = +(val || 12) + zoomDelta; } else if (key == 'layer') { out.layer = val || 'N'; } else if (key == 'page') { out.page = val; } } return out; }
function round(val) { var fact = 100000; return Math.round(val * fact) / fact; }
// if (standalone && location.hash) { // $('body').empty().append(standalone_div); // $('body').addClass('cw-chartlet-extend'); // }
loadWikiCss('CruisersWiki:Ol3chartlet.css'); loadCss("http://cdnjs.cloudflare.com/ajax/libs/ol3/3.13.1/ol.css"); // use debug version, to allow patch below loadScript("http://cdnjs.cloudflare.com/ajax/libs/ol3/3.13.1/ol-debug.js", function () { if (typeof ol === 'undefined') { return; }
// patch ol.xml as /extensions/TreeAndMenu/dtree.js overwrites Node ol.xml.isNode = goog.userAgent.IE ? ol.xml.isNodeIE_ : function(value) { // return value instanceof Node; return typeof value.nodeName === "string"; };
$chartlets.each( function () { new ol3Chartlet(this); }); });});