var IndexViewModel = function(model) { var self = this, _map, _featureNameMarkers = [], _mouseTools = {}, _$textMeasurer = $("#text-measurer"), _hAlign = { left: 0, center: 1, right: 2 }, _vAlign = { top: 0, middle: 1, bottom: 2 }; // ******************************** Knockout observables ******************************** self.zoom = ko.observable(model.zoom); self.showFeatureNames = ko.observable(model.featureNames); self.showFeatureNames.subscribe(function(newValue) { if(newValue) { loadFeatureNames(true); loadWFSLayers(); } else { clearFeatureNames(); clearWFSLayers(); } }); self.contextMenu = { visible: ko.observable(false), top: ko.observable(), left: ko.observable(), lat: ko.observable(), lng: ko.observable() }; self.contextMenu.getLinkToKSO = function() { var wgs84 = { lat: self.contextMenu.lat(), lng: self.contextMenu.lng() }; var sweref99 = GeoUtil.wgs84ToSweref99(wgs84); return "https://kso.etjanster.lantmateriet.se/?e=" + sweref99.x + "&n=" + sweref99.y + "&z=11&profile=default_orto_noauth"; }; self.contextMenu.getLinkToSGU = function() { var wgs84 = { lat: self.contextMenu.lat(), lng: self.contextMenu.lng() }; var sweref99 = GeoUtil.wgs84ToSweref99(wgs84); var right = Number(sweref99.x) + 1000; var left = Number(sweref99.x) - 1000; var top = Number(sweref99.y) + 1000; var bottom = Number(sweref99.y) - 1000; return "http://apps.sgu.se/kartvisare/kartvisare-jordarter-25-100-tusen-sv.html?zoom=" + String(left) + "," + String(bottom) + "," + String(right) + "," + String(top); }; self.contextMenu.getLinkToGoogleMaps = function() { return "https://www.google.se/maps/@" + self.contextMenu.lat() + "," + self.contextMenu.lng() + ",2000m/data=!3m1!1e3"; }; self.contextMenu.getLinkToView = function() { return "/?lat=" + self.contextMenu.lat() + "&lng=" + self.contextMenu.lng() + "&zoom=" + self.zoom() + (self.showFeatureNames() ? "&featureNames=true" : ""); }; self.isAdmin = model.isAdmin; self.password = ko.observable(); self.initMap = function() { _map = createMap(); _wfslayers = createWFSLayers(_map); loadFeatureNames(); loadWFSLayers(); }; self.currentMouseTool = ko.observable(); self.tools = {}; self.zoomLevels = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15]; // ******************************** Knockout event handlers ******************************** self.onLoginButtonClicked = function() { var request = { password: self.password() }; $.postJson("/ajax/login.php", request) .done(function(response) { window.location.replace("//www.mapant.fi"); }) .fail(function(jqXhr) { }); }; self.contextMenu.onRecreateTileLinkClicked = function() { var wgs84 = { lat: self.contextMenu.lat(), lng: self.contextMenu.lng() }; var request = { latitude: wgs84.lat, longitude: wgs84.lng, full: false }; $.postJson("/ajax/recreateTile.php", request); self.contextMenu.visible(false); }; self.contextMenu.onRecreateTileFullLinkClicked = function() { var wgs84 = { lat: self.contextMenu.lat(), lng: self.contextMenu.lng() }; var sweref99 = GeoUtil.wgs84ToSweref99(wgs84); var request = { latitude: wgs84.lat, longitude: wgs84.lng, full: true }; $.postJson("/ajax/recreateTile.php", request); self.contextMenu.visible(false); }; self.onFeatureNameButtonClicked = function() { self.showFeatureNames(!self.showFeatureNames()); }; // ******************************** functions ******************************** function createMap(){ var crs = new L.Proj.CRS.TMS('EPSG:3067', '+proj=utm +zone=35 +ellps=GRS80 +units=m +towgs84=0,0,0,-0,-0,-0,0 +no_defs', [-548576.0, 6291456.0, 1548576.0, 8388608], { resolutions: [ 8192, 4096, 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 0.5, 0.25 ] }); var map = new L.Map('map', { crs: crs, continuousWorld: true, worldCopyJump: false, zoomControl: true }); var templateUrl = '//wmts.mapant.fi/wmts.php?z={z}&x={x}&y={y}'; new L.TileLayer(templateUrl, { maxZoom: 15, minZoom: 0, continuousWorld: true, attribution: 'Laser scanning and topographic data provided by the National Land Survey of Finland under the Creative Commons license.' }).addTo(map); new L.control.scale({ position: 'bottomright', imperial: false }).addTo(map); if(model.lat && model.lng) { map.setView([model.lat, model.lng], model.zoom); } else { map.setView(new L.LatLng(62,25),3); /* map.locate({ setView: true, maxZoom: 7 }); */ } L.Control.measureControl().addTo(map); L.geoJson(finlandBorder, { style: { weight: 4, color: "#00e6b8", opacity: 1 } }).addTo(map); // setup event handlers map.on("zoomstart", onMapZoomStart); map.on("zoomend", onMapZoomEnd); map.on("movestart", onMapMoveStart); map.on("moveend", onMapMoveEnd); map.on("contextmenu", onMapContextMenu, false); map.on("mousedown", onMapMouseDown); map.on("mouseup", onMapMouseUp); map.on("mousemove", onMapMouseMove); $("#map-container").on("contextmenu", function(ev) { ev.preventDefault(); return false; }); map.on("click", function(ev) { self.contextMenu.visible(false); return false; }, false); // Set default view if location not found or denied map.on("locationerror", function() { map.setView(new L.LatLng(62,25),0); }); return map; } function createWFSLayers(_map) { // Layers created in wfslayers.js return [ create_naturreservat(_map), create_nationalpark(_map), create_vag_planerad(_map), create_vag_framtida(_map), create_jarnvag_planerad(_map), create_jarnvag_framtida(_map), create_naturskydd_framtida(_map)]; } function loadWFSLayers() { if(!self.showFeatureNames()) { return; } _wfslayers.forEach(function(layer) { layer.setMap(_map); }); } function clearWFSLayers() { _wfslayers.forEach(function(layer) { layer.setMap(null); }); } function loadFeatureNames(clear) { if(!self.showFeatureNames()) { clearFeatureNames(); return; } if(self.zoom() < 10) { // too small scale, don't output names for now clearFeatureNames(); return; } // 1. get bounds var bounds = _map.getBounds(); // 2. translate to SWEREF var nw = bounds.getNorthWest(), sw = bounds.getSouthWest(), se = bounds.getSouthEast(), ne = bounds.getNorthEast(); // 3. fetch names var request = { south: Math.min(sw.lat, se.lat), north: Math.max(nw.lat, ne.lat), west: Math.min(sw.lng, nw.lng), east: Math.max(se.lng, ne.lng) }; $.postJson("/ajax/getFeatureNames.php", request) .done(function(response) { var featureNames = $.map(response.featureNames, function(fn) { return { id: parseInt(fn.id), lat: parseFloat(fn.lat), lng: parseFloat(fn.lng), text: fn.text, anchor: 1, rotation: parseFloat(fn.rotation), letterSpacing: null, type: parseInt(fn.type), size: parseInt(fn.size) }; }); // 4. update view model clearFeatureNames(); addFeatureNames(featureNames, clear); }) .fail(function(jqXhr) { }); } function clearFeatureNames() { $.each(_featureNameMarkers, function(i, fnm) { _map.removeLayer(fnm); }); _featureNameMarkers = []; } function addFeatureNames(featureNames, clear) { if(clear) { clearFeatureNames(); } $.each(featureNames, function(i, fn) { var di = L.divIcon({ className: "feature-name feature-name-type-" + fn.type + " feature-name-size-" + fn.size, html: '' + fn.text + '' }); var marker = L.marker([fn.lat, fn.lng], { icon: di }).addTo(_map); _featureNameMarkers.push(marker); }); } function getFeatureNameStyle(featureName) { var fontSize = getFontSize(featureName.size, self.zoom()), fontSizeString = "font-size:" + fontSize + "px;", dx, dy, top, bottom, left, right, rotation = "", hAlign = anchorToHorizontalAlign(featureName.anchor), vAlign = anchorToVerticalAlign(featureName.anchor), // only calculate text size if necessary textSize = featureName.rotation || hAlign === _hAlign.center || vAlign === _vAlign.middle ? measureText(featureName.text, fontSize) : { width: 0, height: 0 }; // dummy if (hAlign === _hAlign.left) { dx = -textSize.width / 2; left = 0; } else if (hAlign === _hAlign.center) { dx = 0; left = -textSize.width / 2; } else { dx = textSize.width / 2; right = 0; } if (vAlign === _vAlign.bottom) { dy = textSize.height / 2; bottom = 0; } else if (vAlign === _vAlign.middle) { dy = 0; top = -textSize.height / 2; } else { dy = -textSize.height / 2; top = 0; } if(featureName.rotation) { var a1 = dy === 0 && dx === 0 ? 0 : Math.atan2(dy, dx), a2 = a1 - featureName.rotation * Math.PI / 180, d = Math.sqrt(dx*dx + dy*dy), px = d * Math.cos(a2), py = d * Math.sin(a2); if(left !== undefined) { left = left + (dx - px); } else { right = right - (dx - px); } if(top !== undefined) { top = top + (dy - py); } else { bottom = bottom - (dy - py); } rotation = "transform:rotate(-" + featureName.rotation + "deg);"; } var horizontal = left !== undefined ? "left:" + left + "px;" : "right:" + right + "px;", vertical = top !== undefined ? "top:" + top + "px;" : "bottom:" + bottom + "px;"; var letterSpacing = featureName.letterSpacing ? "letter-spacing:" + (featureName.letterSpacing / 100 * fontSize) + "px;" : ""; return fontSizeString + horizontal + vertical + rotation + letterSpacing; } function anchorToHorizontalAlign(anchor) { if(anchor === 1 || anchor === 4 || anchor === 7) { return _hAlign.left; } else if (anchor === 2 || anchor === 5 || anchor === 8) { return _hAlign.center; } else { return _hAlign.right; } } function anchorToVerticalAlign(anchor) { if (anchor === 1 || anchor === 2 || anchor === 3) { return _vAlign.bottom; } else if (anchor === 4 || anchor === 5 || anchor === 6) { return _vAlign.middle; } else { return _vAlign.top; } } function getFontSize(points, zoom) { var baseSize = 0.4 / 19; return baseSize * points * Math.pow(2, zoom-9); } function measureText(text, fontSize) { _$textMeasurer .text(text) .css("font-size", fontSize + "px"); return { width: _$textMeasurer.width(), height: _$textMeasurer.height() }; } // ******************************** event handlers ******************************** function onMapZoomStart() { clearFeatureNames(); //clearWFSLayers(); } function onMapZoomEnd() { self.zoom(_map._zoom); loadFeatureNames(); //loadWFSLayers(); } function onMapMoveStart() { //clearWFSLayers(); } function onMapMoveEnd() { loadFeatureNames(true); //loadWFSLayers(); } function onMapContextMenu(ev) { var x = ev.originalEvent.clientX, y = ev.originalEvent.clientY, cm = self.contextMenu; cm.top(y); cm.left(x); cm.visible(true); cm.lat(ev.latlng.lat.toFixed(7)); cm.lng(ev.latlng.lng.toFixed(7)); return false; } function onMapMouseDown(ev) { if(_mouseTools[self.currentMouseTool()]){ _mouseTools[self.currentMouseTool()].onMouseDown(ev); } } function onMapMouseUp(ev) { if(_mouseTools[self.currentMouseTool()]){ _mouseTools[self.currentMouseTool()].onMouseUp(ev); } } function onMapMouseMove(ev) { if(_mouseTools[self.currentMouseTool()]){ _mouseTools[self.currentMouseTool()].onMouseMove(ev); } } function handleMouseTool(ev) { switch(_mouseEvent.tool) { case "rectangle": break; } } function getExportScriptName(format) { switch(format) { case "PNG": return "image.php?"; case "Georeferenced PNG": return "image.php?georeference=true"; default: return "exportKmz.php"; } } _mouseTools.exportMapImage = (function() { var _mouseButtonDown, _mouseRectangle, _mouseDownEvent, _mouseUpEvent, _zoomData; function drawRectangle(ev){ _mouseRectangle.setBounds([[_mouseDownEvent.latlng.lat, _mouseDownEvent.latlng.lng], [ev.latlng.lat, ev.latlng.lng]]); } function onZoomChanged(){ var vm = self.tools.exportMapImage; var zoom = vm.zoom(); if(_zoomData) { vm.width(_zoomData[zoom].width); vm.height(_zoomData[zoom].height); vm.area((_zoomData[zoom].area / 1000000).toFixed(1)); vm.tooLarge(_zoomData[zoom].tooLarge); } } $("#export-map-image-modal").on("hidden.bs.modal", function () { self.currentMouseTool(null); }); self.tools.exportMapImage = { onToolbarButtonClicked: function() { self.currentMouseTool(self.currentMouseTool() === "exportMapImage" ? null : "exportMapImage"); if(self.currentMouseTool() === "exportMapImage") { _map.dragging.disable(); } }, onModalOkButtonClicked: function() { var reso=map.options.crs.options.resolutions[self.tools.exportMapImage.zoom()]; var down = _mouseDownEvent.latlng, up = _mouseUpEvent.latlng, scriptName = getExportScriptName(self.tools.exportMapImage.format()); //getExportScriptName(self.tools.exportMapImage.format()), // url = "//www.mapant.se/fi/" + scriptName + // "?south=" + Math.min(down.lat, up.lat) + // "&north=" + Math.max(down.lat, up.lat) + // "&west=" + Math.min(down.lng, up.lng) + // "&east=" + Math.max(down.lng, up.lng) + // "&zoom=" + self.tools.exportMapImage.zoom(); var url = 'https://www.mapant.fi/'+ scriptName +'&west='+ Math.min(map.project(down,13).x-548576.0, map.project(up,13).x-548576.0)+'&south='+ Math.min(8388608-map.project(down,13).y,8388608- map.project(up,13).y) +'&east='+ Math.max(map.project(down,13).x-548576.0, map.project(up,13).x-548576.0)+'&north='+Math.max(8388608-map.project(down,13).y, 8388608-map.project(up,13).y)+'&width='+Math.abs(map.project(down,13).x-map.project(up,13).x)/reso+'&height='+Math.abs(map.project(down,13).y-map.project(up,13).y)/reso+'&zoom='+reso; if (self.tools.exportMapImage.showNorthLinesCheckbox() && self.tools.exportMapImage.drawNorthLines()){ url += "&northlines=true"; } window.location.href = url; $("#export-map-image-modal").modal("hide"); }, zoom: ko.observable(null), zoomInited: ko.observable(false), format: ko.observable("PNG"), formats: ["PNG", "Georeferenced PNG"], // , "Georeferenced PNG", "KML" drawNorthLines: ko.observable(false), width: ko.observable(), height: ko.observable(), area: ko.observable(), tooLarge: ko.observable() }; self.tools.exportMapImage.zoom.subscribe(onZoomChanged); self.tools.exportMapImage.showNorthLinesCheckbox = ko.computed(function() { return self.tools.exportMapImage.zoom() > 10; }); var ret = { onMouseDown: function(ev) { if(ev.originalEvent.button === 0) { _mouseButtonDown = true; _mouseDownEvent = ev; _mouseRectangle = L.rectangle([[ev.latlng.lat, ev.latlng.lng], [ev.latlng.lat, ev.latlng.lng]], {color: "#ff7800", weight: 2}); _mouseRectangle.addTo(_map); drawRectangle(ev); } }, onMouseUp: function(ev) { if(!_mouseButtonDown) { return; } _mouseButtonDown = false; _mouseUpEvent = ev; _map.removeLayer(_mouseRectangle); _mouseRectangle = null; var down = _mouseDownEvent.latlng, up = _mouseUpEvent.latlng, request = { south: Math.min(down.lat, up.lat), north: Math.max(down.lat, up.lat), west: Math.min(down.lng, up.lng), east: Math.max(down.lng, up.lng) }; $.postJson("/ajax/getExportMapImageSizeWMS.php", request) .done(function(response) { _zoomData = response; if(!self.tools.exportMapImage.zoomInited()) { self.tools.exportMapImage.zoom(self.zoom()); self.tools.exportMapImage.zoomInited(true); } onZoomChanged(); $("#export-map-image-modal").modal("show"); }) .fail(function(jqXhr) { alert("An error occured."); }); _map.dragging.enable(); }, onMouseMove: function(ev) { if(_mouseButtonDown) { drawRectangle(ev); } } }; return ret; })(); }; var viewModel; $(function() { window.settings = window.settings || {}; viewModel = new IndexViewModel(window.settings); ko.applyBindings(viewModel); if(window.settings.isAuthenticated) { viewModel.initMap(); } });