越学习openlayer你会发现openlayer是真的很强大,今天记录一下学习的成果,需求是做那种室内的CAD的场景然后里面展示人员icon并且实时展示人员的位置信息,以及点击弹出对应人员的一些位置信息,姓名,电话等等,这个在工业互联网中是很常见的,接下来就开始操作了
由于我是在vue+ts中写的,所以下面的代码片段可能是基于vue来写的
第一步,我们需要建立一个底图,这个底图可以是谷歌地图也可以是我们拿到的cad渲染出来的静态底图
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 | let extent = [pointer.x, pointer.y, pointer2.x, pointer2.y]; // 图片图层四至 // pointer pointer2分别是静态图片左下角和右上角的基于基站的坐标 console.log(extent) let projection = new olprojProjection({ code: "xkcd-image", units: "pixels", extent: extent }); this.map = new olMap({ target: DOM接点的ID, layers: [ new ollayerImage({ source: new olsourceImageStatic({ url: 静态图片的地址, // 静态地图,如果是本地的,在vuecli3中将图片放在public里 projection: projection, imageExtent: extent // 映射到地图的范围 }) }) ], view: new olView({ center: getCenter(extent), projection: projection, zoom: 2.2, minZoom: 1, maxZoom: 12 }), // 加载控件到地图容器中 // 加载鼠标位置控件 controls: defaults().extend([mousePositionControl]) }); |
第二步,底图建立好之后,接下来绘制人员图标,我这边和后台的数据对接方式是ws,就是后台实时推送人员的位置信息,前端渲染,这个时候很刚入学者会每个icon建立一个layer,其实不是这样的,你可以先建立一个定位图层layer,一个layer一个source就可以了,
新建定位图层
1 2 3 4 5 6 | // 创建定位图层 this.positionLayer = new ollayerVector({ source: new olsourceVector(), style: new olstyleStyle() }) this.map.addLayer(this.positionLayer) |
然后拿到数据之后,我这边获取的数据接口是一个list,也就是一个数组,需要for循环来添加icon
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 | list.forEach((value: any, index: number) => { let time = new Date().getTime() if (!that.personListCache.has(value.id)) { // 绘制人员定位信息 let personS = that.createPerson(value) console.log(value) console.log(personS) that.personListCache.set(value.id, { spriteObj: personS, lastModified: time }) } else { let personIn = that.personListCache.get(value.id) // console.log(personIn.spriteObj.getGeometry().getCoordinates()) // var geometry = new olgeomPoint([value.x, value.y]) // personIn.spriteObj.setGeometry(geometry) personIn.lastModified = time if (personIn) { personIn.oldObj = { x: personIn.spriteObj.getGeometry().getCoordinates()[0], y: personIn.spriteObj.getGeometry().getCoordinates()[1] } personIn.newObj = { x: value.x, y: value.y } if (personIn.oldObj.x === personIn.newObj.x && personIn.oldObj.y === personIn.newObj.y) { // that.updataPersonPos(personIn) } else { that.updataPersonPos(personIn) } } } }) |
建立一个map的原因是,后台不确定是否会新增重复的人员给我,故建立一个map对象判断是否以及绘制在底图上,如果绘制在底图上了,那么只用改变他的位置也就是xy或者说是经纬度,如果没有就去调用createPerson方法去绘制icon
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 | createPerson(value: any) { var startMarker = new olFeature({ type: 'person', msg: value, geometry: new olgeomPoint([value.x, value.y]) }) let srcImg = value.type === 'type1' ? './images/type1.png' : value.type === 'type2' ? './images/type2.png' : './images/type3.png' var startStyle = new olstyleStyle({ image: new olstyleIcon({ anchor: [0.5, 0.5], scale: 0.3, src: srcImg, imgSize: [117, 158] }), text: new Text({ text: value.name, // font: '14px font-size', padding: [4, 7, 4, 7], fill: new Fill({ color: '#fff' }), backgroundFill: new Fill({ color: '#3737379e' }), offsetY: -34 }) }) startMarker.setStyle(startStyle) this.positionLayer.getSource().addFeature(startMarker) return startMarker } |
注意红色部分,很关键,第一次的我是直接把startStyle放到了positionLayer上,导致绘制出来的所有的icon的信息都是一样的,至于上面的三目运算大家应该知道,icon的类型不一样绘制出来的图标也是需要不一样的
好了,自定义底图上添加静态icon就完成了,
接下啦看看效果图吧,底图我随便换了一个静态图片,icon也是

索嘎,完工