一个基于Openlayersv4.6.5的封装

封装简介

项目中如果使用了Openlayers3以上版本,难免需要对图层操作;完成一些交互等工作。于是提炼出一些常用的封装逻辑,一下封装都是基于Map对象以及初始化之后。

1. 一些全局定义

为了方便查找图层,定义图层的时候,我们给图层增加_name 属性作为图层的主键。后续查找图层,过滤等操作都是基于这一定义进行。

	//默认样式
	var defaultStyle = {
        'PointHidden': new ol.style.Style({
            image: new ol.style.Circle({
                fill: new ol.style.Fill({
                    color: '#00ff00'
                }),
                radius: 0,
                stroke: new ol.style.Stroke({
                    color: '#000',
                    width: 0
                })
            })
        }),
        'PointCurrent': new ol.style.Style({
            image: new ol.style.Circle({
                fill: new ol.style.Fill({
                    color: '#00ff00'
                }),
                radius: 5,
                stroke: new ol.style.Stroke({
                    color: '#000',
                    width: 1
                })
            }),
            zIndex: 10
        }),
        'LineString': new ol.style.Style({
            stroke: new ol.style.Stroke({
                color: '#f00',
                width: 3
            })
        }),
        'DeviceStyle': new ol.style.Style({
            stroke: new ol.style.Stroke({
                width: 5,
                color: "#000099"
            })
        }),
        'TransStyleDefault': new ol.style.Style({
            image: new ol.style.Circle({
                fill: new ol.style.Fill({
                    color: '#ff0'
                }),
                radius: 10,
                stroke: new ol.style.Stroke({
                    color: '#fff',
                    width: 1
                })
            }),
            zIndex: 15
        }),
        'TransStyleActive': new ol.style.Style({
            image: new ol.style.Circle({
                fill: new ol.style.Fill({
                    color: '#f00'
                }),
                radius: 10,
                stroke: new ol.style.Stroke({
                    color: '#fff',
                    width: 1
                })
            }),
            zIndex: 15
        }),
        'AfterTransStyleDefault': new ol.style.Style({
            image: new ol.style.Circle({
                fill: new ol.style.Fill({
                    color: '#0ff'
                }),
                radius: 10,
                stroke: new ol.style.Stroke({
                    color: '#fff',
                    width: 1
                })
            }),
            zIndex: 15
        }),
        'AfterTransStyleActive': new ol.style.Style({
            image: new ol.style.Circle({
                fill: new ol.style.Fill({
                    color: '#f00'
                }),
                radius: 10,
                stroke: new ol.style.Stroke({
                    color: '#fff',
                    width: 1
                })
            }),
            zIndex: 15
        }),
        'DefaultRoute': new ol.style.Style({
            stroke: new ol.style.Stroke({
                color: '#999',
                lineCap: 'round',
                width: 10
            }),
            fill: new ol.style.Fill({
                color: '#fff'
            })
        }),
        'route': new ol.style.Style({
            stroke: new ol.style.Stroke({
                width: 1,
                color: '#A1601E'
            })
        }),
        'geoMarker': new ol.style.Style({
            image: new ol.style.Circle({
                radius: 1,
                snapToPixel: false,
                fill: new ol.style.Fill({
                    color: '#A1601E'
                }),
                stroke: new ol.style.Stroke({
                    color: '#A1601E',
                    width: 2
                })
            })
        })
    };
	/**
     *  单击事件容器
     */
    var ec = {}
    /**
     *
     * hover 事件对应图层容器
     */
    var slc = [],
        selectStyleFun = [];

    /**
     * 获取点击坐标的回调函数
     */
    var coord_collback = void(0);
    //标识是不是在取坐标
    var isCoord = false;
    var _selectStyleFun = function (fea) {
        return selectStyleFun[select.getLayer(fea).get("_name")](fea)
    }
2. 地图初始化

底图图层顺序的控制时一个比较棘手的问题,一般情况下图层顺序为:底图,其他切片图层,矢量面图层,矢量线图层,矢量点图层,高亮图层,临时图层。另外也可以使用占位图层(空图层)方式保证图层顺序的正确性。

/**
     * 高亮图层
     * @type {ol.layer.Vector}
     */
    highLightLayer = new ol.layer.Vector({
        source: new ol.source.Vector({
            wrapX: false
        })
    })
    /**
     * 临时图层
     * @type {ol.layer.Vector}
     */
    tempLayer = new ol.layer.Vector({
        source: new ol.source.Vector({
            wrapX: false
        })
    })

    map = new ol.Map({
        target: 'map',
        layers: [底图, ... , highLightLayer, tempLayer],
        view: view
    });
3. 单击私有方法定义

所有的单机逻辑都走这里,这里统一管理

/**
     * 私有的地图点击方法
     *  要素图层的点击优先,要素图层点击没有的时候触发切片图层的点击
     * @param e
     * @private
     */
    var _mapClick = function (e) {
    	//如果时取坐标
        if (isCoord) {
            coord_collback(e);
            return true;
        } else {
            var param = this;
            //获取点击位置对应的要素和图层
            var hasFea = map.hasFeatureAtPixel(e.pixel, {
                layerFilter: function (layer) {
                    return !("RegionLayer" === layer.get("_name")); //要素图层中排除 矢量切片图层
                }
            });
            //矢量数据优先
            if (hasFea) { //先检测一下有没有
                map.forEachFeatureAtPixel(e.pixel, function (feature, layer) {
                    // 停止的时候,返回true
                    var _name = layer.get("_name");
                    var _res = Object.keys(ec).find(function (item) {
                        return item === _name;
                    })
                    if (_res) {
                        if (ec[_res].callback && typeof ec[_res].callback === 'function') {
                            //如果是有回调函数,必须是回调函数返回true,才能停止;
                            return ec[_res].callback(feature)
                        }
                    }
                    return true;
                });
            } else {
                //更新当前区划
                
            }
        }
    }
4. 地图事件处理
/**
     *  给Map绑定事件
     * @param layer 事件对应图层
     * @param callback 事件回调函数
     * @param thisObj 事件参数(该参数可以传递到事件函数里面,充当this)
     */
    map.bindClickEvent = function (layer, callback, thisObj) {
        if (thisObj) map.un("click", _mapClick, thisObj)
        ec[layer.get("_name")] = {
            callback: callback || void(0),
            thisObj: thisObj || {}
        }
    }

    /**
     * 解除某事件
     * @param type
     * @param callback
     * @param thisObj
     */
    map.unBindEvent = function (type, callback, thisObj) {
        map.un(type, _mapClick, thisObj);
    }
5. 坐标拾取事件
/**
     * 针对获取坐标点击事件绑定
     * @param _callback
     */
    map.position = function (_callback) {
        if (_callback) {
            coord_collback = _callback || void(0)
            isCoord = true;
            map.on("click", _mapClick)
        } else {
            coord_collback = void(0)
            isCoord = false;
            map.un("click", _mapClick)
        }
    }
6. 矢量数据hover事件
/**
     * 绑定hover事件
     */
    map.bindHoverEvent = function (lys, selStyles) {
        if (lys instanceof Array) {
            lys.forEach(function (item, index, array) {
                selectStyleFun[item.get("_name")] = selStyles[index]
                var isCnt = slc.some(function (a) {
                    return a.get("_name") === item.get("_name")
                })
                if (!isCnt) slc.push(item)
            })
        } else {
            selectStyleFun[lys.get("_name")] = selStyles
            var isCnt = slc.some(function (a) {
                return a.get("_name") === lys.get("_name")
            })
            if (!isCnt) slc.push(lys)
        }
        if (select) map.removeInteraction(select);
        select = new ol.interaction.Select({
            condition: ol.events.condition.pointerMove,
            layers: slc,
            style: _selectStyleFun,
            multi: false
        })
        map.addInteraction(select)
    }
7. 绘图交互封装
/**
     * 绘制封装
     * @param geoType 绘制对象类型 ol.interaction.Draw.type
     * @param targetLayer 联动图层,当鼠标靠近此图层的要素时,会吸附上去
     * @param cb 绘制完成后的回调函数
     * @param pointUp 点对象特殊回调
     * @param geometryFunction ol.interaction.Draw.geometryFunction
     */
    map.startDraw = function (geoType, targetLayer, cb, pointUp, geometryFunction) {
        if (draw) map.removeInteraction(draw);
        if (snap) map.removeInteraction(snap);
        if (targetLayer && (targetLayer.getType() === "VECTOR")) {
            snap = new ol.interaction.Snap({
                source: targetLayer.getSource()
            });
        }
        var darwParam = {
            source: tempLayer.getSource(),
            type: geoType,
        };
        if (geometryFunction) {
            darwParam.geometryFunction = geometryFunction;
        }
        draw = new ol.interaction.Draw(darwParam);

        //4.5.6可用,这里可以更加细化绘制的时候鼠标按下,弹起等回调,不能使用压缩包
        // draw.handleEvent = function (event) {
        //     this.freehand_ = this.mode_ !== ol.interaction.Draw.Mode_.POINT && this.freehandCondition_(event);
        //     var pass = true;
        //     if (this.freehand_ && event.type === ol.MapBrowserEventType.POINTERDRAG && this.sketchFeature_ !== null) {
        //         this.addToDrawing_(event);
        //         pass = false;
        //     } else if (this.freehand_ && event.type === ol.MapBrowserEventType.POINTERDOWN) {
        //         pass = false;
        //     } else if (event.type === ol.MapBrowserEventType.POINTERMOVE) {
        //         pass = this.handlePointerMove_(event);
        //     } else if (event.type === ol.MapBrowserEventType.DBLCLICK) {
        //         pass = false;
        //     } else if (event.type === ol.MapBrowserEventType.SINGLECLICK) {
        //         if ($.isFunction(pointUp)) pointUp(event);
        //     }
        //     return ol.interaction.Pointer.handleEvent.call(this, event) && pass;
        // };

        draw.on("drawend", function (evt) {
            if (geoType === "Point")
                if ($.isFunction(pointUp)) pointUp(evt)
            if ($.isFunction(cb)) cb(evt.feature)
        })

        if (draw) map.addInteraction(draw);
        if (snap) map.addInteraction(snap);
    }

    /**
     * 结束绘制
     * @param notClear 若为true,则在结束绘制后,保留临时图层上的要素
     */
    map.endDraw = function (notClear) {
        if (draw) map.removeInteraction(draw);
        if (snap) map.removeInteraction(snap);
        if (tempLayer && !notClear) {
            tempLayer.getSource().clear();
        }
        ;
    }
8. 查找图层
/**
     * 查找图层
     * @param _name
     * @returns {VRLayer | undefined}
     */
    map.findLayer = function (_name) {
        return map.getLayers().getArray().find(function (lyr) {
            return _name === lyr.get("_name");
        })
    };
9. 清除临时图层
/**
     * 清除临时图层上的要素
     */
    map.cleanTempLayer = function () {
        tempLayer.getSource().clear();
    }
10. 高亮要素集合
/**
     * 高亮要素集合
     * @param features
     */
    map.flashFeatures = function (features) {
        highLightLayer.getSource().clear();
        features.forEach(function (fea) {
            if (fea.getGeometry()) {
                fea.setStyle((fea.getGeometry().getType() === "Point") ? defaultStyle.PointCurrent : defaultStyle.LineString);
                highLightLayer.getSource().addFeature(fea);
            }
        })

        var tmout = setTimeout(function () {
            highLightLayer.getSource().clear();
            tmout = null;
        }, 2000);
    }
11. 缩放至要素集合
/**
     *  缩放至
     * @param features 要素
     * @param zoom 缩放等级
     * @param isFlash 是否缩放
     */
    map.panToFeatures = function (features, zoom, isFlash) {
        if (!features) return;
        var geoms = [];
        features.forEach(function (fea) {
            if (fea && fea.getGeometry()) geoms.push(fea.getGeometry());
        })

        if (geoms.length == 1) {
            var center, extent, geom = geoms[0];
            if (geom.getType() === "Point")
                center = geom.getCoordinates().slice(0, 2);
            else if (geom.getType() === "LineString" || geom.getType() === "MultiLineString" ||
                geom.getType() === "Polygon" || geom.getType() === "MultiPolygon")
                extent = geom.getExtent();
            if (center) view.animate({
                zoom: zoom || view.getZoom()
            }, {
                center: center
            })
            if (extent) view.fit(extent, {
                padding: [20, 20, 20, 20]
            })
        } else if (geoms.length > 1) {
            view.fit(new ol.geom.GeometryCollection(geoms).getExtent(), {
                padding: [20, 20, 20, 20]
            })
        }

        if (isFlash) map.flashFeatures(features);
    }
12. 地图中弹框(popup)
	map.popup = function (loc, html) {
        map.clearPopup();
        var popup = $('<div style="z-index:999999;" class="ol-popup"><a href="#" class="ol-popup-closer"></a><div class="popup-content">' + html + '</div></div>');
        overla = new ol.Overlay({
            position: loc,
            element: popup[0],
            offset: [0, -39],
            autoPan: false,
            autoPanAnimation: {
                duration: 250
            }
        })
        popup.find('.ol-popup-closer').on("click", function () {
            tempLayer.getSource().clear();
            popup.blur();
            overla.setPosition(null);
        })
        map.addOverlay(overla);
        return overla;
    }

    map.andPOIMarker = function (geom) {
        if (tempLayer) tempLayer.getSource().clear();
        var fea = new ol.Feature({
            geometry: geom
        });
        fea.setStyle(new ol.style.Style({
            image: new ol.style.Icon({
                anchor: [0.5, 1],
                src: 'marker.png'
            })
        }));
        tempLayer.getSource().addFeature(fea);
    }
13. 缩放至范围
/**
     * 缩放到范围
     *
     * @param extent
     */
    map.zoomToExtent = function (extent) {
        map.getView().setResolution(map.getView().getResolutionForExtent(extent));
        map.getView().fit(extent, {
            padding: [30, 20, 30, 20]
        });
    };
14. 统一管理地图点击事件
/**
     * 最后触发一下点击事件
     */
    map.on("click", _mapClick);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值