Tidigare inlägg om OpenLayers har handlat om vad det är och hur man visualiserar data. I detta inlägg är det dags att lägga till ett lager som går att redigera direkt i webbkartan.
För att detta skall fungera så använder jag mig av Web Feature Services med Transactions eller WFS-T, som ingår som standard i GeoServer.
Jag utgår från det OpenLayers-projekt jag tidigare gjort, och lägger till ett vektorlager från min PostGIS databas via GeoServer och WFS. Man behöver inte ha GeoServer utan det går exempelvis lika bra med ArcGIS Server som också har stöd för WFS-T, men här handlar det om Open Source.
För att lägga till ett WFS lager så behövs lite kod:
var wfs_roads = new OpenLayers.Layer.Vector(”Vägar”, {
strategies: [new OpenLayers.Strategy.BBOX(), saveStrategy],
protocol: new OpenLayers.Protocol.WFS({
url: ”http://server-IP:8080/geoserver/wfs”,
featureNS : ”postgis_geodata”,
featureType: ”roads0”
})
});
Byt ut ”Vägar” och sökvägar till server och data så att det passar dina förutsättningar. Sedan är det bara att lägga till wfs_roads bland övriga lager i ”map.addLayers” (se originalfil).
I definitionen ovan så finns även hänvisning till en ”saveStrategy” och denna definieras med:
var saveStrategy = new OpenLayers.Strategy.Save();
saveStrategy.events.register(”success”, ”, showSuccessMsg);
saveStrategy.events.register(”failure”, ”, showFailureMsg);
För att kunna redigera data så behövs även lite verktyg. Dessa infogas med ytterligare lite kod:
// Editeringsverktyg
var panel = new OpenLayers.Control.Panel(
{’displayClass’: ’customEditingToolbar’});
var navigera = new OpenLayers.Control.Navigation({
title: ”Panorera”});
var rita = new OpenLayers.Control.DrawFeature(
wfs_roads, OpenLayers.Handler.Path,
{title: ”Rita Väg”,
displayClass: ”olControlDrawFeaturePath”,
multi: true});
var redigera = new OpenLayers.Control.ModifyFeature(wfs_roads, {
title: ”Modifiera Väg”,
displayClass: ”olControlModifyFeature”});
var radera = new DeleteFeature(wfs_roads, {title: ”Radera Väg”});
var spara = new OpenLayers.Control.Button({
title: ”Spara Ändringar”,
trigger: function() {
if(edit.feature) {
edit.selectControl.unselectAll();}
saveStrategy.save();},
displayClass: ”olControlSaveFeatures”});
panel.addControls([navigera, spara, radera, redigera, rita]);
panel.defaultControl = navigera;
map.addControl(panel);
Innan vi går vidare så behövs även lite till kod, men denna skall ligga utanför huvudfunktionen init() eller start() vad man nu döpt den till.
// Verktyg för redigering
var DeleteFeature = OpenLayers.Class(OpenLayers.Control, {
initialize: function(layer, options) {
OpenLayers.Control.prototype.initialize.apply(this, [options]);
this.layer = layer;
this.handler = new OpenLayers.Handler.Feature(
this, layer, {click: this.clickFeature});
},
clickFeature: function(feature) {
if(feature.fid == undefined) {
this.layer.destroyFeatures([feature]);
} else {
feature.state = OpenLayers.State.DELETE;
this.layer.events.triggerEvent(”afterfeaturemodified”,
{feature: feature});
feature.renderIntent = ”select”;
this.layer.drawFeature(feature);}
},
setMap: function(map) {
this.handler.setMap(map);
OpenLayers.Control.prototype.setMap.apply(this, arguments);
},
CLASS_NAME: ”OpenLayers.Control.DeleteFeature”
});
function showMsg(szMessage) {
document.getElementById(”nodelist”).innerHTML = szMessage;
setTimeout(
”document.getElementById(’nodelist’).innerHTML = ””,2000);
}
function showSuccessMsg(){
showMsg(”Transaktionen lyckades!”);
};
function showFailureMsg(){
showMsg(”Ett fel med transaktionen uppstod!”);
};
// Slut på verktyg för redigering
Meddelanden som skapas enligt ovan måste även kunna visas någonstans, så i <body> delen av dokumentet läggs följande till:
<div id=”nodelist”></div>
För att koden som skrivits in ovan så behövs även en beskrivning av knappar och beteenden. Detta görs utanför skripttaggen med lite stilmallar:
<style type=”text/css”>
/* Custom editing toolbar */
.customEditingToolbar {
float: right;
right: 0px;
height: 30px;
width: 200px;
}
.customEditingToolbar div {
float: right;
margin: 5px;
width: 24px;
height: 24px;
}
.olControlNavigationItemActive {
background-image:
url(”theme/default/img/editing_tool_bar.png”);
background-repeat: no-repeat;
background-position: -103px -23px;
}
.olControlNavigationItemInactive {
background-image:
url(”theme/default/img/editing_tool_bar.png”);
background-repeat: no-repeat;
background-position: -103px -0px;
}
.olControlDrawFeaturePathItemInactive {
background-image:
url(”theme/default/img/draw_line_off.png”);
background-repeat: no-repeat;
background-position: 0px 1px;
}
.olControlDrawFeaturePathItemActive {
background-image:
url(”theme/default/img/draw_line_on.png”);
background-repeat: no-repeat;
background-position: 0px 1px;
}
.olControlModifyFeatureItemActive {
background-image:
url(theme/default/img/move_feature_on.png);
background-repeat: no-repeat;
background-position: 0px 1px;
}
.olControlModifyFeatureItemInactive {
background-image:
url(theme/default/img/move_feature_off.png);
background-repeat: no-repeat;
background-position: 0px 1px;
}
.olControlDeleteFeatureItemActive {background-image:
url(theme/default/img/remove_point_on.png);
background-repeat: no-repeat;
background-position: 0px 1px;
}
.olControlDeleteFeatureItemInactive {
background-image:
url(theme/default/img/remove_point_off.png);
background-repeat: no-repeat;
background-position: 0px 1px;
}
</style>
Sökvägarna ovan kräver att ”theme” katalogen från OpenLayers ligger i samma katalog som webbsidan.
Till vänster webbkartan med utritad väg och till höger PostGIS data i QGIS.
Nu kommer redigeringar i webbkartan att slå igenom i exempelvis QGIS i samma sekund som man klickar på spara! Det enda som behövs är en ”refresh” vilket enklast uppnås genom att panorera kartan.
Men attributen då?
Det får bli en senare artikel…
(Koden i exemplet ovan är i huvudsak hämtad från OpenLayers exempel och modifierad för att passa mina behov. Som vanligt så ändrar WordPress om i texten och byter ut tecken så det kommer inte att fungera att kopiera texten från detta inlägg och använda det på en egen sida. På denna länk kan du öppna och ladda ner sidan, men det kommer inte att fungera att redigera data då min PostGIS och GeoServer ligger innanför brandväggen, men det går som sagt att titta på koden och anpassa den.)