ol地图实现模仿百度地图的范围搜索

前期准备

ol版本7.1.0   node版本16.14.2   npm版本8.5.0
 
import 'ol/ol.css';
import { Overlay, sphere } from 'ol';
// import { getDistance } from 'ol/sphere';
import Map from 'ol/Map';
import XYZ from 'ol/source/XYZ'
import View from 'ol/View';
import { get, fromLonLat, transform } from 'ol/proj';
import { Tile as TileLayer, Vector as VectorLayer } from 'ol/layer';
import { getTopLeft, getWidth } from 'ol/extent';
import Feature from 'ol/Feature';
import { Fill, Stroke, Icon, Style } from 'ol/style'
import { Polygon, MultiPolygon, LinearRing, Point, Circle } from "ol/geom";//添加图层按钮
import VectorSource from 'ol/source/Vector';
import GeoJSON from 'ol/format/GeoJSON.js';
import { fromExtent } from "ol/geom/Polygon";
// import OLCesium from 'olcs';
import geoJson from '../../../public/json/hf.json'
 
 
import markerImg from '@/assets/img/bg.png'

html准备部分

 <div id="contextmenu" class="contextmenu" draggable="true">
            <img width="18" height="14" src="@/assets/zzz.png">
        </div>
中间的图片是拖动部分的图标

style部分

.contextmenu {
    width: 44px;
    height: 30px;
    text-align: center;
    border-radius: 35px;
    background: #ddd;
    border: 2px solid #aaa;
    cursor: pointer;
}

.contextmenu:after {
    position: absolute;
    background: #ddd;
    border: 1px solid #aaa;
    left: calc(100% + 5px);
    height: 20px;
    line-height: 20px;
    padding: 2px;
    white-space: nowrap;
    content: attr(radius);
    border-radius: 3px;
}

data准备部分

            olLayer: null,//存储olLayer数据
            radius: 1000,//范围半径
            radiusCenter: [117.283406, 31.860356],//范围中心  4326编码(google编码)
            radiusCenterEPSG: [13055929.034420766, 3744994.1081686635],//范围中心  3857编码(openlayers编码)投影坐标
            radiusOverlay: null,//范围图层数据
            radiusVector: null,//范围图层数据
            radiusSource: null,//范围图层数据源数据
            radiusDom: null,//范围缩放按钮dom

先初始化地图

        // 初始化地图
        initMap() {
            let that = this;
            // 先尝试清除
            this.mapClear()
            // 获取地图容器
            this.mapDom = document.getElementById('map')

            // 初始化地图配置
            this.map = new Map({
                target: this.mapDom, // 地图容器
                view: new View({
                    center: this.mapCenter, // 地图中心点
                    zoom: 10.5, // 缩放
                    projection: 'EPSG:3857', // 坐标系 4326编码(google编码)
                }),
                controls: [] // 不显示任何控件
            })
            var projection = get('EPSG:3857');
            var projectionExtent = projection.getExtent();
            var size = getWidth(projectionExtent) / 256;
            var resolutions = new Array(19);
            var matrixIds = new Array(19);
            for (var z = 1; z < 19; ++z) {
                resolutions[z] = size / Math.pow(2, z);
                matrixIds[z] = z;
            }

            // //线路图
            this.roadmap = new TileLayer({
                visible: true,
                name: '电子图',
                className: 'blueLayer',//增加className属性    样式地图关键
                source: new XYZ({
                    url: "离线地图地址/{z}/{x}/{y}.png",
                    // crossOrigin: "anonymous", //离线瓦片跨域处理
                }),
            });
            // 将图层添加到地图
            this.map.addLayer(this.roadmap)
        },
        mapClear() {
            if (this.mapDom) {
                this.mapDom.innerHTML = ''
                this.mapDom = null
            }
        },

初始化范围方法

 // 初始化半径的逻辑代码
        initRadius() {
            //范围图层数据
            let that = this
            if (this.radiusVector && this.radiusOverlay) {
                this.radiusVector.setVisible(true)
                this.radiusOverlay.setVisible(true)
                // this.radius = 1000
                this.radiusDom.style.display = 'block';
                this.radiusSource.clear();
                this.radiusSource.addFeature(this.getCircleFeature(this.radius));
                this.setDomAttr();
                // console.log('object :>> ', this.radiusCenterEPSG[0] + this.radius);
                this.radiusOverlay.setPosition([this.radiusCenterEPSG[0] + this.radius, this.radiusCenterEPSG[1]]);
            } else {
                var overlay = new Overlay({
                    element: document.getElementById("contextmenu"),
                    positioning: 'center-center',
                    position: this.getRadiusCoord(),
                    visible: true
                });
                this.radiusOverlay = overlay
                this.map.addOverlay(overlay);

                var source = new VectorSource({
                    features: []
                });
                this.radiusSource = source
                var vector = new VectorLayer({
                    source: source,
                    style: new Style({
                        fill: new Fill({
                            color: 'rgba(135,206,250, 0.2)'
                        }),
                        stroke: new Stroke({
                            color: '#87CEFA',
                            width: 2
                        })
                    }),
                    visible: true

                });
                this.radiusVector = vector
                this.map.addLayer(vector);
                source.addFeature(this.getCircleFeature(this.radius));
                var dom = document.getElementById("contextmenu");
                dom.style.display = 'block';
                this.radiusDom = dom
                dom.onmousedown = function () {
                    dom.draggable = true;
                    dom.ondrag = function (ev) {
                        that.dragEvent(ev);
                    };
                    dom.ondragend = function (ev) {
                        that.dragEvent(ev);
                        dom.draggable = false;
                        //如果需要做筛选,在这里调用方法
                    };
                };
                this.setDomAttr()
            }

        },
        hiddenRadius() {
            if (this.radiusVector && this.radiusOverlay) {
                this.radiusVector.setVisible(false)
                this.radiusOverlay.setVisible(false)
                // this.radius = 1000
                this.radiusDom.style.display = 'none';
            }
        },

拖动范围框鼠标弹起调用的方法

        dragEvent(ev) {
            var _pixel = this.map.getPixelFromCoordinate(this.radiusCenterEPSG);
            var pixel = [ev.layerX, _pixel[1]];
            var coord = this.map.getCoordinateFromPixel(pixel);
            this.radiusOverlay.setPosition(coord);
            this.radius = this.getRadius(coord);
            // let num = this.getRadius(coord);
            this.radiusSource.clear();
            this.radiusSource.addFeature(this.getCircleFeature(this.radius));
            this.setDomAttr();
        },
        setDomAttr() {
            let radiusAbs = Math.abs(this.radius)
            var _radius = radiusAbs > 1000 ? (radiusAbs / 1000).toFixed(1) + '千米' : radiusAbs.toFixed(0) + '米';
            this.radiusDom.setAttribute("radius", _radius);
        },
   getRadius(radiusCoord) {
            return radiusCoord[0] - this.radiusCenterEPSG[0];
        },
  getRadiusCoord() {
            return [this.radiusCenterEPSG[0] + this.radius, this.radiusCenterEPSG[1]];
        },
        getCircleFeature(radius) {
            var geom = new Circle(this.radiusCenterEPSG, radius);
            var feature = new Feature({
                geometry: geom
            });
            return feature;
        },

实现效果

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值