openlayers入门开发系列之地图标绘篇
2018-11-11 本文已影响5人
gis之家
本篇的重点内容是利用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();
}
}