使用Overlay创建的标签,如何才能实现鼠标移动呢?除了实现可以随意拖动Overlay之外,还需要提供一条指示线,从图标指向Overlay,就像下面图示一样。
基本的思路如下:
(1) 捕捉overlay的dom的鼠标事件“mousedown”事件,以及地图map的“pointermove”、“pointerup”事件;
(2) 当触发“mousedown”时,记录下当前鼠标在元素中的相对于基点也就是overlay定位点的位置,_x,_y;
(3) 紧接着处理“pointermove”事件,通过改变overlay的停靠点的位置,来移动元素;
(4) 当触发“pointerup”事件时,终止拖动。
1.创建一个overlay 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 import OSM from 'ol/source/OSM' ;import {fromLonLat} from 'ol/proj' ;import TileLayer from 'ol/layer/Tile' ;import View from 'ol/View' ;import Map from 'ol/Map' ;import Overlay from 'ol/Overlay' ;import DragPan from 'ol/interaction/DragPan' ;var pos = fromLonLat ([16.3725 , 48.208889 ]);var layer = new TileLayer ({ source : new OSM () }); var map = new Map ({ layers : [layer], target : 'map' , view : new View ({ center : pos, zoom : 2 }) }); var overlayDom = document .getElementById ('marker' );var overlay = new Overlay ({ position : pos, positioning : 'center-center' , element : overlayDom, stopEvent : false , dragging : false }); map.addOverlay (marker);
2.实现可拖动 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 var dragPan;let map=this .mainmap ;map.getInteractions ().forEach (function (interaction ){ if (interaction instanceof DragPan ) { dragPan = interaction; } }); let offsetXY=[0 ,0 ];overlayDom.addEventListener ('mousedown' , function (evt ) { dragPan.setActive (false ); overlay.set ('dragging' , true ); let evtCoord=map.getEventCoordinate (evt); let domCoord=overlay.get ("coordinate" ); offsetXY=[evtCoord[0 ]-domCoord[0 ],evtCoord[1 ]-domCoord[1 ]]; }); map.on ('pointermove' , function (evt ) { if (overlay.get ('dragging' ) === true ) { let coor=[evt.coordinate [0 ]-offsetXY[0 ],evt.coordinate [1 ]-offsetXY[1 ]]; overlay.setPosition (coor); overlay.set ("coordinate" ,coor); } }); map.on ('pointerup' , function ( ) { if (overlay.get ('dragging' ) === true ) { dragPan.setActive (true ); overlay.set ('dragging' , false ); } });
参考文章: 1.openlayers 地图上绘制区域悬浮弹窗实现跟随鼠标移动 (这个代码也挺简单的,没有拖动一个div,而是实现了一个可以随着鼠标移动的overlay) 2.javascript - 我们可以在OpenLayers 3上使ol.Overlay可拖动吗? (这里有一点就是说,ol.Feature可以实现任何事情,所有不要用Overlay) 3.关于Openlayers Overlay事件监听的一个坑 (这里其实是一个进行标会的案例,说了自己在开发这么一个功能的时候,遇到的手机端和PC端的问题,对于简单的一个地图PC端拖动来说,其实还是不需要的。因为里面涉及到了一些源码的东西) 4.一个可以拖动的Overlay的实例 (这是实现了拖动Overlay的实例,强烈推荐,就是源码,除了没有属性框以及连线,其他的都包括了) 5.原生JavaScript实现div拖拽效果 (涉及到一个偏移量的问题,文章中还写道了进行原生拖动的原理) 6.用Javascript获取页面元素的位置 (阮一峰的讲解) 7.js实现可拖拽的div (代码虽小,但是功能都全了) 8.使用js拖拽div (大同小异)
3.绘制链接线 这个其实有些麻烦的,我感觉。
1 2 3 4 5 6 7 8 9 10 11 12 13 import VectorLayer from 'ol/layer/Vector' ;import VectorSource from 'ol/source/Vector' ;let vectorSource = new VectorSource ({ name :"overlayLineLayer_source" , }); let vector = new VectorLayer ({ source : vectorSource, name :"overlayLineLayer_layer" , zIndex :15 }); map.addLayer (vector);
其中的feature其实就是对应了Overlayer对应的那个地图图标,就是一个箭头的地方。使用监听的方式,其实是因为地图缩放的时候,会出现的起始点连线不正确的问题,监听地图的rendercomplete,是因为不知道为什么,在第一绘制线段的时候,使用map.getPixelFromCoordinate(stationCoordinate);无法获取到正确的屏幕Pixel。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 let stationGeom=feature.getGeometry ();let stationCoordinate=stationGeom.getCoordinates (); overlay.set ("stationCoordinate" ,stationCoordinate); let mapview=map.getView ();mapview.on ("change:resolution" ,function ( ){ let label=feature.get ("label" ); let radian = 0 ; let picOffsetX=parseInt (36 *Math .sin (radian)); let picOffsetY=parseInt (36 *Math .cos (radian)); switch (label){ case 0 : picOffsetX=0 ; picOffsetY=36 ; break ; case 90 : picOffsetX=36 ; picOffsetY=0 ; break ; case 180 : picOffsetX=0 ; picOffsetY=-36 ; break ; case 270 : picOffsetX=-36 ; picOffsetY=0 ; break ; default : radian = label * (Math .PI /180 ); picOffsetX=parseInt (36 *Math .sin (radian)); picOffsetY=parseInt (36 *Math .cos (radian)); break ; } let stationPixel=map.getPixelFromCoordinate (stationCoordinate); stationPixel=[stationPixel[0 ]+picOffsetX,stationPixel[1 ]-picOffsetY]; let offsetCoordinate=map.getCoordinateFromPixel (stationPixel); overlay.set ("offsetCoordinate" ,offsetCoordinate); let lineFeature=overlay.get ("line" ); let source=that.overlayLineLayer .getSource (); if (lineFeature){ source.removeFeature (lineFeature); } let coor=overlay.get ("coordinate" ); if (coor){ let tempOffset=map.getPixelFromCoordinate (coor); tempOffset=[tempOffset[0 ]+offset[0 ],tempOffset[1 ]+offset[1 ]] coor=map.getCoordinateFromPixel (tempOffset); lineFeature = new Feature ({ geometry : new LineString ([coor,offsetCoordinate]) }); overlay.set ("line" ,lineFeature); source.addFeature (lineFeature); } }); map.once ("rendercomplete" ,function ( ){ let label=feature.get ("label" ); let radian = 0 ; let picOffsetX=parseInt (36 *Math .sin (radian)); let picOffsetY=parseInt (36 *Math .cos (radian)); switch (label){ case 0 : picOffsetX=0 ; picOffsetY=36 ; break ; case 90 : picOffsetX=36 ; picOffsetY=0 ; break ; case 180 : picOffsetX=0 ; picOffsetY=-36 ; break ; case 270 : picOffsetX=-36 ; picOffsetY=0 ; break ; default : radian = label * (Math .PI /180 ); picOffsetX=parseInt (36 *Math .sin (radian)); picOffsetY=parseInt (36 *Math .cos (radian)); break ; } let stationPixel=map.getPixelFromCoordinate (stationCoordinate); stationPixel=[stationPixel[0 ]+picOffsetX,stationPixel[1 ]-picOffsetY]; let offsetCoordinate=map.getCoordinateFromPixel (stationPixel); overlay.set ("offsetCoordinate" ,offsetCoordinate); let lineFeature=overlay.get ("line" ); let source=that.overlayLineLayer .getSource (); if (lineFeature){ source.removeFeature (lineFeature); } let coor=overlay.get ("coordinate" ); if (coor){ let tempOffset=map.getPixelFromCoordinate (coor); tempOffset=[tempOffset[0 ]+offset[0 ],tempOffset[1 ]+offset[1 ]] coor=map.getCoordinateFromPixel (tempOffset); lineFeature = new Feature ({ geometry : new LineString ([coor,offsetCoordinate]) }); overlay.set ("line" ,lineFeature); source.addFeature (lineFeature); } });
拖动绘制虚线的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 map.on ('pointermove' , function (evt ) { if (overlay.get ('dragging' ) === true ) { let coor=[evt.coordinate [0 ]-offsetXY[0 ],evt.coordinate [1 ]-offsetXY[1 ]]; overlay.setPosition (coor); overlay.set ("coordinate" ,coor); let lineFeature=overlay.get ("line" ); let source=that.overlayLineLayer .getSource (); if (lineFeature){ source.removeFeature (lineFeature); } let tempOffset=map.getPixelFromCoordinate (coor); tempOffset=[tempOffset[0 ]+offset[0 ],tempOffset[1 ]+offset[1 ]] coor=map.getCoordinateFromPixel (tempOffset); let offsetCoordinate=overlay.get ("offsetCoordinate" ); if (offsetCoordinate){ lineFeature = new Feature ({ geometry : new LineString ([coor,offsetCoordinate]) }); overlay.set ("line" ,lineFeature); source.addFeature (lineFeature); } } });
这样就完成了整个拖动ovlayer并且添加指向线的功能。
参考文章: 1.Openlayers 3 linedash画虚线 (绘制虚线)