使用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 ); } });
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并且添加指向线的功能。