越學習openlayer你會發現openlayer是真的很強大,今天記錄一下學習的成果,需求是做那種室內的CAD的場景然后里面展示人員icon並且實時展示人員的位置信息,以及點擊彈出對應人員的一些位置信息,姓名,電話等等,這個在工業互聯網中是很常見的,接下來就開始操作了
由於我是在vue+ts中寫的,所以下面的代碼片段可能是基於vue來寫的
第一步,我們需要建立一個底圖,這個底圖可以是谷歌地圖也可以是我們拿到的cad渲染出來的靜態底圖
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就可以了,
新建定位圖層
// 創建定位圖層
this.positionLayer = new ollayerVector({
source: new olsourceVector(),
style: new olstyleStyle()
})
this.map.addLayer(this.positionLayer)
然后拿到數據之后,我這邊獲取的數據接口是一個list,也就是一個數組,需要for循環來添加icon
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
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也是

索嘎,完工
