美文网首页GIS之家
openlayers入门开发系列之地图标绘篇

openlayers入门开发系列之地图标绘篇

作者: gis之家 | 来源:发表于2018-11-11 18:06 被阅读5次

本篇的重点内容是利用openlayers实现地图标绘功能,效果图如下:

image

实现思路:

  • 标绘界面设计以及标绘面板控制
<!-- 标绘面板 -->
<div style="position:absolute;right:180px;top:80px;display:none;" id="map_toolbar_plot">
<ul class="map_toolbar_list_more map_toolbar_list_more-float  clearfix">
       <li plottype="freehandline">自由线<span class="map_toolbar_list_more_icon map_toolbar_list_more_icon-toolbar28"></span></li>
       <li plottype="polyline">折线<span class="map_toolbar_list_more_icon map_toolbar_list_more_icon-toolbar29"></span></li>
       <li plottype="arc">弧线<span class="map_toolbar_list_more_icon map_toolbar_list_more_icon-toolbar30"></span></li>
       <li plottype="curve">曲线<span class="map_toolbar_list_more_icon map_toolbar_list_more_icon-toolbar31"></span></li>
       <li plottype="freehandpolygon">手绘<span class="map_toolbar_list_more_icon map_toolbar_list_more_icon-toolbar32"></span></li>
       <li plottype="polygon">多边形<span class="map_toolbar_list_more_icon map_toolbar_list_more_icon-toolbar33"></span></li>
       <li plottype="rectangle">矩形<span class="map_toolbar_list_more_icon map_toolbar_list_more_icon-toolbar34"></span></li>
       <li plottype="circle">圆形<span class="map_toolbar_list_more_icon map_toolbar_list_more_icon-toolbar35"></span></li>
       <li plottype="assaultdirection">直角<span class="map_toolbar_list_more_icon map_toolbar_list_more_icon-toolbar36"></span></li>
       <li plottype="squadcombat">简单<span class="map_toolbar_list_more_icon map_toolbar_list_more_icon-toolbar37"></span></li>
       <li plottype="tailedsquadcombat">燕尾<span class="map_toolbar_list_more_icon map_toolbar_list_more_icon-toolbar38"></span></li>
       <li plottype="gatheringplace">集结地<span class="map_toolbar_list_more_icon map_toolbar_list_more_icon-toolbar39"></span></li>
</ul>
</div>
//标绘例
var plotFlag = false;
$("#bPlot").click(function () {
            if(!plotFlag){
                $("#map_toolbar_plot").show();
                plotFlag = true;
            }else{
                bmap.setCurrentMutexInteraction(null);
                if(bmap.dataClear){
                    bmap.dataClear.clear();
                }
                $("#map_toolbar_plot").hide();
                plotFlag = false;            
            }            
});
  • 标绘初始化以及核心代码实现
//标绘
var plottypes = ["freehandline","polyline","arc","curve","freehandpolygon","polygon",
        "rectangle","circle","assaultdirection","squadcombat","tailedsquadcombat","gatheringplace"];
for(var i = 0; i < plottypes.length; i++){
        var selector = '#map_toolbar_plot li[plottype="' + plottypes[i] + '"]';
        $(selector).on('click',function(){
            var id = "10006";//标绘工具
            var tool = bmap.getIndexInteraction(id);
            bmap.setCurrentMutexInteraction(tool);
            //标绘类型
            var plottype = $(this).attr("plottype");
            tool.setDrawType(plottype);
        })
}
/**
 *  获取带有索引的交互工具
 * @param index {String}
 * @returns {ol.interaction.Interaction|null}
 */
bxmap.Map.prototype.getIndexInteraction = function(index){
    var indexInteractions = this.get("bxmap_index_interactions") || {};
    var interaction = indexInteractions[index];
    if(interaction == null && this.getMap()){
        var arr = this.getMap().getInteractions().getArray();
        for(var i = 0; i < arr.length ; i++){
            if(index == arr[i].get(bxmap.INDEX_INTERACTION_ID)){
                interaction = arr[i];
                indexInteractions[index] = interaction;
                break;
            }
        }
    }
    return interaction;
}
/*----------标绘,依赖于GISpace动态标绘开源项目{bxmap.interaction.Plot}---------*/
/**
 * @classdesc 用于绘制军事图形,依赖于依赖于GISpace动态标绘开源项目
 * @extends {ol.interaction.Interaction}
 * @param options {Object}
 * @param options.type {String} 默认为polygon
 */
bxmap.interaction.Plot = function (options) {
    ol.interaction.Interaction.call(this, { handleEvent: this._handleKeyboardEvent });

    this.plotDraw = null; //绘制标绘
    this.plotEdit = null; //编辑标绘
    this.plotLayer = null; //标绘图层
    this.editingFeatures = new ol.Collection();//当前选择的要素

    var opt_options = options ? options : {};
    var type = opt_options.type ? opt_options.type : "polygon";
    this.setDrawType(type);
}
ol.inherits(bxmap.interaction.Plot, ol.interaction.Interaction);

/**
 * @inheritdoc
 * @param {ol.CanvasMap} map
 */
bxmap.interaction.Plot.prototype.setMap = function (map) {
    ol.interaction.Interaction.prototype.setMap.call(this, map);
    if (map) {
        // 初始化标绘绘制工具,添加绘制结束事件响应
        var plotDraw = this.plotDraw = new P.PlotDraw(map);
        plotDraw.on("draw_end", this._onDrawEnd, this);
        // 初始化标绘编辑工具
        var plotEdit = this.plotEdit = new P.PlotEdit(map);

        var plotLayer = this.plotLayer = this.getLayer();
        // 添加标绘图层
        map.addLayer(plotLayer);

        map.on('click', function (e) {
            if (plotDraw.isDrawing()) return;

            var feature = map.forEachFeatureAtPixel(e.pixel, function (feature, layer) {
                return feature;
            },{
                layerFilter: function (layer) {
                    return layer == plotLayer;
                },
                hitTolerance: 1 //1像素,仅在canvas render中有效
            });
            if (feature) {
                this.editingFeatures.push(feature);
                // 开始编辑
                this._startEditingFeature(feature);
            } else {
                // 结束编辑
                this._finishEditing();
            }
        },this);
    }
}

/**
 * @description 设置绘制图形类型
 * @param {String} drawType 类型
 * @example <caption> 图形类型有效值 </caption>
 *     arc - 弧线,curve - 曲线,polyline - 折线,freehandline - 自由线,circle - 圆,
 *     ellipse - 椭圆,closedcurve - 曲线面,polygon - 多边形,rectangle - 矩形,
 *    freehandpolygon - 自由面,gatheringplace - 聚集地,doublearrow - 钳击双箭头,
 *  straightarrow - 直线箭头,finearrow - 细直箭头,assaultdirection - 直箭头,
 *    attackarrow - 进攻箭头,tailedattackarrow - 燕尾进攻箭头,squadcombat - 斜箭头,
 *     tailedsquadcombat - 燕尾斜箭头
 */
bxmap.interaction.Plot.prototype.setDrawType = function(drawType){
    var map = this.getMap();
    this.setCursor("default");
    
    this.set("draw_type", drawType);
    if (this.plotEdit && this.plotDraw) {
        this._finishEditing();
        this.plotDraw.activate(drawType);
    }
}

/**
 * @description 获取绘制图形类型
 * @returns {String} 绘制图形类型
 */
bxmap.interaction.Plot.prototype.getDrawType = function(){
    return this.get("draw_type");
}

/**
 * @private
 * @description 更新状态
 */
bxmap.interaction.Plot.prototype._updateState = function() {
    var map = this.getMap();
    if(map == null) return;
    var active = this.getActive();
    
    var plotDraw = this.plotDraw;
    var plotEdit = this.plotEdit;
    var layer = this.plotLayer;
    //使激活
    if(active){
        this._finishEditing();
        if(plotDraw){
            var type = this.getDrawType();
            plotDraw.activate(type);
        }
    }else{
        if(plotDraw){
            plotDraw.deactivate();
        }
        this._finishEditing();
    }
};

/**
 * @description 获取标绘图层
 * @returns {ol.layer.Vector}
 */
bxmap.interaction.Plot.prototype.getLayer = function(){
    if(this.plotLayer == null){
        // 设置标绘符号显示的默认样式
        var stroke = new ol.style.Stroke({color: '#FF0000', width: 2});
        var fill = new ol.style.Fill({color: 'rgba(0,255,0,0.4)'});
        var image = new ol.style.Circle({fill: fill, stroke: stroke, radius: 8});
        drawStyle = new ol.style.Style({image: image, fill:fill, stroke:stroke});
    
        // 绘制好的标绘符号,添加到FeatureOverlay显示。
        var layer = this.plotLayer = new ol.layer.Vector({
            source: new ol.source.Vector()
        });
        layer.setStyle(drawStyle);
        layer.setZIndex(bxmap.CONFIG_LEVEL_MAX + 1);//保持不被其他图层覆盖
    }
    return this.plotLayer;
}

/**
 * @private
 * @param mapBrowserEvent
 * @returns {Boolean}
 */
bxmap.interaction.Plot.prototype._handleKeyboardEvent = function(mapBrowserEvent) {
    var stopEvent = false;
    var map = this.getMap();
    if(map == null) return;
    
    if (mapBrowserEvent.type == "keydown" || mapBrowserEvent.type == "keypress") {
        var keyEvent = mapBrowserEvent.originalEvent;
        var keyCode = keyEvent.keyCode;
        if (keyCode == 46) {//delete
            var plotLayer = this.plotLayer;
              this.editingFeatures.forEach(function (elem, index, array) {
                  var close = elem.get("close_button");
                  if (close) {
                      map.removeOverlay(close);
                  }
                  var source = plotLayer.getSource();
                source.removeFeature(elem);
              });
              this.plotEdit.deactivate();
              this.editingFeatures.clear();    
              mapBrowserEvent.preventDefault();
              stopEvent = true;
      }
    }
    return !stopEvent;
}

/**
 * @private
 * @description 绘制结束后,添加图层显示。
 */
bxmap.interaction.Plot.prototype._onDrawEnd = function (event) {
    var feature = event.feature;
    if (feature) {
        //添加到编辑要素集合中
        this.editingFeatures.push(feature);
        //添加到标绘图层
        this.plotLayer.getSource().addFeature(feature);
        this._bindingCloseButton(feature);
        //开始编辑
        this._startEditingFeature(feature);
    }
}

/**
 * @private
 * @description 开始编辑要素
 */
bxmap.interaction.Plot.prototype._startEditingFeature = function (feature) {
    if (this.plotEdit == null || feature == null) return;
    this.plotEdit.activate(feature);
    var close = feature.get("close_button");
    var map = this.getMap();
    if (map && close) {
        var exists = map.getOverlayById(close.getId());
        if(exists == null){
            map.addOverlay(close);
        }
        var ctlPoints = this.plotEdit.getControlPoints();
        var point = ctlPoints[ctlPoints.length - 1];
        close.setPosition(point);
    }
}

/**
 * @private
 * @description 结束编辑要素
 */
bxmap.interaction.Plot.prototype._finishEditing = function () {
    if (this.plotEdit) {
        this.plotEdit.deactivate();
    }

    //移除删除按钮
    var map = this.getMap();
    if (map == null) return;
    this.editingFeatures.forEach(function (elem, index, array) {
        var close = elem.get("close_button");
        if (map && close) {
            map.removeOverlay(close);
        }
    });
    this.editingFeatures.clear();
}

/**
 * @private
 * @description 获取删除按钮
 * @returns {ol.Overlay}
 */
bxmap.interaction.Plot.prototype._bindingCloseButton = function (feature) {
    if (feature == null) return;
    var uid = bxmap.common.getCounterUid(feature);
    var closeTooltipElement = document.createElement('div');
    closeTooltipElement.className = 'tooltip tooltip-close';
    var closeOverlay = new ol.Overlay({
        id: uid,
        element: closeTooltipElement,
        offset: [16, 0],
        positioning: 'bottom-center'
    });
    closeTooltipElement.innerHTML = '<a style="color:red;" href:"#" title="删除">✘</a>';
    feature.set("close_button", closeOverlay);

    //执行删除绘制
    var plotLayer = this.plotLayer;
    var plotEdit = this.plotEdit;
    var map = this.getMap();
    closeTooltipElement.addEventListener('click', function () {
        if (plotEdit && feature && plotLayer) {
            var close = feature.get("close_button");
            if (close && map) {
                map.removeOverlay(close);
            }
            var source = plotLayer.getSource();
            source.removeFeature(feature);
            plotEdit.deactivate();
        }
    });
}

/**
 * 清空绘制的数据
 */
bxmap.interaction.Plot.prototype.clear = function(){
    this._finishEditing();
    if(this.plotLayer){
        this.plotLayer.getSource().clear();
    }
}

GIS之家作品:GIS之家
GIS之家在线咨询:在线咨询

相关文章

网友评论

    本文标题:openlayers入门开发系列之地图标绘篇

    本文链接:https://www.haomeiwen.com/subject/esfffqtx.html