openlayers3 wfs-t保存绘图

时间:2016-05-09 12:17:36

标签: save openlayers-3 geoserver

我正在使用OL3应用程序,用户可以在其中绘制,修改和删除多边形,并通过WFS-T将更改保存到GeoServer。

首先,我从这里使用了解决方案:wfs-t example app 我已经更改了代码以使用我的GeoServer中的多边形图层。绘制,修改和删除多边形函数效果很好,如果我修改或删除它也保存了多边形,但新的多边形创建没有保存,我无法弄清楚原因。原始应用程序没有任何问题。

我希望有人也尝试使用这个应用程序作为起点并解决了这个问题。有人能告诉我这是什么问题吗?

代码中最重要的部分:

    var dirty = {};
var formatWFS = new ol.format.WFS();
var formatGML = new ol.format.GML({
    featureNS: 'http://www.openplans.org/topp',
    featureType: 'poly',
    srsName: 'EPSG:3857'
    });
var transactWFS = function(p,f) {
    switch(p) {
    case 'insert':
        node = formatWFS.writeTransaction([f],null,null,formatGML);
        break;
    case 'update':
        node = formatWFS.writeTransaction(null,[f],null,formatGML);
        break;
    case 'delete':
        node = formatWFS.writeTransaction(null,null,[f],formatGML);
        break;
    }
    s = new XMLSerializer();
    str = s.serializeToString(node);
    $.ajax('http://localhost:8080/geoserver/wfs',{
        type: 'POST',
        dataType: 'xml',
        processData: false,
        contentType: 'text/xml',
        data: str
        }).done();
}

$('.btn-floating').hover(
        function() {
            $(this).addClass('darken-2');},
        function() {
            $(this).removeClass('darken-2');}
        );

$('.btnMenu').on('click', function(event) {
    $('.btnMenu').removeClass('orange');
    $(this).addClass('orange');
    map.removeInteraction(interaction);
    select.getFeatures().clear();
    map.removeInteraction(select);
    switch($(this).attr('id')) {

    case 'btnSelect':
        interaction = new ol.interaction.Select({
            style: new ol.style.Style({
                stroke: new ol.style.Stroke({color: '#f50057', width: 2})
                })
        });
        map.addInteraction(interaction);
        interaction.getFeatures().on('add', function(e) {
            props = e.element.getProperties();
            if (props.status){$('#popup-status').html(props.status);}else{$('#popup-status').html('n/a');}
            if (props.tiendas){$('#popup-tiendas').html(props.tiendas);}else{$('#popup-tiendas').html('n/a');}
            coord = $('.ol-mouse-position').html().split(',');
            overlayPopup.setPosition(coord);
            });
        break;

    case 'btnEdit':
        map.addInteraction(select);
        interaction = new ol.interaction.Modify({
            features: select.getFeatures()
            });
        map.addInteraction(interaction);

        snap = new ol.interaction.Snap({
            source: layerVector.getSource()
            });
        map.addInteraction(snap);

        dirty = {};
        select.getFeatures().on('add', function(e) {
            e.element.on('change', function(e) {
                dirty[e.target.getId()] = true;
                });
            });
        select.getFeatures().on('remove', function(e) {
            f = e.element;
            if (dirty[f.getId()]){
                delete dirty[f.getId()];
                featureProperties = f.getProperties();
                delete featureProperties.boundedBy;
                var clone = new ol.Feature(featureProperties);
                clone.setId(f.getId());
                transactWFS('update',clone);
                }
            });
        break;

    case 'btnDrawPoly':
        interaction = new ol.interaction.Draw({
            type: 'Polygon',
            source: layerVector.getSource()
        });
        map.addInteraction(interaction);
        interaction.on('drawend', function(e) {
            transactWFS('insert',e.feature);
        });
        break;

    case 'btnDelete':
        interaction = new ol.interaction.Select();
        map.addInteraction(interaction);
        interaction.getFeatures().on('change:length', function(e) {
            transactWFS('delete',e.target.item(0));
            interaction.getFeatures().clear();
            selectPointerMove.getFeatures().clear();
        });
        break;

    default:
        break;
    }
    });

我使用单个形状文件作为数据存储。

完成多边形后对GeoServer的请求:

 <Transaction xmlns="http://www.opengis.net/wfs" service="WFS" version="1.1.0" xsi:schemaLocation="http
    ://www.opengis.net/wfs http://schemas.opengis.net/wfs/1.1.0/wfs.xsd" xmlns:xsi="http://www.w3.org/2001
    /XMLSchema-instance"><Insert><poly xmlns="http://www.openplans.org/topp"><geometry><Polygon xmlns="http
    ://www.opengis.net/gml"><exterior><LinearRing><posList>2274170.418847337 5923526.286802612 2329612.7433635183
     5979783.939620501 2373640.4716557795 5936979.203780803 2330835.735816081 5891728.483035979 2274170.418847337
     5923526.286802612</posList></LinearRing></exterior></Polygon></geometry></poly></Insert></Transaction
    >

GeoServer的回复:

<?xml version="1.0" encoding="UTF-8"?><wfs:TransactionResponse xmlns:xs="http://www.w3.org/2001/XMLSchema"
 xmlns:sf="http://www.openplans.org/spearfish" xmlns:wfs="http://www.opengis.net/wfs" xmlns:gml="http
://www.opengis.net/gml" xmlns:ogc="http://www.opengis.net/ogc" xmlns:ows="http://www.opengis.net/ows"
 xmlns:tiger="http://www.census.gov" xmlns:topp="http://www.openplans.org/topp" xmlns:xlink="http://www
.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1.0" xsi:schemaLocation
="http://www.opengis.net/wfs http://localhost:8080/geoserver/schemas/wfs/1.1.0/wfs.xsd"><wfs:TransactionSummary
><wfs:totalInserted>1</wfs:totalInserted><wfs:totalUpdated>0</wfs:totalUpdated><wfs:totalDeleted>0</wfs
:totalDeleted></wfs:TransactionSummary><wfs:TransactionResults/><wfs:InsertResults><wfs:Feature><ogc
:FeatureId fid="new0"/></wfs:Feature></wfs:InsertResults></wfs:TransactionResponse>

2 个答案:

答案 0 :(得分:3)

那个代码示例看起来很熟悉......我在很久以前写过这篇文章并且惊讶于这仍然有效,以及有多少人使用过它。我很确定问题是几何列不称为几何。我相信这必须永远称为几何。我已经更新了这个例子,因为它可以使用Geoserver 2.8和OpenLayers 3.16。

在我的设置中,我在Postgis表中使用了一个简单的几何字段。这不是生产环境,但允许您在同一个表中包含所有类型的几何(点,线,多边形)。我没有在这里定义EPSG代码,但我总是在开发期间使用EPSG:3857。如果您设置这样的表,您可以测试WFS-T帖子是否有效。

CREATE TABLE wfs_geom
(
  id bigint NOT NULL,
  geometry geometry,
  CONSTRAINT wfs_geom_pkey PRIMARY KEY (id)
)
WITH (
  OIDS=FALSE
);
ALTER TABLE wfs_geom
  OWNER TO geoserver;

这是一个新的jsfiddle,但我也可以把它放在stackoverflow代码片段中。

https://jsfiddle.net/goldrydigital/13Lwsfmf/

&#13;
&#13;
var formatWFS = new ol.format.WFS();

var formatGML = new ol.format.GML({
    featureNS: 'https://geolytix.net/wfs',
    featureType: 'wfs_geom',
    srsName: 'EPSG:3857'
});

var xs = new XMLSerializer();

var sourceWFS = new ol.source.Vector({
    loader: function (extent) {
        $.ajax('https://maps.geolytix.net/geoserver/geolytix.wfs/wfs', {
            type: 'GET',
            data: {
                service: 'WFS',
                version: '1.1.0',
                request: 'GetFeature',
                typename: 'wfs_geom',
                srsname: 'EPSG:3857',
                bbox: extent.join(',') + ',EPSG:3857'
            }
        }).done(function (response) {
            sourceWFS.addFeatures(formatWFS.readFeatures(response));
        });
    },
    //strategy: ol.loadingstrategy.tile(ol.tilegrid.createXYZ()),
    strategy: ol.loadingstrategy.bbox,
    projection: 'EPSG:3857'
});

var layerWFS = new ol.layer.Vector({
    source: sourceWFS
});

var interaction;

var interactionSelectPointerMove = new ol.interaction.Select({
    condition: ol.events.condition.pointerMove
});

var interactionSelect = new ol.interaction.Select({
    style: new ol.style.Style({
        stroke: new ol.style.Stroke({
            color: '#FF2828'
        })
    })
});

var interactionSnap = new ol.interaction.Snap({
    source: layerWFS.getSource()
});

var map = new ol.Map({
    target: 'map',
    controls: [],
    interactions: [
        interactionSelectPointerMove,
        new ol.interaction.MouseWheelZoom(),
        new ol.interaction.DragPan()
    ],
    layers: [
        new ol.layer.Tile({
            source: new ol.source.OSM({
                url: 'https://cartodb-basemaps-{a-d}.global.ssl.fastly.net/dark_nolabels/{z}/{x}/{y}.png',
                opaque: false,
                attributions: []
            })
        }),
        layerWFS
    ],
    view: new ol.View({
        center: ol.proj.fromLonLat([-1.7, 53.2]),
        zoom: 6
    })
});

//wfs-t
var dirty = {};
var transactWFS = function (mode, f) {
    var node;
    switch (mode) {
        case 'insert':
            node = formatWFS.writeTransaction([f], null, null, formatGML);
            break;
        case 'update':
            node = formatWFS.writeTransaction(null, [f], null, formatGML);
            break;
        case 'delete':
            node = formatWFS.writeTransaction(null, null, [f], formatGML);
            break;
    }
    var payload = xs.serializeToString(node);
    $.ajax('https://maps.geolytix.net/geoserver/geolytix.wfs/wfs', {
        type: 'POST',
        dataType: 'xml',
        processData: false,
        contentType: 'text/xml',
        data: payload
    }).done(function() {
        sourceWFS.clear();
    });
};

$('button').click(function () {
    $(this).siblings().removeClass('btn-active');
    $(this).addClass('btn-active');
    map.removeInteraction(interaction);
    interactionSelect.getFeatures().clear();
    map.removeInteraction(interactionSelect);

    switch ($(this).attr('id')) {

        case 'btnEdit':
            map.addInteraction(interactionSelect);
            interaction = new ol.interaction.Modify({
                features: interactionSelect.getFeatures()
            });
            map.addInteraction(interaction);
            map.addInteraction(interactionSnap);
            dirty = {};
            interactionSelect.getFeatures().on('add', function (e) {
                e.element.on('change', function (e) {
                    dirty[e.target.getId()] = true;
                });
            });
            interactionSelect.getFeatures().on('remove', function (e) {
                var f = e.element;
                if (dirty[f.getId()]) {
                    delete dirty[f.getId()];
                    var featureProperties = f.getProperties();
                    delete featureProperties.boundedBy;
                    var clone = new ol.Feature(featureProperties);
                    clone.setId(f.getId());
                    transactWFS('update', clone);
                }
            });
            break;

        case 'btnPoint':
            interaction = new ol.interaction.Draw({
                type: 'Point',
                source: layerWFS.getSource()
            });
            map.addInteraction(interaction);
            interaction.on('drawend', function (e) {
                transactWFS('insert', e.feature);
            });
            break;

        case 'btnLine':
            interaction = new ol.interaction.Draw({
                type: 'LineString',
                source: layerWFS.getSource()
            });
            map.addInteraction(interaction);
            interaction.on('drawend', function (e) {
                transactWFS('insert', e.feature);
            });
            break;

        case 'btnArea':
            interaction = new ol.interaction.Draw({
                type: 'Polygon',
                source: layerWFS.getSource()
            });
            interaction.on('drawend', function (e) {
                transactWFS('insert', e.feature);
            });
            map.addInteraction(interaction);
            break;

        case 'btnDelete':
            interaction = new ol.interaction.Select();
            interaction.getFeatures().on('add', function (e) {
                transactWFS('delete', e.target.item(0));
                interactionSelectPointerMove.getFeatures().clear();
                interaction.getFeatures().clear();
            });
            map.addInteraction(interaction);
            break;

        default:
            break;
    }
});
&#13;
html,
body {
  height: 100%;
  width: 100%;
  padding: 0;
  margin: 0;
  border: 0;
}

.map {
  height: 100%;
  width: 100%;
}

#btnPoint {
  position: absolute;
  top: 10px;
  left: 10px;
}

#btnLine {
  position: absolute;
  top: 10px;
  left: 80px;
}

#btnArea {
  position: absolute;
  top: 10px;
  left: 150px;
}

#btnEdit {
  position: absolute;
  top: 10px;
  left: 220px;
}

#btnDelete {
  position: absolute;
  top: 10px;
  left: 290px;
}

.btn-active {
  background-color: #0d47a1 !important;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ol3/3.16.0/ol.css" type="text/css">
    <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
    <link rel="stylesheet" href="https://code.getmdl.io/1.1.3/material.indigo-pink.min.css">
    <script src="https://code.getmdl.io/1.1.3/material.min.js"></script>
</head>
<body>
    <div id="map" class="map"></div>
    <button id="btnPoint" class="mdl-button mdl-js-button mdl-button--fab mdl-button--colored">
      <i class="material-icons">add_location</i>
    </button>
    <button id="btnLine" class="mdl-button mdl-js-button mdl-button--fab mdl-button--colored">
      <i class="material-icons">timeline</i>
    </button>
    <button id="btnArea" class="mdl-button mdl-js-button mdl-button--fab mdl-button--colored">
      <i class="material-icons">signal_cellular_null</i>
    </button>
    <button id="btnEdit" class="mdl-button mdl-js-button mdl-button--fab mdl-button--colored">
      <i class="material-icons">build</i>
    </button>
    <button id="btnDelete" class="mdl-button mdl-js-button mdl-button--fab mdl-button--colored">
      <i class="material-icons">delete</i>
    </button>
</body>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.3.14/proj4.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/ol3/3.16.0/ol.js"></script>
</html>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

GeoServer实际上正确处理了您的请求,问题在于您的基础数据存储区不允许您尝试执行的操作。 Shapefiles必须具有名为the_geom的几何属性,因此当您发送名为poly的几何图形时,shapefile编写器会在编写该要素时忽略它。如果您使用的是数据库(例如PostGIS),那么一切都会好的。