Commit 4a1aa956 authored by 高晓帆's avatar 高晓帆

fix

parent 1c847bbd
{
"SERVICE_IP": "172.16.0.114:1234",
"MAP_CENTER": [39.74441007068,111.24544532751],
"version": "1.1.3"
}
\ No newline at end of file
{
"SERVICE_IP": "172.16.0.114:1234",
"MAP_CENTER": [39.74441007068,111.24544532751],
"version": "1.1.3"
}
\ No newline at end of file
/**
* 关于deck.gl的二次封装,由于很多功能使用起来不方便,因此进行二次封装
* gaoxf
*/
import { Deck } from '@deck.gl/core';
import { GeoJsonLayer, PathLayer, TextLayer, IconLayer, PolygonLayer } from '@deck.gl/layers';
import { ScenegraphLayer } from '@deck.gl/mesh-layers';
import { PathStyleExtension, CollisionFilterExtension } from '@deck.gl/extensions';
import * as turf from '@turf/turf'
export default class DeckNew {
constructor(props) {
this.deck =new Deck({ ...props })
this.initProps = { initialViewState: props.initialViewState };
this.rotate = props.initialViewState.rotate || 0;
this.pitch = props.initialViewState.pitch || 0
this.zoom = props.initialViewState.zoom || 17
this.mapLayers = [];
this.carLayers = [];
this.markerLayers = [];
this.textLayers = [];
this.polygonLayers = [];
this.pathLayers = [];
this.layerSortArray = {
carLayer: [],
textLayer: [],
markerLayer: [],
polygonLayer: [],
pathLayer: ['avoidancePath','currentPath', 'nextPath'],
bufferLayer: ['avoidancePathBuffer', 'pathBuffer', 'obstacleBuffer', 'currentCarBuffer', 'nextPathBuffer','currentPathBuffer'],
baseLayer: ['dynamicLine', 'obstacle', 'dealSingle', 'barricade', 'lane', 'lanenode', 'centerLine', 'electronicFence', 'obstacles', 'staticobjs', 'wetArea', 'dumparea', 'parkspot', 'diggingworkarea', 'stationarea', 'runablearea'],
}
this.createGeoJsonLayer = this.createGeoJsonLayer.bind(this);
this.createPathLayer = this.createPathLayer.bind(this);
this.setRotation = this.setRotation.bind(this);
this.createTextLayer = this.createTextLayer.bind(this);
this.creatMarker = this.creatMarker.bind(this);
this.creatCircle = this.creatCircle.bind(this);
this.creatPolygon = this.creatPolygon.bind(this);
this.setLayerSortName = this.setLayerSortName.bind(this);
this.setPitch = this.setPitch.bind(this);
}
initLayer() {
this.layerSort()
this.deck.setProps({
layers: [...this.textLayers, ...this.carLayers, ...this.markerLayers, this.polygonLayers,...this.mapLayers, ...this.pathLayers]
})
}
setPitch(number) {
this.pitch = number;
let zoom = this.getZoom() || this.zoom
this.deck.setProps({ initialViewState: {} })
this.deck.setProps({
initialViewState: {
latitude: document.location.mapCenter[0],
longitude: document.location.mapCenter[1],
zoom: zoom,
pitch: this.pitch,
bearing: -this.rotate,
// pickingRadius:5,
controller:true
}
})
}
getZoom() {
if (this.deck.viewState.hasOwnProperty('default-view')) {
return this.deck.viewState['default-view'].zoom
}
return this.deck.viewState.zoom
}
getPitch() {
if (this.deck.viewState.hasOwnProperty('default-view')) {
return this.deck.viewState['default-view'].pitch
}
return this.deck.viewState.pitch
}
clearLayer(key){
switch (key) {
case 'marker':
this.markerLayers=[]
break;
case 'car':
this.carLayers = [];
break;
case 'map':
this.mapLayers.forEach((item, index) => {
if (item.id == layerName) {
this.mapLayers.splice(index, 1)
}
})
break;
case 'text':
this.textLayers=[]
break;
case 'polygon':
this.polygonLayers=[]
break;
case 'path':
this.pathLayers=[]
}
}
setLayerSortName(key, name, sort) {
if (this.layerSortArray.hasOwnProperty(key)) {
if (this.layerSortArray[key].includes(name)) {
this.layerSortArray[key].forEach((m, i) => {
if (m === name) {
if (sort){
this.layerSortArray[key].splice(i, 1)
this.layerSortArray[key].splice(sort >= 1 ? sort - 1 : 0, 0, name)
}
}
})
}else{
if (sort) {
this.layerSortArray[key].splice(sort >= 1 ? sort - 1 : 0, 0, name)
} else {
this.layerSortArray[key].push(name)
}
}
}
}
createGeoJsonLayer(data, option, layerName) {
let defalutOprion = {
id: layerName,
data: this.convert(data),
stroked: true,
filled: true,
extruded: false,
wireframe: true,
getElevation: 0,
pickable: true,
}
let layer = new GeoJsonLayer(Object.assign(defalutOprion, option));
this.removeLayer('map', layerName)
this.mapLayers.push(layer)
this.initLayer()
}
creatCircle(data, option, layerName) {
let cicleList = []
data.forEach(item => {
var radius = option.radius;
var options = { steps: 20, units: 'meters', properties: { foo: 'bar' } };
var circle = turf.circle(item.coordinates, radius, options);
cicleList.push(circle)
})
const obj = {
type: "FeatureCollection",
features: [...cicleList]
}
this.createGeoJsonLayer(obj, option, layerName)
}
creatPolygon(data, option, layerName) {
let defalutOprion = {
id: layerName,
data:[data],
pickable: true,
stroked: true,
filled: true,
wireframe: true,
lineWidthMinPixels: 1,
getPolygon: d => d.coordinates,
}
let layer = new PolygonLayer(Object.assign(defalutOprion, option));
this.setLayerSortName('polygonLayer', layerName)
this.removeLayer('map', layerName)
this.mapLayers.push(layer)
this.initLayer()
}
createPathLayer(data, option, layerName) {
let defalutOprion = {
id: layerName,
data,
pickable: true,
// widthScale: 20,
// widthMinPixels: 2,
getDashArray: [3, 3],
getOffset:0,
dashJustified: false,
// dashGapPickable: true,
highPrecisionDash:true,
extensions: [new PathStyleExtension({ dash: true, offset: true })],
// getPath: d => d.path,
getColor: d => d.color,
}
const layer = new PathLayer(Object.assign(defalutOprion, option));
this.setLayerSortName('pathLayer', layerName)
this.removeLayer('path', layerName)
this.pathLayers.push(layer)
this.initLayer()
}
createCarModel(data, option, layerName) {
let defalutOprion = {
id: layerName,
data,
pickable: true,
getPosition: d => d.coordinates,
sizeScale: 1,
_lighting: 'pbr',
getTranslation: [0, 0, 0],
_dataDiff: (newData, oldData) => [{ startRow: 0, endRow: data.length + 1 }],
getOrientation: f => {
return [0, f.rotate * 180 / Math.PI + 90, 90]
},
}
const layer = new ScenegraphLayer(Object.assign(defalutOprion, option));
// this.setLayerSortName('carLayer', layerName)
this.removeLayer('car', layerName)
this.carLayers.push(layer)
this.initLayer()
}
createTextLayer(data, option, layerName) {
let defalutOprion = {
id: layerName,
data,
pickable: true,
getPosition: d => d.coordinates,
getText: d => d.name,
characterSet: 'auto',//这样设置支持中文
getAngle: 0,
getTextAnchor: 'middle',
getAlignmentBaseline: 'bottom',
fontSettings: {
buffer: 2,
sdf: true,
smoothing: 0.2
},
fontWeight: 100,
// billboard:false,
collisionEnabled: true,
collisionTestProps: {
sizeScale: 6 * 2,
sizeMaxPixels: 40 * 2,
sizeMinPixels: 1 * 2
},
extensions: [new CollisionFilterExtension()],
}
const layer = new TextLayer(Object.assign(defalutOprion, option));
// this.setLayerSortName('textLayer', layerName)
this.removeLayer('text', layerName)
this.textLayers.push(layer)
this.initLayer()
}
creatMarker(data, option, layerName) {
const layer = new IconLayer({
id: layerName,
data,
pickable: true,
// iconAtlas and iconMapping are required
// getIcon: return a string
getPosition: d => d.coordinates,
...option
});
this.setLayerSortName('markerLayer', layerName)
this.removeLayer('marker', layerName)
this.markerLayers.push(layer)
this.initLayer()
}
setRoll(coor){
let zoom = this.getZoom() || 15
let pitch = this.getPitch() || 40
this.deck.setProps({ initialViewState: {} })
this.deck.setProps({
initialViewState: {
latitude: coor[0],
longitude: coor[1],
zoom: zoom,
pitch: pitch,
bearing: -this.rotate,
// pickingRadius:5,
controller:true
// * 180 / Math.PI + 60 + 180
}
})
}
setRotation(rotate) {
this.rotate = rotate
let zoom = this.getZoom() || 15
let pitch = this.getPitch() || 40
this.deck.setProps({ initialViewState: {} })
this.deck.setProps({
initialViewState: {
latitude: document.location.mapCenter[0],
longitude: document.location.mapCenter[1],
zoom: zoom,
pitch: pitch,
bearing: -rotate,
// pickingRadius:5,
controller:true
// * 180 / Math.PI + 60 + 180
}
})
}
flyTo(coor, zoom) {
let pitch = this.getPitch() || 40
this.deck.setProps({ initialViewState: {} })
this.deck.setProps({
initialViewState: {
latitude: coor[0],
longitude: coor[1],
zoom: zoom,
pitch: pitch,
bearing: -this.rotate,
// pickingRadius:5,
controller:true
}
})
}
//根据页面中图层的顺序排序
layerSort() {
//图层的顺序
let obj = []
Object.values(this.layerSortArray).forEach(item => {
obj.push(...item)
})
let newArray = []
obj.forEach(item => {
this.mapLayers.forEach(m => {
if (item == m.id) {
newArray.push(m)
}
})
})
this.mapLayers = newArray.reverse();
}
//根据图层名字从图层数组中移除对应图层
removeLayer(type, layerName) {
switch (type) {
case 'marker':
this.markerLayers.forEach((item, index) => {
if (item.id == layerName) {
this.markerLayers.splice(index, 1)
}
})
break;
case 'car':
this.carLayers.forEach((item, index) => {
if (item.id == layerName) {
this.carLayers.splice(index, 1)
}
})
break;
case 'map':
this.mapLayers.forEach((item, index) => {
if (item.id == layerName) {
this.mapLayers.splice(index, 1)
}
})
break;
case 'text':
this.textLayers.forEach((item, index) => {
if (item.id == layerName) {
this.textLayers.splice(index, 1)
}
})
break;
case 'polygon':
this.polygonLayers.forEach((item, index) => {
if (item.id == layerName) {
this.polygonLayers.splice(index, 1)
}
})
break;
case 'path':
this.pathLayers.forEach((item, index) => {
if (item.id == layerName) {
this.pathLayers.splice(index, 1)
}
})
}
this.initLayer();
}
/**
* 移除所有图层
**/
remove() {
this.deck.setProps({
layers: []
})
}
/**
* 坐标去掉高程
**/
convert(obj) {
let { features } = obj;
for (let i = 0; i < features.length; i++) {
let { geometry } = features[i];
let { coordinates, type } = geometry;
for (let j = 0; j < coordinates.length; j++) {
if (type == "Polygon") {
for (let k = 0; k < coordinates[j].length; k++) {
if (coordinates[j][k].length > 2) {
coordinates[j][k] = coordinates[j][k].slice(0, 2)
}
}
} else {
if (coordinates[j].length > 2) {
coordinates[j] = coordinates[j].slice(0, 2)
}
}
}
}
return obj
}
/**
* 经纬度互换
**/
coorReverse(data) {
return data.map(item => {
let list = [];
list = [item[1], item[0]]
return list
})
}
/**
* 颜色16进制转成rgba
**/
convertColor(color, opacity) {
if (!color) return;
if (color.indexOf('rgba') > -1) {
let colors = color.replace('rgba', '').replace('(', '').replace(')', '').split(',').map(m => parseInt(m))
return [...colors.slice(0, 3), opacity ? opacity * 225 : 225]
} else {
let result = []
if (color.length === 4) {
result = /^#?([a-f\d])([a-f\d])([a-f\d])$/i.exec(color);
// 将分解出的分量转换为十进制数,并将它们扩展为 6 位十六进制字符串
let r = parseInt(result[1] + result[1], 16);
let g = parseInt(result[2] + result[2], 16);
let b = parseInt(result[3] + result[3], 16);
return [r, g, b, opacity ? opacity * 225 : 225]
} else {
result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(color);
// 将分解出的分量转换为十进制数
let r = parseInt(result[1], 16);
let g = parseInt(result[2], 16);
let b = parseInt(result[3], 16);
return [r, g, b, opacity ? opacity * 225 : 225]
}
}
}
mergeOption(oldOption, newOption) {
Object.keys(newOption).forEach(key => {
if (typeof newOption[key] == "object") {
if (oldOption.hasOwnProperty(key)) {
this.mergeOption(oldOption[key], newOption[key])
} else {
oldOption[key] = newOption[key]
}
} else {
oldOption[key] = newOption[key]
}
})
}
}
/**
* 关于deck.gl的二次封装,由于很多功能使用起来不方便,因此进行二次封装
* gaoxf
*/
import { Deck } from '@deck.gl/core';
import { GeoJsonLayer, PathLayer, TextLayer, IconLayer, PolygonLayer } from '@deck.gl/layers';
import { ScenegraphLayer } from '@deck.gl/mesh-layers';
import { PathStyleExtension, CollisionFilterExtension } from '@deck.gl/extensions';
import * as turf from '@turf/turf'
export default class DeckNew {
constructor(props) {
this.deck =new Deck({ ...props })
this.initProps = { initialViewState: props.initialViewState };
this.rotate = props.initialViewState.rotate || 0;
this.pitch = props.initialViewState.pitch || 0
this.zoom = props.initialViewState.zoom || 17
this.mapLayers = [];
this.carLayers = [];
this.markerLayers = [];
this.textLayers = [];
this.polygonLayers = [];
this.pathLayers = [];
this.layerSortArray = {
carLayer: [],
textLayer: [],
markerLayer: [],
polygonLayer: [],
pathLayer: ['avoidancePath','currentPath', 'nextPath'],
bufferLayer: ['avoidancePathBuffer', 'pathBuffer', 'obstacleBuffer', 'currentCarBuffer', 'nextPathBuffer','currentPathBuffer'],
baseLayer: ['dynamicLine', 'obstacle', 'dealSingle', 'barricade', 'lane', 'lanenode', 'centerLine', 'electronicFence', 'obstacles', 'staticobjs', 'wetArea', 'dumparea', 'parkspot', 'diggingworkarea', 'stationarea', 'runablearea'],
}
this.createGeoJsonLayer = this.createGeoJsonLayer.bind(this);
this.createPathLayer = this.createPathLayer.bind(this);
this.setRotation = this.setRotation.bind(this);
this.createTextLayer = this.createTextLayer.bind(this);
this.creatMarker = this.creatMarker.bind(this);
this.creatCircle = this.creatCircle.bind(this);
this.creatPolygon = this.creatPolygon.bind(this);
this.setLayerSortName = this.setLayerSortName.bind(this);
this.setPitch = this.setPitch.bind(this);
}
initLayer() {
this.layerSort()
this.deck.setProps({
layers: [...this.textLayers, ...this.carLayers, ...this.markerLayers, this.polygonLayers,...this.mapLayers, ...this.pathLayers]
})
}
setPitch(number) {
this.pitch = number;
let zoom = this.getZoom() || this.zoom
this.deck.setProps({ initialViewState: {} })
this.deck.setProps({
initialViewState: {
latitude: document.location.mapCenter[0],
longitude: document.location.mapCenter[1],
zoom: zoom,
pitch: this.pitch,
bearing: -this.rotate,
// pickingRadius:5,
controller:true
}
})
}
getZoom() {
if (this.deck.viewState.hasOwnProperty('default-view')) {
return this.deck.viewState['default-view'].zoom
}
return this.deck.viewState.zoom
}
getPitch() {
if (this.deck.viewState.hasOwnProperty('default-view')) {
return this.deck.viewState['default-view'].pitch
}
return this.deck.viewState.pitch
}
clearLayer(key){
switch (key) {
case 'marker':
this.markerLayers=[]
break;
case 'car':
this.carLayers = [];
break;
case 'map':
this.mapLayers.forEach((item, index) => {
if (item.id == layerName) {
this.mapLayers.splice(index, 1)
}
})
break;
case 'text':
this.textLayers=[]
break;
case 'polygon':
this.polygonLayers=[]
break;
case 'path':
this.pathLayers=[]
}
}
setLayerSortName(key, name, sort) {
if (this.layerSortArray.hasOwnProperty(key)) {
if (this.layerSortArray[key].includes(name)) {
this.layerSortArray[key].forEach((m, i) => {
if (m === name) {
if (sort){
this.layerSortArray[key].splice(i, 1)
this.layerSortArray[key].splice(sort >= 1 ? sort - 1 : 0, 0, name)
}
}
})
}else{
if (sort) {
this.layerSortArray[key].splice(sort >= 1 ? sort - 1 : 0, 0, name)
} else {
this.layerSortArray[key].push(name)
}
}
}
}
createGeoJsonLayer(data, option, layerName) {
let defalutOprion = {
id: layerName,
data: this.convert(data),
stroked: true,
filled: true,
extruded: false,
wireframe: true,
getElevation: 0,
pickable: true,
}
let layer = new GeoJsonLayer(Object.assign(defalutOprion, option));
this.removeLayer('map', layerName)
this.mapLayers.push(layer)
this.initLayer()
}
creatCircle(data, option, layerName) {
let cicleList = []
data.forEach(item => {
var radius = option.radius;
var options = { steps: 20, units: 'meters', properties: { foo: 'bar' } };
var circle = turf.circle(item.coordinates, radius, options);
cicleList.push(circle)
})
const obj = {
type: "FeatureCollection",
features: [...cicleList]
}
this.createGeoJsonLayer(obj, option, layerName)
}
creatPolygon(data, option, layerName) {
let defalutOprion = {
id: layerName,
data:[data],
pickable: true,
stroked: true,
filled: true,
wireframe: true,
lineWidthMinPixels: 1,
getPolygon: d => d.coordinates,
}
let layer = new PolygonLayer(Object.assign(defalutOprion, option));
this.setLayerSortName('polygonLayer', layerName)
this.removeLayer('map', layerName)
this.mapLayers.push(layer)
this.initLayer()
}
createPathLayer(data, option, layerName) {
let defalutOprion = {
id: layerName,
data,
pickable: true,
// widthScale: 20,
// widthMinPixels: 2,
getDashArray: [3, 3],
getOffset:0,
dashJustified: false,
// dashGapPickable: true,
highPrecisionDash:true,
extensions: [new PathStyleExtension({ dash: true, offset: true })],
// getPath: d => d.path,
getColor: d => d.color,
}
const layer = new PathLayer(Object.assign(defalutOprion, option));
this.setLayerSortName('pathLayer', layerName)
this.removeLayer('path', layerName)
this.pathLayers.push(layer)
this.initLayer()
}
createCarModel(data, option, layerName) {
let defalutOprion = {
id: layerName,
data,
pickable: true,
getPosition: d => d.coordinates,
sizeScale: 1,
_lighting: 'pbr',
getTranslation: [0, 0, 0],
_dataDiff: (newData, oldData) => [{ startRow: 0, endRow: data.length + 1 }],
getOrientation: f => {
return [0, f.rotate * 180 / Math.PI + 90, 90]
},
}
const layer = new ScenegraphLayer(Object.assign(defalutOprion, option));
// this.setLayerSortName('carLayer', layerName)
this.removeLayer('car', layerName)
this.carLayers.push(layer)
this.initLayer()
}
createTextLayer(data, option, layerName) {
let defalutOprion = {
id: layerName,
data,
pickable: true,
getPosition: d => d.coordinates,
getText: d => d.name,
characterSet: 'auto',//这样设置支持中文
getAngle: 0,
getTextAnchor: 'middle',
getAlignmentBaseline: 'bottom',
fontSettings: {
buffer: 2,
sdf: true,
smoothing: 0.2
},
fontWeight: 100,
// billboard:false,
collisionEnabled: true,
collisionTestProps: {
sizeScale: 6 * 2,
sizeMaxPixels: 40 * 2,
sizeMinPixels: 1 * 2
},
extensions: [new CollisionFilterExtension()],
}
const layer = new TextLayer(Object.assign(defalutOprion, option));
// this.setLayerSortName('textLayer', layerName)
this.removeLayer('text', layerName)
this.textLayers.push(layer)
this.initLayer()
}
creatMarker(data, option, layerName) {
const layer = new IconLayer({
id: layerName,
data,
pickable: true,
// iconAtlas and iconMapping are required
// getIcon: return a string
getPosition: d => d.coordinates,
...option
});
this.setLayerSortName('markerLayer', layerName)
this.removeLayer('marker', layerName)
this.markerLayers.push(layer)
this.initLayer()
}
setRoll(coor){
let zoom = this.getZoom() || 15
let pitch = this.getPitch() || 40
this.deck.setProps({ initialViewState: {} })
this.deck.setProps({
initialViewState: {
latitude: coor[0],
longitude: coor[1],
zoom: zoom,
pitch: pitch,
bearing: -this.rotate,
// pickingRadius:5,
controller:true
// * 180 / Math.PI + 60 + 180
}
})
}
setRotation(rotate) {
this.rotate = rotate
let zoom = this.getZoom() || 15
let pitch = this.getPitch() || 40
this.deck.setProps({ initialViewState: {} })
this.deck.setProps({
initialViewState: {
latitude: document.location.mapCenter[0],
longitude: document.location.mapCenter[1],
zoom: zoom,
pitch: pitch,
bearing: -rotate,
// pickingRadius:5,
controller:true
// * 180 / Math.PI + 60 + 180
}
})
}
flyTo(coor, zoom) {
let pitch = this.getPitch() || 40
this.deck.setProps({ initialViewState: {} })
this.deck.setProps({
initialViewState: {
latitude: coor[0],
longitude: coor[1],
zoom: zoom,
pitch: pitch,
bearing: -this.rotate,
// pickingRadius:5,
controller:true
}
})
}
//根据页面中图层的顺序排序
layerSort() {
//图层的顺序
let obj = []
Object.values(this.layerSortArray).forEach(item => {
obj.push(...item)
})
let newArray = []
obj.forEach(item => {
this.mapLayers.forEach(m => {
if (item == m.id) {
newArray.push(m)
}
})
})
this.mapLayers = newArray.reverse();
}
//根据图层名字从图层数组中移除对应图层
removeLayer(type, layerName) {
switch (type) {
case 'marker':
this.markerLayers.forEach((item, index) => {
if (item.id == layerName) {
this.markerLayers.splice(index, 1)
}
})
break;
case 'car':
this.carLayers.forEach((item, index) => {
if (item.id == layerName) {
this.carLayers.splice(index, 1)
}
})
break;
case 'map':
this.mapLayers.forEach((item, index) => {
if (item.id == layerName) {
this.mapLayers.splice(index, 1)
}
})
break;
case 'text':
this.textLayers.forEach((item, index) => {
if (item.id == layerName) {
this.textLayers.splice(index, 1)
}
})
break;
case 'polygon':
this.polygonLayers.forEach((item, index) => {
if (item.id == layerName) {
this.polygonLayers.splice(index, 1)
}
})
break;
case 'path':
this.pathLayers.forEach((item, index) => {
if (item.id == layerName) {
this.pathLayers.splice(index, 1)
}
})
}
this.initLayer();
}
/**
* 移除所有图层
**/
remove() {
this.deck.setProps({
layers: []
})
}
/**
* 坐标去掉高程
**/
convert(obj) {
let { features } = obj;
for (let i = 0; i < features.length; i++) {
let { geometry } = features[i];
let { coordinates, type } = geometry;
for (let j = 0; j < coordinates.length; j++) {
if (type == "Polygon") {
for (let k = 0; k < coordinates[j].length; k++) {
if (coordinates[j][k].length > 2) {
coordinates[j][k] = coordinates[j][k].slice(0, 2)
}
}
} else {
if (coordinates[j].length > 2) {
coordinates[j] = coordinates[j].slice(0, 2)
}
}
}
}
return obj
}
/**
* 经纬度互换
**/
coorReverse(data) {
return data.map(item => {
let list = [];
list = [item[1], item[0]]
return list
})
}
/**
* 颜色16进制转成rgba
**/
convertColor(color, opacity) {
if (!color) return;
if (color.indexOf('rgba') > -1) {
let colors = color.replace('rgba', '').replace('(', '').replace(')', '').split(',').map(m => parseInt(m))
return [...colors.slice(0, 3), opacity ? opacity * 225 : 225]
} else {
let result = []
if (color.length === 4) {
result = /^#?([a-f\d])([a-f\d])([a-f\d])$/i.exec(color);
// 将分解出的分量转换为十进制数,并将它们扩展为 6 位十六进制字符串
let r = parseInt(result[1] + result[1], 16);
let g = parseInt(result[2] + result[2], 16);
let b = parseInt(result[3] + result[3], 16);
return [r, g, b, opacity ? opacity * 225 : 225]
} else {
result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(color);
// 将分解出的分量转换为十进制数
let r = parseInt(result[1], 16);
let g = parseInt(result[2], 16);
let b = parseInt(result[3], 16);
return [r, g, b, opacity ? opacity * 225 : 225]
}
}
}
mergeOption(oldOption, newOption) {
Object.keys(newOption).forEach(key => {
if (typeof newOption[key] == "object") {
if (oldOption.hasOwnProperty(key)) {
this.mergeOption(oldOption[key], newOption[key])
} else {
oldOption[key] = newOption[key]
}
} else {
oldOption[key] = newOption[key]
}
})
}
}
<template>
<div class="map-contain">
<canvas id="map" ref="root"></canvas>
<img src="/image/compass.png" class="compass" ref="compass"
:style="`transform: rotateZ(${compassRotationAngle}rad)`" alt="" @click="changeCompass">
<div class="navigate-preview">
<img src="/image/navigate.png" class="navigate" @click="changeNavigate" alt="" />
</div>
</div>
</template>
<script setup>
import { markRaw, onMounted, watch, ref, computed, onBeforeUnmount, nextTick } from 'vue'
import { useMapStore } from '@/store/MapStore.js'
import { useVehicleStore } from '@/store/VehicleStore'
import { storeToRefs } from 'pinia'
import { vehicleScale } from '../js/tools'
import DeckNew from '@/tools/Deck';
import * as turf from '@turf/turf'
const safe_color = '#FFA500'
const BASE_RAD = 1.5707963267948966
const MAP_ZOOM = 17
const LAYER_PROPOITY = {
runablearea: 1,
staticobjs: 2,
diggingarea: 3,
diggingworkarea: 3,
dumparea: 4,
barricade: 5,
electronicFence: 6,
wetArea: 7,
lane: 8,
obstacles: 9,
stationarea: 10,
parkspot: 11,
lanenode: 12,
currPathinfo: 13,
nextPathinfo: 14,
avoidancePath: 15,
traj: 16,
obstacle: 17
}
const vehicles = {}
let ismousedown = false
let ismousemove = false
let resetTime = null
let obstaclePolygons = []
let dynamicPaths = []
const reNavigateTime = 2.5 * 1000
const props = defineProps({
isShowBasic: Boolean,
clearSinglePointEnable: Boolean,
reloadData: Boolean
})
let map = markRaw({})
let currentPosition = markRaw([])
const root = ref(null)
const mapLayers = markRaw({})
const safeObjects = markRaw({})
const safeTrajs = markRaw({})
const singlePaths = markRaw([])
const navigate = ref(true)
const currentRotation = ref(0)
const markerLayerGroupLists = markRaw({})
const isSinglePreview = ref(false)
const compassRotationAngle = ref(0)
const compass = ref(null)
const mapStore = useMapStore()
const mapStoreToRefs = storeToRefs(mapStore)
const {
lanenode,
lane,
runablearea,
centerline,
obstacles,
diggingworkarea,
dumparea,
barricade,
stationarea,
parkspot,
staticobjs,
electronicFence,
morepoint, // 单机循迹单路径
morepath, // 单机循迹多路径
nextPathinfo,
currPathinfo,
nextPathAvailable,
avoidancePath, // 绕障路径
obstacleData,
dynamicPathinfo, // 车辆动态路权信息
} = mapStoreToRefs
const vehicleStore = useVehicleStore()
const vehicleStoreToRefs = storeToRefs(vehicleStore)
const { vehiclesPositioninfo, safeObj, trajObj, paraminfo, deleteVehicles } = vehicleStoreToRefs
const deviceId = computed(() => {
return paraminfo.value.deviceId
})
const emits = defineEmits(['handleSend'])
onMounted(() => {
//阻止鼠标右键
document.oncontextmenu = f => {
event.returnValue = false
}
let currentCoordinate = []
let bool = false
map = new DeckNew({
initialViewState: {
latitude: document.location.mapCenter[0],
longitude: document.location.mapCenter[1],
zoom: MAP_ZOOM,
// pickingRadius:5,
controller: true,
},
controller: true,
// parent: document.getElementById('mapMain'),
canvas: 'map',
//如果deck滚动条滚动或者拖动地图时,不进行地图角度和等级矫正
onInteractionStateChange: f => {
if (!currentPosition) return
if (f.isZooming || f.isDragging) {
navigate.value = false
clearTimeout(resetTime)
resetTime = window.setTimeout(() => {
if (!navigate.value) {
navigate.value = true
dealVehicleRotate()
currentRotation.value = BASE_RAD
clearTimeout(resetTime)
resetTime=null;
}
}, reNavigateTime)
}
}
})
map.setPitch(40)
emits('handleSend', {
type: 'syncMapVersion',
msg: {}
})
})
function changeNavigate() {
navigate.value = true
dealMapRotate(currentRotation.value, currentPosition, map.getZoom())
}
// 指南针
function changeCompass() {
dealVehicleRotate(0)
currentRotation.value = BASE_RAD
if (navigate.value) {
setTimeout(() => {
dealVehicleRotate()
}, 3 * 1000)
}
}
function dealVehicleRotate(rotate) {
let keys = Object.keys(vehicles)
let target = keys.find(item => item === deviceId.value)
let currentTarget = vehicles[target]
let vehicleHeading = BASE_RAD
let currentOldHeading = currentTarget && currentTarget.options.vehicleHeading
if (typeof rotate === 'number') {
dealMapRotate(0, currentPosition, map.getZoom())
} else {
vehicleHeading = currentOldHeading
currentRotation.value = vehicleHeading
dealMapRotate(vehicleHeading, currentPosition, map.getZoom())
}
}
function dealMapLayer(value, color, layerName) {
if (!value || !map) return
let result = JSON.parse(value)
if (!result) return
let attr = {};
if (layerName === 'barricade') {
attr = {
getLineColor: map.convertColor('#0066ff', 1),
// width: 5
}
} else {
attr = {
getLineColor: feature => {
return layerName === 'lane' ? map.convertColor('#eee', 0.5) : map.convertColor(feature.properties.color, 1)
},
getFillColor: feature => {
let opacity = 0.7;
if (layerName === 'runablearea') {
opacity = 0.5
}
return layerName === 'electronicFence' ? map.convertColor(feature.properties.color, opacity) : color ? map.convertColor(color, opacity) : map.convertColor(feature.properties.color, opacity)
}
}
}
map.createGeoJsonLayer(result, attr, layerName)
mapStore.setData(layerName, null)
}
function dealMapPath(value, layerName, color) {
if (value && value.length) {
let data = JSON.parse(JSON.stringify(value))
let path = map.createPathLayer([
{
path: [...map.coorReverse(data)],
name: layerName,
}
], {
getColor: f => map.convertColor('#ffff00'),
}, layerName)
mapLayers[layerName] = layerName
const lineGeo = turf.lineString([...map.coorReverse(JSON.parse(JSON.stringify(data)))])
let bufferLine = turf.buffer(lineGeo, 6.5, { units: "meters" })
const obj = {
type: "FeatureCollection",
features: [bufferLine]
}
const attr = {
getFillColor: f => map.convertColor(color, 0.6),
getLineColor: f => map.convertColor(color, 1)
}
// map.setLayerSortName('bufferLayer', layerName + 'Buffer')
map.createGeoJsonLayer(obj, attr, layerName + 'Buffer')
mapLayers[`${layerName}Buffer`] = `${layerName}Buffer`
}
}
function dealDivIcon(value, layerName) {
if (!value || !map) return
let result = JSON.parse(value)
if (!result) return
const { features } = result
for (let i = 0; i < features.length; i++) {
let feature = features[i]
let { name, id } = feature.properties
let { coordinates } = feature.geometry
let markerCoor = null
if (layerName === 'lanenode') {
markerCoor = [coordinates[1], coordinates[0]]
} else {
let center = turf.center(feature)
markerCoor = [center.geometry.coordinates[1], center.geometry.coordinates[0]]
}
let texData = {
name: name,
id: id,
coordinates: [markerCoor[1], markerCoor[0], 1],
}
if (markerLayerGroupLists[`${layerName}${id}`]) {
markerLayerGroupLists[`${layerName}${id}`] = texData
} else {
markerLayerGroupLists[`${layerName}${id}`] = texData
}
}
map.createTextLayer([...Object.values(markerLayerGroupLists)], {
getSize: 15
}, 'text')
// map.setLayerSortName('marker', 'marker')
map.setLayerSortName('markerLayer', 'marker')
map.creatCircle(Object.values(markerLayerGroupLists), {
getFillColor: f => map.convertColor('#2aa1fa', 1),
getLineColor: f => map.convertColor('#2aa1fa', 0.5),
getLineWidth: 0.5,
radius: 1.5
}, 'marker')
mapStore.setData(layerName, null)
}
function removeLayer(obj, vehicleID) {
if (obj[vehicleID]) {
for (let item in obj[vehicleID]) {
map.removeLayer('map', obj[vehicleID][item])
}
}
}
function dealSafe(vehicleID, safe) {
if (!map) return
const { enable, data, dealedData, vehicleType, vehicleLatitude, vehicleLongtitude } = safe
removeLayer(safeObjects, vehicleID)
safeObjects[vehicleID] = {}
if (!enable) return
let safeType = [1, 20, 21].includes(vehicleType) ? 'circle' : 'rectangle'
let zIndex = 16
for (let i = 0; i < dealedData.length; i++) {
let item = JSON.parse(JSON.stringify(dealedData[i]))
let layer = safeType === 'rectangle' ? map.creatPolygon({
coordinates: map.coorReverse(item),
}, {
getFillColor: d => map.convertColor(safe_color,0.4),
getLineColor: d => map.convertColor(safe_color),
getLineWidth: 1
}, 'rectangle'+i) : map.creatCircle([vehicleLongtitude, vehicleLatitude], {
getFillColor: f => map.convertColor(safe_color,0.4),
getLineColor: f => map.convertColor(safe_color),
getLineWidth: 1,
radius: data[i]
}, vehicleID+i)
safeObjects[vehicleID][i] = vehicleID
}
}
function dealTraj(vehicleID, traj) {
if (!traj || !map) return
const { trajPathWid, radius, dealedData, vehicleType, vehicleLatitude, vehicleLongtitude } = traj
removeLayer(safeTrajs, vehicleID)
safeTrajs[vehicleID] = {}
// if (!dealedData) return
// if ((dealedData && !dealedData.length) || !radius)) return
if ([1, 20, 21].includes(vehicleType && !radius)) return;
const zIndex = LAYER_PROPOITY['traj']
if ([1, 20, 21].includes(vehicleType) && radius) {
map.creatCircle([vehicleLongtitude, vehicleLatitude], {
getFillColor: f => map.convertColor('#FFA500'),
getLineColor: f => map.convertColor('#FFA500'),
getLineWidth: 1,
radius: radius
}, vehicleID)
safeTrajs[vehicleID]['circle'] = vehicleID
} else {
if (dealedData && !dealedData.length) return;
const lineGeo = turf.lineString([...map.coorReverse(JSON.parse(JSON.stringify(dealedData)))])
// safeTrajs[vehicleID]['path'] = path
let bufferLine = turf.buffer(lineGeo, trajPathWid / 2, { units: "meters" })
const data = {
type: "FeatureCollection",
features: [bufferLine]
}
const attr = {
getFillColor: f => map.convertColor(safe_color, 0.4),
getLineColor: f => map.convertColor(safe_color, 1)
}
safeTrajs[vehicleID]['pathBuffer'] = vehicleID + 'Buffer'
map.setLayerSortName('bufferLayer', vehicleID + 'Buffer', 1)
map.createGeoJsonLayer(data, attr, vehicleID + 'Buffer')
}
}
function dealMapRotate(rotationAngle, center, zoom) {
let rotate = 0
if (rotationAngle) {
rotate = turf.radiansToDegrees(rotationAngle - BASE_RAD)
}
if (compass.value) {
compassRotationAngle.value = rotationAngle
map.setRotation(rotate)
}
center && center.length && map.flyTo(center, zoom, { animate: false })
}
function dealVehiclePosition(value) {
if (!map || !value.length) return
let zoom = map.getZoom()
for (let i = 0; i < value.length; i++) {
const item = value[i]
const { vehicleLatitude, vehicleLongtitude, vehicleHeading, vehicleID, image } = item
let vehiclePosition = [vehicleLatitude, vehicleLongtitude]
let baseObj = {
name: vehicleID,
rotate: vehicleHeading,
coordinates: [vehicleLongtitude, vehicleLatitude],
image: image,
options: {
vehicleHeading: vehicleHeading
}
}
if (vehicles[vehicleID]) {
vehicles[vehicleID] = baseObj
} else {
vehicles[vehicleID] = baseObj
}
if (vehicleID === deviceId.value) {
currentPosition = vehiclePosition
if (navigate.value) {
currentRotation.value = vehicleHeading
dealMapRotate(vehicleHeading, vehiclePosition, zoom <= MAP_ZOOM ? MAP_ZOOM : zoom)
}
}
}
initCar()
}
function initCar(){
map.clearLayer('car')
const nameText = JSON.parse(JSON.stringify(Object.values(vehicles))).map(item => {
item.coordinates = [item.coordinates[0], item.coordinates[1], 10]
return item
})
map.createTextLayer(nameText, {
getSize: 15,
getColor: f => [255, 255, 255, 255],
fontWeight: 400,
fontSettings: {
buffer: 2,
sdf: true,
smoothing: 0.5
},
}, 'carName')
let car = {};
Object.values(vehicles).forEach(item => {
if (car.hasOwnProperty(item.image)) {
car[item.image].push(item)
} else {
car[item.image] = [item]
}
})
for (let key in car) {
// map.setLayerSortName('carLayer', key)
let imageURL = `image/${key}.glb`
map.createCarModel(car[key], { scenegraph: imageURL }, key)
}
}
function dealSingleDatas(datas) {
const { color, coor } = datas
let data = JSON.parse(JSON.stringify(value))
const lineGeo = turf.lineString([...map.coorReverse(JSON.parse(JSON.stringify(data)))])
// safeTrajs[vehicleID]['path'] = path
let bufferLine = turf.buffer(lineGeo, 2, { units: "meters" })
const obj = {
type: "FeatureCollection",
features: [bufferLine]
}
const attr = {
getFillColor: f => map.convertColor(color, 0.4),
getLineColor: f => map.convertColor(color, 1)
}
map.createGeoJsonLayer(obj, attr, layerName)
singlePaths.push(layerName)
}
function dealObtacleData(value) {
if (value && value.length) {
for (let i = 0; i < value.length; i++) {
let obstacle = value[i]
let { typeColor, coordinate, centerLon, centerLat, centerRadius, centerColor } = obstacle
map.creatPolygon({
coordinates: JSON.parse(JSON.stringify(coordinate)),
}, {
getFillColor: d => map.convertColor(typeColor),
getLineColor: d => map.convertColor(typeColor),
getLineWidth: 3
}, 'obstacle')
map.setLayerSortName('buffer', 'obstacleBuffer')
map.creatCircle([centerLon, centerLat], {
getFillColor: f => map.convertColor(centerColor, 0.5),
getLineColor: f => map.convertColor(centerColor, 0.5),
getLineWidth: 0,
radius: centerRadius
}, 'obstacleBuffer')
}
}
}
function dealDynamicDatas(datas) {
let name = 'dynamicLine';
const { color, path } = datas
const lineGeo = turf.lineString([...map.coorReverse(JSON.parse(JSON.stringify(path)))])
// safeTrajs[vehicleID]['path'] = path
let bufferLine = turf.buffer(lineGeo, 2, { units: "meters" })
const obj = {
type: "FeatureCollection",
features: [bufferLine]
}
const attr = {
// getFillColor: f => map.convertColor(color, 0.3),
getLineColor: f => map.convertColor(color, 0.3),
getLineWidth: 30
}
map.createGeoJsonLayer(obj, attr, name)
}
// 直接监听props.isShowBasic 不会触发
watch(() => props.isShowBasic, () => {
nextTick(() => {
// map.invalidateSize(true)
})
})
watch(lanenode, (value) => {
dealDivIcon(value, 'lanenode', '#ff0000')
}, { immediate: true, deep: true })
watch(lane, (value) => {
dealMapLayer(value, '#fff', 'lane')
}, { immediate: true, deep: true })
watch(runablearea, (value) => {
dealMapLayer(value, '#98a0a0', 'runablearea')
}, { immediate: true, deep: true })
watch(centerline, (value) => {
dealMapLayer(value, '#eee', 'centerline')
}, { immediate: true, deep: true })
watch(obstacles, (value) => {
dealDivIcon(value, 'obstacles')
dealMapLayer(value, '#6f9bdd', 'obstacles')
}, { immediate: true, deep: true })
watch(diggingworkarea, (value) => {
dealDivIcon(value, 'diggingworkarea')
dealMapLayer(value, '#886e26', 'diggingworkarea')
}, { immediate: true, deep: true })
watch(dumparea, (value) => {
dealDivIcon(value, 'dumparea')
dealMapLayer(value, '#886e26', 'dumparea')
}, { immediate: true, deep: true })
watch(barricade, (value) => {
dealMapLayer(value, '#0000ff', 'barricade')
}, { immediate: true, deep: true })
watch(stationarea, (value) => {
dealDivIcon(value, 'stationarea')
dealMapLayer(value, '#90ee90', 'stationarea')
}, { immediate: true, deep: true })
watch(parkspot, (value) => {
dealDivIcon(value, 'parkspot')
dealMapLayer(value, '#7e8185', 'parkspot')
}, { immediate: true, deep: true })
watch(staticobjs, (value) => {
dealMapLayer(value, '#98a0a0', 'staticobjs')
}, { immediate: true, deep: true })
watch(electronicFence, (value) => {
dealDivIcon(value, 'electronicFence')
dealMapLayer(value, '#d51d20', 'electronicFence')
}, { immediate: true, deep: true })
watch(nextPathinfo, (value) => {
dealMapPath(value, 'nextPath', nextPathAvailable.value === 1 ? '#19ae19' : '#8B4513')
}, { immediate: true, deep: true })
watch(currPathinfo, (value) => {
dealMapPath(value, 'currentPath', '#19ae19')
}, { immediate: true, deep: true })
watch(avoidancePath, (value) => {
dealMapPath(value, 'avoidancePath', 'blue')
}, { immediate: true, deep: true })
watch(vehiclesPositioninfo, (value) => {
dealVehiclePosition(value)
}, {
immediate: true,
deep: true
})
watch(safeObj, (value) => {
Object.keys(value).forEach(item => {
dealSafe(item, value[item])
})
}, {
immediate: true,
deep: true
})
watch(trajObj, (value) => {
Object.keys(value).forEach(item => {
dealTraj(item, value[item])
})
}, {
immediate: true,
deep: true
})
watch(obstacleData, (value) => {
dealObtacleData(value)
}, { immediate: true, deep: true })
watch(deleteVehicles, (data) => {
if (!map) return
if (data && data.length) {
data.forEach(item => {
// map.removeLayer(vehicles[item])
removeLayer(safeTrajs, item)
removeLayer(safeObjects, item)
delete vehicles[item]
initCar()
})
}
}, {
immediate: true
})
watch(() => props.clearSinglePointEnable, (enable) => {
if (!enable) return
isSinglePreview.value = true
singlePaths.forEach(item => map.removeLayer('map',item))
}, { deep: true })
watch([morepoint, morepath], (pointData, pathData) => {
if (isSinglePreview.value && (pointData || pathData)) {
let datas = pointData.concat(pathData)
for (let i = 0; i < datas.length; i++) {
dealSingleDatas(datas[i])
}
}
}, { deep: true })
watch(dynamicPathinfo, (pathData) => {
if (pathData.length > 0) {
for (let i = 0; i < pathData.length; i++) {
dealDynamicDatas(pathData[i])
}
}
}, { deep: true })
watch(deviceId, (value) => {
if (value && map) {
dealMapRotate(currentRotation.value, currentPosition, map.getZoom())
}
}, { deep: true })
function doUnmount() {
// Object.keys(mapLayers).map(layer => map.removeLayer(mapLayers[layer]))
map.remove()
map = null
}
watch(() => props.reloadData, (value) => {
if (value) {
doUnmount()
}
})
onBeforeUnmount(() => {
doUnmount()
})
</script>
<style lang="less" scope>
.map-contain {
height: 100%;
overflow: hidden;
}
#map {
width: 200% !important;
height: 200% !important;
top: -50%;
left: -50%;
background: #171A23;
position: relative !important;
}
.navigate-preview {
background: #4A75A9;
box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.25);
border-radius: 10px;
opacity: 1;
display: flex;
align-items: center;
justify-content: center;
}
.compass,
.navigate-preview {
position: absolute;
width: 4vw;
height: 4vw;
z-index: 999;
}
.compass {
bottom: 88px;
max-width: 60px;
max-height: 60px;
}
.navigate-preview {
bottom: 24px;
max-width: 60px;
max-height: 60px;
}
</style>
<style lang="less">
.icon-node {
width: 120px !important;
white-space: nowrap;
color: #676565;
// padding-left: -2em !important;
z-index: 1;
font-size: 12px !important;
font-family: "Open Sans Regular", "Arial Unicode MS Regular", sans-serif;
text-transform: uppercase;
text-align: center;
-webkit-text-stroke-display: block;
-webkit-text-stroke-width: 1px;
-webkit-text-stroke-color: rgba(33, 33, 33, 0.8);
}
@media screen and (min-width: 1700px) {
.icon-node {
font-size: 18px !important;
}
}
.icon-node-name {
display: inline-block;
transform: scale(.6);
padding-left: -20px !important;
}
.hide {
display: none !important;
}
.middle-line {
// 为svg设置虚线,数字越大,虚线段越长,
// 设置2个参数,参数1: 虚线的长度 参数2: 虚线和虚线之间的间隔, 如果只设置一个参数,说明两个值一样大小
stroke-dasharray: 15 20;
z-index: 999;
}
.leaflet-tooltip {
color: #fff !important;
background-color: rgba(255, 255, 255, 0) !important;
border: 0 !important;
box-shadow: rgba(0, 0, 0, 0);
font-size: 12px !important;
}
.leaflet-control-attribution {
display: none !important;
}
</style>
\ No newline at end of file
<template>
<div class="map-contain">
<canvas id="map" ref="root"></canvas>
<img src="/image/compass.png" class="compass" ref="compass"
:style="`transform: rotateZ(${compassRotationAngle}rad)`" alt="" @click="changeCompass">
<div class="navigate-preview">
<img src="/image/navigate.png" class="navigate" @click="changeNavigate" alt="" />
</div>
</div>
</template>
<script setup>
import { markRaw, onMounted, watch, ref, computed, onBeforeUnmount, nextTick } from 'vue'
import { useMapStore } from '@/store/MapStore.js'
import { useVehicleStore } from '@/store/VehicleStore'
import { storeToRefs } from 'pinia'
import { vehicleScale } from '../js/tools'
import DeckNew from '@/tools/Deck';
import * as turf from '@turf/turf'
const safe_color = '#FFA500'
const BASE_RAD = 1.5707963267948966
const MAP_ZOOM = 17
const LAYER_PROPOITY = {
runablearea: 1,
staticobjs: 2,
diggingarea: 3,
diggingworkarea: 3,
dumparea: 4,
barricade: 5,
electronicFence: 6,
wetArea: 7,
lane: 8,
obstacles: 9,
stationarea: 10,
parkspot: 11,
lanenode: 12,
currPathinfo: 13,
nextPathinfo: 14,
avoidancePath: 15,
traj: 16,
obstacle: 17
}
const vehicles = {}
let ismousedown = false
let ismousemove = false
let resetTime = null
let obstaclePolygons = []
let dynamicPaths = []
const reNavigateTime = 2.5 * 1000
const props = defineProps({
isShowBasic: Boolean,
clearSinglePointEnable: Boolean,
reloadData: Boolean
})
let map = markRaw({})
let currentPosition = markRaw([])
const root = ref(null)
const mapLayers = markRaw({})
const safeObjects = markRaw({})
const safeTrajs = markRaw({})
const singlePaths = markRaw([])
const navigate = ref(true)
const currentRotation = ref(0)
const markerLayerGroupLists = markRaw({})
const isSinglePreview = ref(false)
const compassRotationAngle = ref(0)
const compass = ref(null)
const mapStore = useMapStore()
const mapStoreToRefs = storeToRefs(mapStore)
const {
lanenode,
lane,
runablearea,
centerline,
obstacles,
diggingworkarea,
dumparea,
barricade,
stationarea,
parkspot,
staticobjs,
electronicFence,
morepoint, // 单机循迹单路径
morepath, // 单机循迹多路径
nextPathinfo,
currPathinfo,
nextPathAvailable,
avoidancePath, // 绕障路径
obstacleData,
dynamicPathinfo, // 车辆动态路权信息
} = mapStoreToRefs
const vehicleStore = useVehicleStore()
const vehicleStoreToRefs = storeToRefs(vehicleStore)
const { vehiclesPositioninfo, safeObj, trajObj, paraminfo, deleteVehicles } = vehicleStoreToRefs
const deviceId = computed(() => {
return paraminfo.value.deviceId
})
const emits = defineEmits(['handleSend'])
onMounted(() => {
//阻止鼠标右键
document.oncontextmenu = f => {
event.returnValue = false
}
let currentCoordinate = []
let bool = false
map = new DeckNew({
initialViewState: {
latitude: document.location.mapCenter[0],
longitude: document.location.mapCenter[1],
zoom: MAP_ZOOM,
// pickingRadius:5,
controller: true,
},
controller: true,
// parent: document.getElementById('mapMain'),
canvas: 'map',
//如果deck滚动条滚动或者拖动地图时,不进行地图角度和等级矫正
onInteractionStateChange: f => {
if (!currentPosition) return
if (f.isZooming || f.isDragging) {
navigate.value = false
clearTimeout(resetTime)
resetTime = window.setTimeout(() => {
if (!navigate.value) {
navigate.value = true
dealVehicleRotate()
currentRotation.value = BASE_RAD
clearTimeout(resetTime)
resetTime=null;
}
}, reNavigateTime)
}
}
})
map.setPitch(40)
emits('handleSend', {
type: 'syncMapVersion',
msg: {}
})
})
function changeNavigate() {
navigate.value = true
dealMapRotate(currentRotation.value, currentPosition, map.getZoom())
}
// 指南针
function changeCompass() {
dealVehicleRotate(0)
currentRotation.value = BASE_RAD
if (navigate.value) {
setTimeout(() => {
dealVehicleRotate()
}, 3 * 1000)
}
}
function dealVehicleRotate(rotate) {
let keys = Object.keys(vehicles)
let target = keys.find(item => item === deviceId.value)
let currentTarget = vehicles[target]
let vehicleHeading = BASE_RAD
let currentOldHeading = currentTarget && currentTarget.options.vehicleHeading
if (typeof rotate === 'number') {
dealMapRotate(0, currentPosition, map.getZoom())
} else {
vehicleHeading = currentOldHeading
currentRotation.value = vehicleHeading
dealMapRotate(vehicleHeading, currentPosition, map.getZoom())
}
}
function dealMapLayer(value, color, layerName) {
if (!value || !map) return
let result = JSON.parse(value)
if (!result) return
let attr = {};
if (layerName === 'barricade') {
attr = {
getLineColor: map.convertColor('#0066ff', 1),
// width: 5
}
} else {
attr = {
getLineColor: feature => {
return layerName === 'lane' ? map.convertColor('#eee', 0.5) : map.convertColor(feature.properties.color, 1)
},
getFillColor: feature => {
let opacity = 0.7;
if (layerName === 'runablearea') {
opacity = 0.5
}
return layerName === 'electronicFence' ? map.convertColor(feature.properties.color, opacity) : color ? map.convertColor(color, opacity) : map.convertColor(feature.properties.color, opacity)
}
}
}
map.createGeoJsonLayer(result, attr, layerName)
mapStore.setData(layerName, null)
}
function dealMapPath(value, layerName, color) {
if (value && value.length) {
let data = JSON.parse(JSON.stringify(value))
let path = map.createPathLayer([
{
path: [...map.coorReverse(data)],
name: layerName,
}
], {
getColor: f => map.convertColor('#ffff00'),
}, layerName)
mapLayers[layerName] = layerName
const lineGeo = turf.lineString([...map.coorReverse(JSON.parse(JSON.stringify(data)))])
let bufferLine = turf.buffer(lineGeo, 6.5, { units: "meters" })
const obj = {
type: "FeatureCollection",
features: [bufferLine]
}
const attr = {
getFillColor: f => map.convertColor(color, 0.6),
getLineColor: f => map.convertColor(color, 1)
}
// map.setLayerSortName('bufferLayer', layerName + 'Buffer')
map.createGeoJsonLayer(obj, attr, layerName + 'Buffer')
mapLayers[`${layerName}Buffer`] = `${layerName}Buffer`
}
}
function dealDivIcon(value, layerName) {
if (!value || !map) return
let result = JSON.parse(value)
if (!result) return
const { features } = result
for (let i = 0; i < features.length; i++) {
let feature = features[i]
let { name, id } = feature.properties
let { coordinates } = feature.geometry
let markerCoor = null
if (layerName === 'lanenode') {
markerCoor = [coordinates[1], coordinates[0]]
} else {
let center = turf.center(feature)
markerCoor = [center.geometry.coordinates[1], center.geometry.coordinates[0]]
}
let texData = {
name: name,
id: id,
coordinates: [markerCoor[1], markerCoor[0], 1],
}
if (markerLayerGroupLists[`${layerName}${id}`]) {
markerLayerGroupLists[`${layerName}${id}`] = texData
} else {
markerLayerGroupLists[`${layerName}${id}`] = texData
}
}
map.createTextLayer([...Object.values(markerLayerGroupLists)], {
getSize: 15
}, 'text')
// map.setLayerSortName('marker', 'marker')
map.setLayerSortName('markerLayer', 'marker')
map.creatCircle(Object.values(markerLayerGroupLists), {
getFillColor: f => map.convertColor('#2aa1fa', 1),
getLineColor: f => map.convertColor('#2aa1fa', 0.5),
getLineWidth: 0.5,
radius: 1.5
}, 'marker')
mapStore.setData(layerName, null)
}
function removeLayer(obj, vehicleID) {
if (obj[vehicleID]) {
for (let item in obj[vehicleID]) {
map.removeLayer('map', obj[vehicleID][item])
}
}
}
function dealSafe(vehicleID, safe) {
if (!map) return
const { enable, data, dealedData, vehicleType, vehicleLatitude, vehicleLongtitude } = safe
removeLayer(safeObjects, vehicleID)
safeObjects[vehicleID] = {}
if (!enable) return
let safeType = [1, 20, 21].includes(vehicleType) ? 'circle' : 'rectangle'
let zIndex = 16
for (let i = 0; i < dealedData.length; i++) {
let item = JSON.parse(JSON.stringify(dealedData[i]))
let layer = safeType === 'rectangle' ? map.creatPolygon({
coordinates: map.coorReverse(item),
}, {
getFillColor: d => map.convertColor(safe_color,0.4),
getLineColor: d => map.convertColor(safe_color),
getLineWidth: 0.4
}, 'rectangle'+i) : map.creatCircle([vehicleLongtitude, vehicleLatitude], {
getFillColor: f => map.convertColor(safe_color,0.4),
getLineColor: f => map.convertColor(safe_color),
getLineWidth: 0.4,
radius: data[i]
}, vehicleID+i)
safeObjects[vehicleID][i] = vehicleID
}
}
function dealTraj(vehicleID, traj) {
if (!traj || !map) return
const { trajPathWid, radius, dealedData, vehicleType, vehicleLatitude, vehicleLongtitude } = traj
removeLayer(safeTrajs, vehicleID)
safeTrajs[vehicleID] = {}
// if (!dealedData) return
// if ((dealedData && !dealedData.length) || !radius)) return
if ([1, 20, 21].includes(vehicleType && !radius)) return;
const zIndex = LAYER_PROPOITY['traj']
if ([1, 20, 21].includes(vehicleType) && radius) {
map.creatCircle([vehicleLongtitude, vehicleLatitude], {
getFillColor: f => map.convertColor('#FFA500'),
getLineColor: f => map.convertColor('#FFA500'),
getLineWidth: 1,
radius: radius
}, vehicleID)
safeTrajs[vehicleID]['circle'] = vehicleID
} else {
if (dealedData && !dealedData.length) return;
const lineGeo = turf.lineString([...map.coorReverse(JSON.parse(JSON.stringify(dealedData)))])
// safeTrajs[vehicleID]['path'] = path
let bufferLine = turf.buffer(lineGeo, trajPathWid / 2, { units: "meters" })
const data = {
type: "FeatureCollection",
features: [bufferLine]
}
const attr = {
getFillColor: f => map.convertColor(safe_color, 0.4),
getLineColor: f => map.convertColor(safe_color, 1)
}
safeTrajs[vehicleID]['pathBuffer'] = vehicleID + 'Buffer'
map.setLayerSortName('bufferLayer', vehicleID + 'Buffer', 1)
map.createGeoJsonLayer(data, attr, vehicleID + 'Buffer')
}
}
function dealMapRotate(rotationAngle, center, zoom) {
let rotate = 0
if (rotationAngle) {
rotate = turf.radiansToDegrees(rotationAngle - BASE_RAD)
}
if (compass.value) {
compassRotationAngle.value = rotationAngle
map.setRotation(rotate)
}
center && center.length && map.flyTo(center, zoom, { animate: false })
}
function dealVehiclePosition(value) {
if (!map || !value.length) return
let zoom = map.getZoom()
for (let i = 0; i < value.length; i++) {
const item = value[i]
const { vehicleLatitude, vehicleLongtitude, vehicleHeading, vehicleID, image } = item
let vehiclePosition = [vehicleLatitude, vehicleLongtitude]
let baseObj = {
name: vehicleID,
rotate: vehicleHeading,
coordinates: [vehicleLongtitude, vehicleLatitude],
image: image,
options: {
vehicleHeading: vehicleHeading
}
}
if (vehicles[vehicleID]) {
vehicles[vehicleID] = baseObj
} else {
vehicles[vehicleID] = baseObj
}
if (vehicleID === deviceId.value) {
currentPosition = vehiclePosition
if (navigate.value) {
currentRotation.value = vehicleHeading
dealMapRotate(vehicleHeading, vehiclePosition, zoom <= MAP_ZOOM ? MAP_ZOOM : zoom)
}
}
}
initCar()
}
function initCar(){
map.clearLayer('car')
const nameText = JSON.parse(JSON.stringify(Object.values(vehicles))).map(item => {
item.coordinates = [item.coordinates[0], item.coordinates[1], 10]
return item
})
map.createTextLayer(nameText, {
getSize: 15,
getColor: f => [255, 255, 255, 255],
fontWeight: 400,
fontSettings: {
buffer: 2,
sdf: true,
smoothing: 0.5
},
}, 'carName')
let car = {};
Object.values(vehicles).forEach(item => {
if (car.hasOwnProperty(item.image)) {
car[item.image].push(item)
} else {
car[item.image] = [item]
}
})
for (let key in car) {
// map.setLayerSortName('carLayer', key)
let imageURL = `image/${key}.glb`
map.createCarModel(car[key], { scenegraph: imageURL }, key)
}
}
function dealSingleDatas(datas) {
const { color, coor } = datas
let data = JSON.parse(JSON.stringify(value))
const lineGeo = turf.lineString([...map.coorReverse(JSON.parse(JSON.stringify(data)))])
// safeTrajs[vehicleID]['path'] = path
let bufferLine = turf.buffer(lineGeo, 2, { units: "meters" })
const obj = {
type: "FeatureCollection",
features: [bufferLine]
}
const attr = {
getFillColor: f => map.convertColor(color, 0.4),
getLineColor: f => map.convertColor(color, 1)
}
map.createGeoJsonLayer(obj, attr, layerName)
singlePaths.push(layerName)
}
function dealObtacleData(value) {
if (value && value.length) {
for (let i = 0; i < value.length; i++) {
let obstacle = value[i]
let { typeColor, coordinate, centerLon, centerLat, centerRadius, centerColor } = obstacle
map.creatPolygon({
coordinates: JSON.parse(JSON.stringify(coordinate)),
}, {
getFillColor: d => map.convertColor(typeColor),
getLineColor: d => map.convertColor(typeColor),
getLineWidth: 3
}, 'obstacle')
map.setLayerSortName('buffer', 'obstacleBuffer')
map.creatCircle([centerLon, centerLat], {
getFillColor: f => map.convertColor(centerColor, 0.5),
getLineColor: f => map.convertColor(centerColor, 0.5),
getLineWidth: 0,
radius: centerRadius
}, 'obstacleBuffer')
}
}
}
function dealDynamicDatas(datas) {
let name = 'dynamicLine';
const { color, path } = datas
const lineGeo = turf.lineString([...map.coorReverse(JSON.parse(JSON.stringify(path)))])
// safeTrajs[vehicleID]['path'] = path
let bufferLine = turf.buffer(lineGeo, 2, { units: "meters" })
const obj = {
type: "FeatureCollection",
features: [bufferLine]
}
const attr = {
// getFillColor: f => map.convertColor(color, 0.3),
getLineColor: f => map.convertColor(color, 0.3),
getLineWidth: 30
}
map.createGeoJsonLayer(obj, attr, name)
}
// 直接监听props.isShowBasic 不会触发
watch(() => props.isShowBasic, () => {
nextTick(() => {
// map.invalidateSize(true)
})
})
watch(lanenode, (value) => {
dealDivIcon(value, 'lanenode', '#ff0000')
}, { immediate: true, deep: true })
watch(lane, (value) => {
dealMapLayer(value, '#fff', 'lane')
}, { immediate: true, deep: true })
watch(runablearea, (value) => {
dealMapLayer(value, '#98a0a0', 'runablearea')
}, { immediate: true, deep: true })
watch(centerline, (value) => {
dealMapLayer(value, '#eee', 'centerline')
}, { immediate: true, deep: true })
watch(obstacles, (value) => {
dealDivIcon(value, 'obstacles')
dealMapLayer(value, '#6f9bdd', 'obstacles')
}, { immediate: true, deep: true })
watch(diggingworkarea, (value) => {
dealDivIcon(value, 'diggingworkarea')
dealMapLayer(value, '#886e26', 'diggingworkarea')
}, { immediate: true, deep: true })
watch(dumparea, (value) => {
dealDivIcon(value, 'dumparea')
dealMapLayer(value, '#886e26', 'dumparea')
}, { immediate: true, deep: true })
watch(barricade, (value) => {
dealMapLayer(value, '#0000ff', 'barricade')
}, { immediate: true, deep: true })
watch(stationarea, (value) => {
dealDivIcon(value, 'stationarea')
dealMapLayer(value, '#90ee90', 'stationarea')
}, { immediate: true, deep: true })
watch(parkspot, (value) => {
dealDivIcon(value, 'parkspot')
dealMapLayer(value, '#7e8185', 'parkspot')
}, { immediate: true, deep: true })
watch(staticobjs, (value) => {
dealMapLayer(value, '#98a0a0', 'staticobjs')
}, { immediate: true, deep: true })
watch(electronicFence, (value) => {
dealDivIcon(value, 'electronicFence')
dealMapLayer(value, '#d51d20', 'electronicFence')
}, { immediate: true, deep: true })
watch(nextPathinfo, (value) => {
dealMapPath(value, 'nextPath', nextPathAvailable.value === 1 ? '#19ae19' : '#8B4513')
}, { immediate: true, deep: true })
watch(currPathinfo, (value) => {
dealMapPath(value, 'currentPath', '#19ae19')
}, { immediate: true, deep: true })
watch(avoidancePath, (value) => {
dealMapPath(value, 'avoidancePath', 'blue')
}, { immediate: true, deep: true })
watch(vehiclesPositioninfo, (value) => {
dealVehiclePosition(value)
}, {
immediate: true,
deep: true
})
watch(safeObj, (value) => {
Object.keys(value).forEach(item => {
dealSafe(item, value[item])
})
}, {
immediate: true,
deep: true
})
watch(trajObj, (value) => {
Object.keys(value).forEach(item => {
dealTraj(item, value[item])
})
}, {
immediate: true,
deep: true
})
watch(obstacleData, (value) => {
dealObtacleData(value)
}, { immediate: true, deep: true })
watch(deleteVehicles, (data) => {
if (!map) return
if (data && data.length) {
data.forEach(item => {
// map.removeLayer(vehicles[item])
removeLayer(safeTrajs, item)
removeLayer(safeObjects, item)
delete vehicles[item]
initCar()
})
}
}, {
immediate: true
})
watch(() => props.clearSinglePointEnable, (enable) => {
if (!enable) return
isSinglePreview.value = true
singlePaths.forEach(item => map.removeLayer('map',item))
}, { deep: true })
watch([morepoint, morepath], (pointData, pathData) => {
if (isSinglePreview.value && (pointData || pathData)) {
let datas = pointData.concat(pathData)
for (let i = 0; i < datas.length; i++) {
dealSingleDatas(datas[i])
}
}
}, { deep: true })
watch(dynamicPathinfo, (pathData) => {
if (pathData.length > 0) {
for (let i = 0; i < pathData.length; i++) {
dealDynamicDatas(pathData[i])
}
}
}, { deep: true })
watch(deviceId, (value) => {
if (value && map) {
dealMapRotate(currentRotation.value, currentPosition, map.getZoom())
}
}, { deep: true })
function doUnmount() {
// Object.keys(mapLayers).map(layer => map.removeLayer(mapLayers[layer]))
map.remove()
map = null
}
watch(() => props.reloadData, (value) => {
if (value) {
doUnmount()
}
})
onBeforeUnmount(() => {
doUnmount()
})
</script>
<style lang="less" scope>
.map-contain {
height: 100%;
overflow: hidden;
}
#map {
width: 200% !important;
height: 200% !important;
top: -50%;
left: -50%;
background: #171A23;
position: relative !important;
}
.navigate-preview {
background: #4A75A9;
box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.25);
border-radius: 10px;
opacity: 1;
display: flex;
align-items: center;
justify-content: center;
}
.compass,
.navigate-preview {
position: absolute;
width: 4vw;
height: 4vw;
z-index: 999;
}
.compass {
bottom: 88px;
max-width: 60px;
max-height: 60px;
}
.navigate-preview {
bottom: 24px;
max-width: 60px;
max-height: 60px;
}
</style>
<style lang="less">
.icon-node {
width: 120px !important;
white-space: nowrap;
color: #676565;
// padding-left: -2em !important;
z-index: 1;
font-size: 12px !important;
font-family: "Open Sans Regular", "Arial Unicode MS Regular", sans-serif;
text-transform: uppercase;
text-align: center;
-webkit-text-stroke-display: block;
-webkit-text-stroke-width: 1px;
-webkit-text-stroke-color: rgba(33, 33, 33, 0.8);
}
@media screen and (min-width: 1700px) {
.icon-node {
font-size: 18px !important;
}
}
.icon-node-name {
display: inline-block;
transform: scale(.6);
padding-left: -20px !important;
}
.hide {
display: none !important;
}
.middle-line {
// 为svg设置虚线,数字越大,虚线段越长,
// 设置2个参数,参数1: 虚线的长度 参数2: 虚线和虚线之间的间隔, 如果只设置一个参数,说明两个值一样大小
stroke-dasharray: 15 20;
z-index: 999;
}
.leaflet-tooltip {
color: #fff !important;
background-color: rgba(255, 255, 255, 0) !important;
border: 0 !important;
box-shadow: rgba(0, 0, 0, 0);
font-size: 12px !important;
}
.leaflet-control-attribution {
display: none !important;
}
</style>
\ No newline at end of file
<template>
<div class="map-contain">
<canvas id="map" ref="root"></canvas>
<img src="/image/compass.png" class="compass" ref="compass"
:style="`transform: rotateZ(${compassRotationAngle}rad)`" alt="" @click="changeCompass">
<div class="navigate-preview">
<img src="/image/navigate.png" class="navigate" @click="changeNavigate" alt="" />
</div>
</div>
</template>
<script setup>
import { markRaw, onMounted, watch, ref, computed, onBeforeUnmount, nextTick } from 'vue'
import { useMapStore } from '@/store/MapStore.js'
import { useVehicleStore } from '@/store/VehicleStore'
import { storeToRefs } from 'pinia'
import { vehicleScale } from '../js/tools'
import DeckNew from '@/tools/Deck';
import * as turf from '@turf/turf'
const safe_color = '#FFA500'
const BASE_RAD = 1.5707963267948966
const MAP_ZOOM = 17
const LAYER_PROPOITY = {
runablearea: 1,
staticobjs: 2,
diggingarea: 3,
diggingworkarea: 3,
dumparea: 4,
barricade: 5,
electronicFence: 6,
wetArea: 7,
lane: 8,
obstacles: 9,
stationarea: 10,
parkspot: 11,
lanenode: 12,
currPathinfo: 13,
nextPathinfo: 14,
avoidancePath: 15,
traj: 16,
obstacle: 17
}
const vehicles = {}
let ismousedown = false
let ismousemove = false
let resetTime = null
let obstaclePolygons = []
let dynamicPaths = []
const reNavigateTime = 2.5 * 1000
const props = defineProps({
isShowBasic: Boolean,
clearSinglePointEnable: Boolean,
reloadData: Boolean
})
let map = markRaw({})
let currentPosition = markRaw([])
const root = ref(null)
const mapLayers = markRaw({})
const safeObjects = markRaw({})
const safeTrajs = markRaw({})
const singlePaths = markRaw([])
const navigate = ref(true)
const currentRotation = ref(0)
const markerLayerGroupLists = markRaw({})
const isSinglePreview = ref(false)
const compassRotationAngle = ref(0)
const compass = ref(null)
const mapStore = useMapStore()
const mapStoreToRefs = storeToRefs(mapStore)
const {
lanenode,
lane,
runablearea,
centerline,
obstacles,
diggingworkarea,
dumparea,
barricade,
stationarea,
parkspot,
staticobjs,
electronicFence,
morepoint, // 单机循迹单路径
morepath, // 单机循迹多路径
nextPathinfo,
currPathinfo,
nextPathAvailable,
avoidancePath, // 绕障路径
obstacleData,
dynamicPathinfo, // 车辆动态路权信息
} = mapStoreToRefs
const vehicleStore = useVehicleStore()
const vehicleStoreToRefs = storeToRefs(vehicleStore)
const { vehiclesPositioninfo, safeObj, trajObj, paraminfo, deleteVehicles } = vehicleStoreToRefs
const deviceId = computed(() => {
return paraminfo.value.deviceId
})
const emits = defineEmits(['handleSend'])
onMounted(() => {
//阻止鼠标右键
document.oncontextmenu = f => {
event.returnValue = false
}
let currentCoordinate = []
let bool = false
map = new DeckNew({
initialViewState: {
latitude: document.location.mapCenter[0],
longitude: document.location.mapCenter[1],
zoom: MAP_ZOOM,
// pickingRadius:5,
controller: true,
},
controller: true,
// parent: document.getElementById('mapMain'),
canvas: 'map',
//如果deck滚动条滚动或者拖动地图时,不进行地图角度和等级矫正
onInteractionStateChange: f => {
if (!currentPosition) return
if (f.isZooming || f.isDragging) {
navigate.value = false
clearTimeout(resetTime)
resetTime = window.setTimeout(() => {
if (!navigate.value) {
navigate.value = true
dealVehicleRotate()
currentRotation.value = BASE_RAD
clearTimeout(resetTime)
resetTime=null;
}
}, reNavigateTime)
}
}
})
map.setPitch(40)
emits('handleSend', {
type: 'syncMapVersion',
msg: {}
})
})
function changeNavigate() {
navigate.value = true
dealMapRotate(currentRotation.value, currentPosition, map.getZoom())
}
// 指南针
function changeCompass() {
dealVehicleRotate(0)
currentRotation.value = BASE_RAD
if (navigate.value) {
setTimeout(() => {
dealVehicleRotate()
}, 3 * 1000)
}
}
function dealVehicleRotate(rotate) {
let keys = Object.keys(vehicles)
let target = keys.find(item => item === deviceId.value)
let currentTarget = vehicles[target]
let vehicleHeading = BASE_RAD
let currentOldHeading = currentTarget && currentTarget.options.vehicleHeading
if (typeof rotate === 'number') {
dealMapRotate(0, currentPosition, map.getZoom())
} else {
vehicleHeading = currentOldHeading
currentRotation.value = vehicleHeading
dealMapRotate(vehicleHeading, currentPosition, map.getZoom())
}
}
function dealMapLayer(value, color, layerName) {
if (!value || !map) return
let result = JSON.parse(value)
if (!result) return
let attr = {};
if (layerName === 'barricade') {
attr = {
getLineColor: map.convertColor('#0066ff', 1),
// width: 5
}
} else {
attr = {
getLineColor: feature => {
return layerName === 'lane' ? map.convertColor('#eee', 0.5) : map.convertColor(feature.properties.color, 1)
},
getFillColor: feature => {
let opacity = 0.7;
if (layerName === 'runablearea') {
opacity = 0.5
}
return layerName === 'electronicFence' ? map.convertColor(feature.properties.color, opacity) : color ? map.convertColor(color, opacity) : map.convertColor(feature.properties.color, opacity)
}
}
}
map.createGeoJsonLayer(result, attr, layerName)
mapStore.setData(layerName, null)
}
function dealMapPath(value, layerName, color) {
if (value && value.length) {
let data = JSON.parse(JSON.stringify(value))
let path = map.createPathLayer([
{
path: [...map.coorReverse(data)],
name: layerName,
}
], {
getColor: f => map.convertColor('#ffff00'),
}, layerName)
mapLayers[layerName] = layerName
const lineGeo = turf.lineString([...map.coorReverse(JSON.parse(JSON.stringify(data)))])
let bufferLine = turf.buffer(lineGeo, 6.5, { units: "meters" })
const obj = {
type: "FeatureCollection",
features: [bufferLine]
}
const attr = {
getFillColor: f => map.convertColor(color, 0.6),
getLineColor: f => map.convertColor(color, 1)
}
// map.setLayerSortName('bufferLayer', layerName + 'Buffer')
map.createGeoJsonLayer(obj, attr, layerName + 'Buffer')
mapLayers[`${layerName}Buffer`] = `${layerName}Buffer`
}
}
function dealDivIcon(value, layerName) {
if (!value || !map) return
let result = JSON.parse(value)
if (!result) return
const { features } = result
for (let i = 0; i < features.length; i++) {
let feature = features[i]
let { name, id } = feature.properties
let { coordinates } = feature.geometry
let markerCoor = null
if (layerName === 'lanenode') {
markerCoor = [coordinates[1], coordinates[0]]
} else {
let center = turf.center(feature)
markerCoor = [center.geometry.coordinates[1], center.geometry.coordinates[0]]
}
let texData = {
name: name,
id: id,
coordinates: [markerCoor[1], markerCoor[0], 1],
}
if (markerLayerGroupLists[`${layerName}${id}`]) {
markerLayerGroupLists[`${layerName}${id}`] = texData
} else {
markerLayerGroupLists[`${layerName}${id}`] = texData
}
}
map.createTextLayer([...Object.values(markerLayerGroupLists)], {
getSize: 15
}, 'text')
// map.setLayerSortName('marker', 'marker')
map.setLayerSortName('markerLayer', 'marker')
map.creatCircle(Object.values(markerLayerGroupLists), {
getFillColor: f => map.convertColor('#2aa1fa', 1),
getLineColor: f => map.convertColor('#2aa1fa', 0.5),
getLineWidth: 0.5,
radius: 1.5
}, 'marker')
mapStore.setData(layerName, null)
}
function removeLayer(obj, vehicleID) {
if (obj[vehicleID]) {
for (let item in obj[vehicleID]) {
map.removeLayer('map', obj[vehicleID][item])
}
}
}
function dealSafe(vehicleID, safe) {
if (!map) return
const { enable, data, dealedData, vehicleType, vehicleLatitude, vehicleLongtitude } = safe
removeLayer(safeObjects, vehicleID)
safeObjects[vehicleID] = {}
if (!enable) return
let safeType = [1, 20, 21].includes(vehicleType) ? 'circle' : 'rectangle'
let zIndex = 16
for (let i = 0; i < dealedData.length; i++) {
let item = JSON.parse(JSON.stringify(dealedData[i]))
let layer = safeType === 'rectangle' ? map.creatPolygon({
coordinates: map.coorReverse(item),
}, {
getFillColor: d => map.convertColor(safe_color,0.4),
getLineColor: d => map.convertColor(safe_color),
getLineWidth: 0.4
}, vehicleID+i) : map.creatCircle([vehicleLongtitude, vehicleLatitude], {
getFillColor: f => map.convertColor(safe_color,0.4),
getLineColor: f => map.convertColor(safe_color),
getLineWidth: 0.4,
radius: data[i]
}, vehicleID+i)
safeObjects[vehicleID][i] = vehicleID+i
}
}
function dealTraj(vehicleID, traj) {
if (!traj || !map) return
const { trajPathWid, radius, dealedData, vehicleType, vehicleLatitude, vehicleLongtitude } = traj
removeLayer(safeTrajs, vehicleID)
safeTrajs[vehicleID] = {}
// if (!dealedData) return
// if ((dealedData && !dealedData.length) || !radius)) return
if ([1, 20, 21].includes(vehicleType && !radius)) return;
const zIndex = LAYER_PROPOITY['traj']
if ([1, 20, 21].includes(vehicleType) && radius) {
map.creatCircle([vehicleLongtitude, vehicleLatitude], {
getFillColor: f => map.convertColor('#FFA500'),
getLineColor: f => map.convertColor('#FFA500'),
getLineWidth: 1,
radius: radius
}, vehicleID)
safeTrajs[vehicleID]['circle'] = vehicleID
} else {
if (dealedData && !dealedData.length) return;
const lineGeo = turf.lineString([...map.coorReverse(JSON.parse(JSON.stringify(dealedData)))])
// safeTrajs[vehicleID]['path'] = path
let bufferLine = turf.buffer(lineGeo, trajPathWid / 2, { units: "meters" })
const data = {
type: "FeatureCollection",
features: [bufferLine]
}
const attr = {
getFillColor: f => map.convertColor(safe_color, 0.4),
getLineColor: f => map.convertColor(safe_color, 1)
}
safeTrajs[vehicleID]['pathBuffer'] = vehicleID + 'Buffer'
map.setLayerSortName('bufferLayer', vehicleID + 'Buffer', 1)
map.createGeoJsonLayer(data, attr, vehicleID + 'Buffer')
}
}
function dealMapRotate(rotationAngle, center, zoom) {
let rotate = 0
if (rotationAngle) {
rotate = turf.radiansToDegrees(rotationAngle - BASE_RAD)
}
if (compass.value) {
compassRotationAngle.value = rotationAngle
map.setRotation(rotate)
}
center && center.length && map.flyTo(center, zoom, { animate: false })
}
function dealVehiclePosition(value) {
if (!map || !value.length) return
let zoom = map.getZoom()
for (let i = 0; i < value.length; i++) {
const item = value[i]
const { vehicleLatitude, vehicleLongtitude, vehicleHeading, vehicleID, image } = item
let vehiclePosition = [vehicleLatitude, vehicleLongtitude]
let baseObj = {
name: vehicleID,
rotate: vehicleHeading,
coordinates: [vehicleLongtitude, vehicleLatitude],
image: image,
options: {
vehicleHeading: vehicleHeading
}
}
if (vehicles[vehicleID]) {
vehicles[vehicleID] = baseObj
} else {
vehicles[vehicleID] = baseObj
}
if (vehicleID === deviceId.value) {
currentPosition = vehiclePosition
if (navigate.value) {
currentRotation.value = vehicleHeading
dealMapRotate(vehicleHeading, vehiclePosition, zoom <= MAP_ZOOM ? MAP_ZOOM : zoom)
}
}
}
initCar()
}
function initCar(){
map.clearLayer('car')
const nameText = JSON.parse(JSON.stringify(Object.values(vehicles))).map(item => {
item.coordinates = [item.coordinates[0], item.coordinates[1], 10]
return item
})
map.createTextLayer(nameText, {
getSize: 15,
getColor: f => [255, 255, 255, 255],
fontWeight: 400,
fontSettings: {
buffer: 2,
sdf: true,
smoothing: 0.5
},
}, 'carName')
let car = {};
Object.values(vehicles).forEach(item => {
if (car.hasOwnProperty(item.image)) {
car[item.image].push(item)
} else {
car[item.image] = [item]
}
})
for (let key in car) {
// map.setLayerSortName('carLayer', key)
let imageURL = `image/${key}.glb`
map.createCarModel(car[key], { scenegraph: imageURL }, key)
}
}
function dealSingleDatas(datas) {
const { color, coor } = datas
let data = JSON.parse(JSON.stringify(value))
const lineGeo = turf.lineString([...map.coorReverse(JSON.parse(JSON.stringify(data)))])
// safeTrajs[vehicleID]['path'] = path
let bufferLine = turf.buffer(lineGeo, 2, { units: "meters" })
const obj = {
type: "FeatureCollection",
features: [bufferLine]
}
const attr = {
getFillColor: f => map.convertColor(color, 0.4),
getLineColor: f => map.convertColor(color, 1)
}
map.createGeoJsonLayer(obj, attr, layerName)
singlePaths.push(layerName)
}
function dealObtacleData(value) {
if (value && value.length) {
for (let i = 0; i < value.length; i++) {
let obstacle = value[i]
let { typeColor, coordinate, centerLon, centerLat, centerRadius, centerColor } = obstacle
map.creatPolygon({
coordinates: JSON.parse(JSON.stringify(coordinate)),
}, {
getFillColor: d => map.convertColor(typeColor),
getLineColor: d => map.convertColor(typeColor),
getLineWidth: 3
}, 'obstacle')
map.setLayerSortName('buffer', 'obstacleBuffer')
map.creatCircle([centerLon, centerLat], {
getFillColor: f => map.convertColor(centerColor, 0.5),
getLineColor: f => map.convertColor(centerColor, 0.5),
getLineWidth: 0,
radius: centerRadius
}, 'obstacleBuffer')
}
}
}
function dealDynamicDatas(datas) {
let name = 'dynamicLine';
const { color, path } = datas
const lineGeo = turf.lineString([...map.coorReverse(JSON.parse(JSON.stringify(path)))])
// safeTrajs[vehicleID]['path'] = path
let bufferLine = turf.buffer(lineGeo, 2, { units: "meters" })
const obj = {
type: "FeatureCollection",
features: [bufferLine]
}
const attr = {
// getFillColor: f => map.convertColor(color, 0.3),
getLineColor: f => map.convertColor(color, 0.3),
getLineWidth: 30
}
map.createGeoJsonLayer(obj, attr, name)
}
// 直接监听props.isShowBasic 不会触发
watch(() => props.isShowBasic, () => {
nextTick(() => {
// map.invalidateSize(true)
})
})
watch(lanenode, (value) => {
dealDivIcon(value, 'lanenode', '#ff0000')
}, { immediate: true, deep: true })
watch(lane, (value) => {
dealMapLayer(value, '#fff', 'lane')
}, { immediate: true, deep: true })
watch(runablearea, (value) => {
dealMapLayer(value, '#98a0a0', 'runablearea')
}, { immediate: true, deep: true })
watch(centerline, (value) => {
dealMapLayer(value, '#eee', 'centerline')
}, { immediate: true, deep: true })
watch(obstacles, (value) => {
dealDivIcon(value, 'obstacles')
dealMapLayer(value, '#6f9bdd', 'obstacles')
}, { immediate: true, deep: true })
watch(diggingworkarea, (value) => {
dealDivIcon(value, 'diggingworkarea')
dealMapLayer(value, '#886e26', 'diggingworkarea')
}, { immediate: true, deep: true })
watch(dumparea, (value) => {
dealDivIcon(value, 'dumparea')
dealMapLayer(value, '#886e26', 'dumparea')
}, { immediate: true, deep: true })
watch(barricade, (value) => {
dealMapLayer(value, '#0000ff', 'barricade')
}, { immediate: true, deep: true })
watch(stationarea, (value) => {
dealDivIcon(value, 'stationarea')
dealMapLayer(value, '#90ee90', 'stationarea')
}, { immediate: true, deep: true })
watch(parkspot, (value) => {
dealDivIcon(value, 'parkspot')
dealMapLayer(value, '#7e8185', 'parkspot')
}, { immediate: true, deep: true })
watch(staticobjs, (value) => {
dealMapLayer(value, '#98a0a0', 'staticobjs')
}, { immediate: true, deep: true })
watch(electronicFence, (value) => {
dealDivIcon(value, 'electronicFence')
dealMapLayer(value, '#d51d20', 'electronicFence')
}, { immediate: true, deep: true })
watch(nextPathinfo, (value) => {
dealMapPath(value, 'nextPath', nextPathAvailable.value === 1 ? '#19ae19' : '#8B4513')
}, { immediate: true, deep: true })
watch(currPathinfo, (value) => {
dealMapPath(value, 'currentPath', '#19ae19')
}, { immediate: true, deep: true })
watch(avoidancePath, (value) => {
dealMapPath(value, 'avoidancePath', 'blue')
}, { immediate: true, deep: true })
watch(vehiclesPositioninfo, (value) => {
dealVehiclePosition(value)
}, {
immediate: true,
deep: true
})
watch(safeObj, (value) => {
Object.keys(value).forEach(item => {
dealSafe(item, value[item])
})
}, {
immediate: true,
deep: true
})
watch(trajObj, (value) => {
Object.keys(value).forEach(item => {
dealTraj(item, value[item])
})
}, {
immediate: true,
deep: true
})
watch(obstacleData, (value) => {
dealObtacleData(value)
}, { immediate: true, deep: true })
watch(deleteVehicles, (data) => {
if (!map) return
if (data && data.length) {
data.forEach(item => {
// map.removeLayer(vehicles[item])
removeLayer(safeTrajs, item)
removeLayer(safeObjects, item)
delete vehicles[item]
initCar()
})
}
}, {
immediate: true
})
watch(() => props.clearSinglePointEnable, (enable) => {
if (!enable) return
isSinglePreview.value = true
singlePaths.forEach(item => map.removeLayer('map',item))
}, { deep: true })
watch([morepoint, morepath], (pointData, pathData) => {
if (isSinglePreview.value && (pointData || pathData)) {
let datas = pointData.concat(pathData)
for (let i = 0; i < datas.length; i++) {
dealSingleDatas(datas[i])
}
}
}, { deep: true })
watch(dynamicPathinfo, (pathData) => {
if (pathData.length > 0) {
for (let i = 0; i < pathData.length; i++) {
dealDynamicDatas(pathData[i])
}
}
}, { deep: true })
watch(deviceId, (value) => {
if (value && map) {
dealMapRotate(currentRotation.value, currentPosition, map.getZoom())
}
}, { deep: true })
function doUnmount() {
// Object.keys(mapLayers).map(layer => map.removeLayer(mapLayers[layer]))
map.remove()
map = null
}
watch(() => props.reloadData, (value) => {
if (value) {
doUnmount()
}
})
onBeforeUnmount(() => {
doUnmount()
})
</script>
<style lang="less" scope>
.map-contain {
height: 100%;
overflow: hidden;
}
#map {
width: 200% !important;
height: 200% !important;
top: -50%;
left: -50%;
background: #171A23;
position: relative !important;
}
.navigate-preview {
background: #4A75A9;
box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.25);
border-radius: 10px;
opacity: 1;
display: flex;
align-items: center;
justify-content: center;
}
.compass,
.navigate-preview {
position: absolute;
width: 4vw;
height: 4vw;
z-index: 999;
}
.compass {
bottom: 88px;
max-width: 60px;
max-height: 60px;
}
.navigate-preview {
bottom: 24px;
max-width: 60px;
max-height: 60px;
}
</style>
<style lang="less">
.icon-node {
width: 120px !important;
white-space: nowrap;
color: #676565;
// padding-left: -2em !important;
z-index: 1;
font-size: 12px !important;
font-family: "Open Sans Regular", "Arial Unicode MS Regular", sans-serif;
text-transform: uppercase;
text-align: center;
-webkit-text-stroke-display: block;
-webkit-text-stroke-width: 1px;
-webkit-text-stroke-color: rgba(33, 33, 33, 0.8);
}
@media screen and (min-width: 1700px) {
.icon-node {
font-size: 18px !important;
}
}
.icon-node-name {
display: inline-block;
transform: scale(.6);
padding-left: -20px !important;
}
.hide {
display: none !important;
}
.middle-line {
// 为svg设置虚线,数字越大,虚线段越长,
// 设置2个参数,参数1: 虚线的长度 参数2: 虚线和虚线之间的间隔, 如果只设置一个参数,说明两个值一样大小
stroke-dasharray: 15 20;
z-index: 999;
}
.leaflet-tooltip {
color: #fff !important;
background-color: rgba(255, 255, 255, 0) !important;
border: 0 !important;
box-shadow: rgba(0, 0, 0, 0);
font-size: 12px !important;
}
.leaflet-control-attribution {
display: none !important;
}
</style>
\ No newline at end of file
<template>
<div class="map-contain">
<canvas id="map" ref="root"></canvas>
<img src="/image/compass.png" class="compass" ref="compass"
:style="`transform: rotateZ(${compassRotationAngle}rad)`" alt="" @click="changeCompass">
<div class="navigate-preview">
<img src="/image/navigate.png" class="navigate" @click="changeNavigate" alt="" />
</div>
</div>
</template>
<script setup>
import { markRaw, onMounted, watch, ref, computed, onBeforeUnmount, nextTick } from 'vue'
import { useMapStore } from '@/store/MapStore.js'
import { useVehicleStore } from '@/store/VehicleStore'
import { storeToRefs } from 'pinia'
import { vehicleScale } from '../js/tools'
import DeckNew from '@/tools/Deck';
import * as turf from '@turf/turf'
const safe_color = '#FFA500'
const BASE_RAD = 1.5707963267948966
const MAP_ZOOM = 17
const LAYER_PROPOITY = {
runablearea: 1,
staticobjs: 2,
diggingarea: 3,
diggingworkarea: 3,
dumparea: 4,
barricade: 5,
electronicFence: 6,
wetArea: 7,
lane: 8,
obstacles: 9,
stationarea: 10,
parkspot: 11,
lanenode: 12,
currPathinfo: 13,
nextPathinfo: 14,
avoidancePath: 15,
traj: 16,
obstacle: 17
}
const vehicles = {}
let ismousedown = false
let ismousemove = false
let resetTime = null
let obstaclePolygons = []
let dynamicPaths = []
const reNavigateTime = 2.5 * 1000
const props = defineProps({
isShowBasic: Boolean,
clearSinglePointEnable: Boolean,
reloadData: Boolean
})
let map = markRaw({})
let currentPosition = markRaw([])
const root = ref(null)
const mapLayers = markRaw({})
const safeObjects = markRaw({})
const safeTrajs = markRaw({})
const singlePaths = markRaw([])
const navigate = ref(true)
const currentRotation = ref(0)
const markerLayerGroupLists = markRaw({})
const isSinglePreview = ref(false)
const compassRotationAngle = ref(0)
const compass = ref(null)
const mapStore = useMapStore()
const mapStoreToRefs = storeToRefs(mapStore)
const {
lanenode,
lane,
runablearea,
centerline,
obstacles,
diggingworkarea,
dumparea,
barricade,
stationarea,
parkspot,
staticobjs,
electronicFence,
morepoint, // 单机循迹单路径
morepath, // 单机循迹多路径
nextPathinfo,
currPathinfo,
nextPathAvailable,
avoidancePath, // 绕障路径
obstacleData,
dynamicPathinfo, // 车辆动态路权信息
} = mapStoreToRefs
const vehicleStore = useVehicleStore()
const vehicleStoreToRefs = storeToRefs(vehicleStore)
const { vehiclesPositioninfo, safeObj, trajObj, paraminfo, deleteVehicles } = vehicleStoreToRefs
const deviceId = computed(() => {
return paraminfo.value.deviceId
})
const emits = defineEmits(['handleSend'])
onMounted(() => {
//阻止鼠标右键
document.oncontextmenu = f => {
event.returnValue = false
}
let currentCoordinate = []
let bool = false
map = new DeckNew({
initialViewState: {
latitude: document.location.mapCenter[0],
longitude: document.location.mapCenter[1],
zoom: MAP_ZOOM,
// pickingRadius:5,
controller: true,
},
controller: true,
// parent: document.getElementById('mapMain'),
canvas: 'map',
//如果deck滚动条滚动或者拖动地图时,不进行地图角度和等级矫正
onInteractionStateChange: f => {
if (!currentPosition) return
if (f.isZooming || f.isDragging) {
navigate.value = false
clearTimeout(resetTime)
resetTime = window.setTimeout(() => {
if (!navigate.value) {
navigate.value = true
dealVehicleRotate()
currentRotation.value = BASE_RAD
clearTimeout(resetTime)
resetTime = null;
}
}, reNavigateTime)
}
}
})
map.setPitch(40)
emits('handleSend', {
type: 'syncMapVersion',
msg: {}
})
})
function changeNavigate() {
navigate.value = true
dealMapRotate(currentRotation.value, currentPosition, map.getZoom())
}
// 指南针
function changeCompass() {
dealVehicleRotate(0)
currentRotation.value = BASE_RAD
if (navigate.value) {
setTimeout(() => {
dealVehicleRotate()
}, 3 * 1000)
}
}
function dealVehicleRotate(rotate) {
let keys = Object.keys(vehicles)
let target = keys.find(item => item === deviceId.value)
let currentTarget = vehicles[target]
let vehicleHeading = BASE_RAD
let currentOldHeading = currentTarget && currentTarget.options.vehicleHeading
if (typeof rotate === 'number') {
dealMapRotate(0, currentPosition, map.getZoom())
} else {
vehicleHeading = currentOldHeading
currentRotation.value = vehicleHeading
dealMapRotate(vehicleHeading, currentPosition, map.getZoom())
}
}
function dealMapLayer(value, color, layerName) {
if (!value || !map) return
let result = JSON.parse(value)
if (!result) return
let attr = {};
if (layerName === 'barricade') {
attr = {
getLineColor: map.convertColor('#0066ff', 1),
// width: 5
}
} else {
attr = {
getLineColor: feature => {
return layerName === 'lane' ? map.convertColor('#eee', 0.5) : map.convertColor(feature.properties.color, 1)
},
getFillColor: feature => {
let opacity = 0.7;
if (layerName === 'runablearea') {
opacity = 0.5
}
return layerName === 'electronicFence' ? map.convertColor(feature.properties.color, opacity) : color ? map.convertColor(color, opacity) : map.convertColor(feature.properties.color, opacity)
}
}
}
map.createGeoJsonLayer(result, attr, layerName)
mapStore.setData(layerName, null)
}
function dealMapPath(value, layerName, color) {
if (value && value.length) {
let data = JSON.parse(JSON.stringify(value))
let path = map.createPathLayer([
{
path: [...map.coorReverse(data)],
name: layerName,
}
], {
getColor: f => map.convertColor('#ffff00'),
}, layerName)
mapLayers[layerName] = layerName
const lineGeo = turf.lineString([...map.coorReverse(JSON.parse(JSON.stringify(data)))])
let bufferLine = turf.buffer(lineGeo, 6.5, { units: "meters" })
const obj = {
type: "FeatureCollection",
features: [bufferLine]
}
const attr = {
getFillColor: f => map.convertColor(color, 0.6),
getLineColor: f => map.convertColor(color, 1)
}
// map.setLayerSortName('bufferLayer', layerName + 'Buffer')
map.createGeoJsonLayer(obj, attr, layerName + 'Buffer')
mapLayers[`${layerName}Buffer`] = `${layerName}Buffer`
}
}
function dealDivIcon(value, layerName) {
if (!value || !map) return
let result = JSON.parse(value)
if (!result) return
const { features } = result
for (let i = 0; i < features.length; i++) {
let feature = features[i]
let { name, id } = feature.properties
let { coordinates } = feature.geometry
let markerCoor = null
if (layerName === 'lanenode') {
markerCoor = [coordinates[1], coordinates[0]]
} else {
let center = turf.center(feature)
markerCoor = [center.geometry.coordinates[1], center.geometry.coordinates[0]]
}
let texData = {
name: name,
id: id,
coordinates: [markerCoor[1], markerCoor[0], 1],
}
if (markerLayerGroupLists[`${layerName}${id}`]) {
markerLayerGroupLists[`${layerName}${id}`] = texData
} else {
markerLayerGroupLists[`${layerName}${id}`] = texData
}
}
map.createTextLayer([...Object.values(markerLayerGroupLists)], {
getSize: 15
}, 'text')
// map.setLayerSortName('marker', 'marker')
map.setLayerSortName('markerLayer', 'marker')
map.creatCircle(Object.values(markerLayerGroupLists), {
getFillColor: f => map.convertColor('#2aa1fa', 1),
getLineColor: f => map.convertColor('#2aa1fa', 0.5),
getLineWidth: 0.5,
radius: 1.5
}, 'marker')
mapStore.setData(layerName, null)
}
function removeLayer(obj, vehicleID) {
if (obj[vehicleID]) {
for (let item in obj[vehicleID]) {
map.removeLayer('map', obj[vehicleID][item])
}
}
}
function dealSafe(vehicleID, safe) {
if (!map) return
const { enable, data, dealedData, vehicleType, vehicleLatitude, vehicleLongtitude } = safe
removeLayer(safeObjects, vehicleID)
safeObjects[vehicleID] = {}
if (!enable) return
let safeType = [1, 20, 21].includes(vehicleType) ? 'circle' : 'rectangle'
let zIndex = 16
for (let i = 0; i < dealedData.length; i++) {
let item = JSON.parse(JSON.stringify(dealedData[i]))
if (safeType === 'rectangle') {
map.creatPolygon({
coordinates: map.coorReverse(item),
}, {
getFillColor: d => map.convertColor(safe_color, 0.4),
getLineColor: d => map.convertColor(safe_color),
getLineWidth: 0.4
}, vehicleID + i)
} else {
map.creatCircle([vehicleLongtitude, vehicleLatitude], {
getFillColor: f => map.convertColor(safe_color, 0.4),
getLineColor: f => map.convertColor(safe_color),
getLineWidth: 0.4,
radius: data[i]
}, vehicleID + i)
}
safeObjects[vehicleID][i] = vehicleID + i
}
}
function dealTraj(vehicleID, traj) {
if (!traj || !map) return
const { trajPathWid, radius, dealedData, vehicleType, vehicleLatitude, vehicleLongtitude } = traj
removeLayer(safeTrajs, vehicleID)
safeTrajs[vehicleID] = {}
// if (!dealedData) return
// if ((dealedData && !dealedData.length) || !radius)) return
if ([1, 20, 21].includes(vehicleType && !radius)) return;
const zIndex = LAYER_PROPOITY['traj']
if ([1, 20, 21].includes(vehicleType) && radius) {
map.creatCircle([vehicleLongtitude, vehicleLatitude], {
getFillColor: f => map.convertColor('#FFA500'),
getLineColor: f => map.convertColor('#FFA500'),
getLineWidth: 1,
radius: radius
}, vehicleID)
safeTrajs[vehicleID]['circle'] = vehicleID
} else {
if (dealedData && !dealedData.length) return;
const lineGeo = turf.lineString([...map.coorReverse(JSON.parse(JSON.stringify(dealedData)))])
// safeTrajs[vehicleID]['path'] = path
let bufferLine = turf.buffer(lineGeo, trajPathWid / 2, { units: "meters" })
const data = {
type: "FeatureCollection",
features: [bufferLine]
}
const attr = {
getFillColor: f => map.convertColor(safe_color, 0.4),
getLineColor: f => map.convertColor(safe_color, 1)
}
safeTrajs[vehicleID]['pathBuffer'] = vehicleID + 'Buffer'
map.setLayerSortName('bufferLayer', vehicleID + 'Buffer', 1)
map.createGeoJsonLayer(data, attr, vehicleID + 'Buffer')
}
}
function dealMapRotate(rotationAngle, center, zoom) {
let rotate = 0
if (rotationAngle) {
rotate = turf.radiansToDegrees(rotationAngle - BASE_RAD)
}
if (compass.value) {
compassRotationAngle.value = rotationAngle
map.setRotation(rotate)
}
center && center.length && map.flyTo(center, zoom, { animate: false })
}
function dealVehiclePosition(value) {
if (!map || !value.length) return
let zoom = map.getZoom()
for (let i = 0; i < value.length; i++) {
const item = value[i]
const { vehicleLatitude, vehicleLongtitude, vehicleHeading, vehicleID, image } = item
let vehiclePosition = [vehicleLatitude, vehicleLongtitude]
let baseObj = {
name: vehicleID,
rotate: vehicleHeading,
coordinates: [vehicleLongtitude, vehicleLatitude],
image: image,
options: {
vehicleHeading: vehicleHeading
}
}
if (vehicles[vehicleID]) {
vehicles[vehicleID] = baseObj
} else {
vehicles[vehicleID] = baseObj
}
if (vehicleID === deviceId.value) {
currentPosition = vehiclePosition
if (navigate.value) {
currentRotation.value = vehicleHeading
dealMapRotate(vehicleHeading, vehiclePosition, zoom <= MAP_ZOOM ? MAP_ZOOM : zoom)
}
}
}
initCar()
}
function initCar() {
map.clearLayer('car')
const nameText = JSON.parse(JSON.stringify(Object.values(vehicles))).map(item => {
item.coordinates = [item.coordinates[0], item.coordinates[1], 10]
return item
})
map.createTextLayer(nameText, {
getSize: 15,
getColor: f => [255, 255, 255, 255],
fontWeight: 400,
fontSettings: {
buffer: 2,
sdf: true,
smoothing: 0.5
},
}, 'carName')
let car = {};
Object.values(vehicles).forEach(item => {
if (car.hasOwnProperty(item.image)) {
car[item.image].push(item)
} else {
car[item.image] = [item]
}
})
for (let key in car) {
// map.setLayerSortName('carLayer', key)
let imageURL = `image/${key}.glb`
map.createCarModel(car[key], { scenegraph: imageURL }, key)
}
}
function dealSingleDatas(datas) {
const { color, coor } = datas
let data = JSON.parse(JSON.stringify(value))
const lineGeo = turf.lineString([...map.coorReverse(JSON.parse(JSON.stringify(data)))])
// safeTrajs[vehicleID]['path'] = path
let bufferLine = turf.buffer(lineGeo, 2, { units: "meters" })
const obj = {
type: "FeatureCollection",
features: [bufferLine]
}
const attr = {
getFillColor: f => map.convertColor(color, 0.4),
getLineColor: f => map.convertColor(color, 1)
}
map.createGeoJsonLayer(obj, attr, layerName)
singlePaths.push(layerName)
}
function dealObtacleData(value) {
if (value && value.length) {
for (let i = 0; i < value.length; i++) {
let obstacle = value[i]
let { typeColor, coordinate, centerLon, centerLat, centerRadius, centerColor } = obstacle
map.creatPolygon({
coordinates: JSON.parse(JSON.stringify(coordinate)),
}, {
getFillColor: d => map.convertColor(typeColor),
getLineColor: d => map.convertColor(typeColor),
getLineWidth: 3
}, 'obstacle')
map.setLayerSortName('buffer', 'obstacleBuffer')
map.creatCircle([centerLon, centerLat], {
getFillColor: f => map.convertColor(centerColor, 0.5),
getLineColor: f => map.convertColor(centerColor, 0.5),
getLineWidth: 0,
radius: centerRadius
}, 'obstacleBuffer')
}
}
}
function dealDynamicDatas(datas) {
let name = 'dynamicLine';
const { color, path } = datas
const lineGeo = turf.lineString([...map.coorReverse(JSON.parse(JSON.stringify(path)))])
// safeTrajs[vehicleID]['path'] = path
let bufferLine = turf.buffer(lineGeo, 2, { units: "meters" })
const obj = {
type: "FeatureCollection",
features: [bufferLine]
}
const attr = {
// getFillColor: f => map.convertColor(color, 0.3),
getLineColor: f => map.convertColor(color, 0.3),
getLineWidth: 30
}
map.createGeoJsonLayer(obj, attr, name)
}
// 直接监听props.isShowBasic 不会触发
watch(() => props.isShowBasic, () => {
nextTick(() => {
// map.invalidateSize(true)
})
})
watch(lanenode, (value) => {
dealDivIcon(value, 'lanenode', '#ff0000')
}, { immediate: true, deep: true })
watch(lane, (value) => {
dealMapLayer(value, '#fff', 'lane')
}, { immediate: true, deep: true })
watch(runablearea, (value) => {
dealMapLayer(value, '#98a0a0', 'runablearea')
}, { immediate: true, deep: true })
watch(centerline, (value) => {
dealMapLayer(value, '#eee', 'centerline')
}, { immediate: true, deep: true })
watch(obstacles, (value) => {
dealDivIcon(value, 'obstacles')
dealMapLayer(value, '#6f9bdd', 'obstacles')
}, { immediate: true, deep: true })
watch(diggingworkarea, (value) => {
dealDivIcon(value, 'diggingworkarea')
dealMapLayer(value, '#886e26', 'diggingworkarea')
}, { immediate: true, deep: true })
watch(dumparea, (value) => {
dealDivIcon(value, 'dumparea')
dealMapLayer(value, '#886e26', 'dumparea')
}, { immediate: true, deep: true })
watch(barricade, (value) => {
dealMapLayer(value, '#0000ff', 'barricade')
}, { immediate: true, deep: true })
watch(stationarea, (value) => {
dealDivIcon(value, 'stationarea')
dealMapLayer(value, '#90ee90', 'stationarea')
}, { immediate: true, deep: true })
watch(parkspot, (value) => {
dealDivIcon(value, 'parkspot')
dealMapLayer(value, '#7e8185', 'parkspot')
}, { immediate: true, deep: true })
watch(staticobjs, (value) => {
dealMapLayer(value, '#98a0a0', 'staticobjs')
}, { immediate: true, deep: true })
watch(electronicFence, (value) => {
dealDivIcon(value, 'electronicFence')
dealMapLayer(value, '#d51d20', 'electronicFence')
}, { immediate: true, deep: true })
watch(nextPathinfo, (value) => {
dealMapPath(value, 'nextPath', nextPathAvailable.value === 1 ? '#19ae19' : '#8B4513')
}, { immediate: true, deep: true })
watch(currPathinfo, (value) => {
dealMapPath(value, 'currentPath', '#19ae19')
}, { immediate: true, deep: true })
watch(avoidancePath, (value) => {
dealMapPath(value, 'avoidancePath', 'blue')
}, { immediate: true, deep: true })
watch(vehiclesPositioninfo, (value) => {
dealVehiclePosition(value)
}, {
immediate: true,
deep: true
})
watch(safeObj, (value) => {
Object.keys(value).forEach(item => {
dealSafe(item, value[item])
})
}, {
immediate: true,
deep: true
})
watch(trajObj, (value) => {
Object.keys(value).forEach(item => {
dealTraj(item, value[item])
})
}, {
immediate: true,
deep: true
})
watch(obstacleData, (value) => {
dealObtacleData(value)
}, { immediate: true, deep: true })
watch(deleteVehicles, (data) => {
if (!map) return
if (data && data.length) {
data.forEach(item => {
// map.removeLayer(vehicles[item])
removeLayer(safeTrajs, item)
removeLayer(safeObjects, item)
delete vehicles[item]
initCar()
})
}
}, {
immediate: true
})
watch(() => props.clearSinglePointEnable, (enable) => {
if (!enable) return
isSinglePreview.value = true
singlePaths.forEach(item => map.removeLayer('map', item))
}, { deep: true })
watch([morepoint, morepath], (pointData, pathData) => {
if (isSinglePreview.value && (pointData || pathData)) {
let datas = pointData.concat(pathData)
for (let i = 0; i < datas.length; i++) {
dealSingleDatas(datas[i])
}
}
}, { deep: true })
watch(dynamicPathinfo, (pathData) => {
if (pathData.length > 0) {
for (let i = 0; i < pathData.length; i++) {
dealDynamicDatas(pathData[i])
}
}
}, { deep: true })
watch(deviceId, (value) => {
if (value && map) {
dealMapRotate(currentRotation.value, currentPosition, map.getZoom())
}
}, { deep: true })
function doUnmount() {
// Object.keys(mapLayers).map(layer => map.removeLayer(mapLayers[layer]))
map.remove()
map = null
}
watch(() => props.reloadData, (value) => {
if (value) {
doUnmount()
}
})
onBeforeUnmount(() => {
doUnmount()
})
</script>
<style lang="less" scope>
.map-contain {
height: 100%;
overflow: hidden;
}
#map {
width: 200% !important;
height: 200% !important;
top: -50%;
left: -50%;
background: #171A23;
position: relative !important;
}
.navigate-preview {
background: #4A75A9;
box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.25);
border-radius: 10px;
opacity: 1;
display: flex;
align-items: center;
justify-content: center;
}
.compass,
.navigate-preview {
position: absolute;
width: 4vw;
height: 4vw;
z-index: 999;
}
.compass {
bottom: 88px;
max-width: 60px;
max-height: 60px;
}
.navigate-preview {
bottom: 24px;
max-width: 60px;
max-height: 60px;
}
</style>
<style lang="less">
.icon-node {
width: 120px !important;
white-space: nowrap;
color: #676565;
// padding-left: -2em !important;
z-index: 1;
font-size: 12px !important;
font-family: "Open Sans Regular", "Arial Unicode MS Regular", sans-serif;
text-transform: uppercase;
text-align: center;
-webkit-text-stroke-display: block;
-webkit-text-stroke-width: 1px;
-webkit-text-stroke-color: rgba(33, 33, 33, 0.8);
}
@media screen and (min-width: 1700px) {
.icon-node {
font-size: 18px !important;
}
}
.icon-node-name {
display: inline-block;
transform: scale(.6);
padding-left: -20px !important;
}
.hide {
display: none !important;
}
.middle-line {
// 为svg设置虚线,数字越大,虚线段越长,
// 设置2个参数,参数1: 虚线的长度 参数2: 虚线和虚线之间的间隔, 如果只设置一个参数,说明两个值一样大小
stroke-dasharray: 15 20;
z-index: 999;
}
.leaflet-tooltip {
color: #fff !important;
background-color: rgba(255, 255, 255, 0) !important;
border: 0 !important;
box-shadow: rgba(0, 0, 0, 0);
font-size: 12px !important;
}
.leaflet-control-attribution {
display: none !important;
}
</style>
\ No newline at end of file
<template>
<div class="map-contain">
<canvas id="map" ref="root"></canvas>
<img src="/image/compass.png" class="compass" ref="compass"
:style="`transform: rotateZ(${compassRotationAngle}rad)`" alt="" @click="changeCompass">
<div class="navigate-preview">
<img src="/image/navigate.png" class="navigate" @click="changeNavigate" alt="" />
</div>
</div>
</template>
<script setup>
import { markRaw, onMounted, watch, ref, computed, onBeforeUnmount, nextTick } from 'vue'
import { useMapStore } from '@/store/MapStore.js'
import { useVehicleStore } from '@/store/VehicleStore'
import { storeToRefs } from 'pinia'
import { vehicleScale } from '../js/tools'
import DeckNew from '@/tools/Deck';
import * as turf from '@turf/turf'
const safe_color = '#FFA500'
const BASE_RAD = 1.5707963267948966
const MAP_ZOOM = 17
const LAYER_PROPOITY = {
runablearea: 1,
staticobjs: 2,
diggingarea: 3,
diggingworkarea: 3,
dumparea: 4,
barricade: 5,
electronicFence: 6,
wetArea: 7,
lane: 8,
obstacles: 9,
stationarea: 10,
parkspot: 11,
lanenode: 12,
currPathinfo: 13,
nextPathinfo: 14,
avoidancePath: 15,
traj: 16,
obstacle: 17
}
const vehicles = {}
let ismousedown = false
let ismousemove = false
let resetTime = null
let obstaclePolygons = []
let dynamicPaths = []
const reNavigateTime = 2.5 * 1000
const props = defineProps({
isShowBasic: Boolean,
clearSinglePointEnable: Boolean,
reloadData: Boolean
})
let map = markRaw({})
let currentPosition = markRaw([])
const root = ref(null)
const mapLayers = markRaw({})
const safeObjects = markRaw({})
const safeTrajs = markRaw({})
const singlePaths = markRaw([])
const navigate = ref(true)
const currentRotation = ref(0)
const markerLayerGroupLists = markRaw({})
const isSinglePreview = ref(false)
const compassRotationAngle = ref(0)
const compass = ref(null)
const mapStore = useMapStore()
const mapStoreToRefs = storeToRefs(mapStore)
const {
lanenode,
lane,
runablearea,
centerline,
obstacles,
diggingworkarea,
dumparea,
barricade,
stationarea,
parkspot,
staticobjs,
electronicFence,
morepoint, // 单机循迹单路径
morepath, // 单机循迹多路径
nextPathinfo,
currPathinfo,
nextPathAvailable,
avoidancePath, // 绕障路径
obstacleData,
dynamicPathinfo, // 车辆动态路权信息
} = mapStoreToRefs
const vehicleStore = useVehicleStore()
const vehicleStoreToRefs = storeToRefs(vehicleStore)
const { vehiclesPositioninfo, safeObj, trajObj, paraminfo, deleteVehicles } = vehicleStoreToRefs
const deviceId = computed(() => {
return paraminfo.value.deviceId
})
const emits = defineEmits(['handleSend'])
onMounted(() => {
//阻止鼠标右键
document.oncontextmenu = f => {
event.returnValue = false
}
let currentCoordinate = []
let bool = false
map = new DeckNew({
initialViewState: {
latitude: document.location.mapCenter[0],
longitude: document.location.mapCenter[1],
zoom: MAP_ZOOM,
// pickingRadius:5,
controller: true,
},
controller: true,
// parent: document.getElementById('mapMain'),
canvas: 'map',
//如果deck滚动条滚动或者拖动地图时,不进行地图角度和等级矫正
onInteractionStateChange: f => {
if (!currentPosition) return
if (f.isZooming || f.isDragging) {
navigate.value = false
clearTimeout(resetTime)
resetTime = window.setTimeout(() => {
if (!navigate.value) {
navigate.value = true
dealVehicleRotate()
currentRotation.value = BASE_RAD
clearTimeout(resetTime)
resetTime = null;
}
}, reNavigateTime)
}
}
})
map.setPitch(40)
emits('handleSend', {
type: 'syncMapVersion',
msg: {}
})
})
function changeNavigate() {
navigate.value = true
dealMapRotate(currentRotation.value, currentPosition, map.getZoom())
}
// 指南针
function changeCompass() {
dealVehicleRotate(0)
currentRotation.value = BASE_RAD
if (navigate.value) {
setTimeout(() => {
dealVehicleRotate()
}, 3 * 1000)
}
}
function dealVehicleRotate(rotate) {
let keys = Object.keys(vehicles)
let target = keys.find(item => item === deviceId.value)
let currentTarget = vehicles[target]
let vehicleHeading = BASE_RAD
let currentOldHeading = currentTarget && currentTarget.options.vehicleHeading
if (typeof rotate === 'number') {
dealMapRotate(0, currentPosition, map.getZoom())
} else {
vehicleHeading = currentOldHeading
currentRotation.value = vehicleHeading
dealMapRotate(vehicleHeading, currentPosition, map.getZoom())
}
}
function dealMapLayer(value, color, layerName) {
if (!value || !map) return
let result = JSON.parse(value)
if (!result) return
let attr = {};
if (layerName === 'barricade') {
attr = {
getLineColor: map.convertColor('#0066ff', 1),
// width: 5
}
} else {
attr = {
getLineColor: feature => {
return layerName === 'lane' ? map.convertColor('#eee', 0.5) : map.convertColor(feature.properties.color, 1)
},
getFillColor: feature => {
let opacity = 0.7;
if (layerName === 'runablearea') {
opacity = 0.5
}
return layerName === 'electronicFence' ? map.convertColor(feature.properties.color, opacity) : color ? map.convertColor(color, opacity) : map.convertColor(feature.properties.color, opacity)
}
}
}
map.createGeoJsonLayer(result, attr, layerName)
mapStore.setData(layerName, null)
}
function dealMapPath(value, layerName, color) {
if (value && value.length) {
let data = JSON.parse(JSON.stringify(value))
let path = map.createPathLayer([
{
path: [...map.coorReverse(data)],
name: layerName,
}
], {
getColor: f => map.convertColor('#ffff00'),
}, layerName)
mapLayers[layerName] = layerName
const lineGeo = turf.lineString([...map.coorReverse(JSON.parse(JSON.stringify(data)))])
let bufferLine = turf.buffer(lineGeo, 6.5, { units: "meters" })
const obj = {
type: "FeatureCollection",
features: [bufferLine]
}
const attr = {
getFillColor: f => map.convertColor(color, 0.6),
getLineColor: f => map.convertColor(color, 1)
}
// map.setLayerSortName('bufferLayer', layerName + 'Buffer')
map.createGeoJsonLayer(obj, attr, layerName + 'Buffer')
mapLayers[`${layerName}Buffer`] = `${layerName}Buffer`
}
}
function dealDivIcon(value, layerName) {
if (!value || !map) return
let result = JSON.parse(value)
if (!result) return
const { features } = result
for (let i = 0; i < features.length; i++) {
let feature = features[i]
let { name, id } = feature.properties
let { coordinates } = feature.geometry
let markerCoor = null
if (layerName === 'lanenode') {
markerCoor = [coordinates[1], coordinates[0]]
} else {
let center = turf.center(feature)
markerCoor = [center.geometry.coordinates[1], center.geometry.coordinates[0]]
}
let texData = {
name: name,
id: id,
coordinates: [markerCoor[1], markerCoor[0], 1],
}
if (markerLayerGroupLists[`${layerName}${id}`]) {
markerLayerGroupLists[`${layerName}${id}`] = texData
} else {
markerLayerGroupLists[`${layerName}${id}`] = texData
}
}
map.createTextLayer([...Object.values(markerLayerGroupLists)], {
getSize: 15
}, 'text')
// map.setLayerSortName('marker', 'marker')
map.setLayerSortName('markerLayer', 'marker')
map.creatCircle(Object.values(markerLayerGroupLists), {
getFillColor: f => map.convertColor('#2aa1fa', 1),
getLineColor: f => map.convertColor('#2aa1fa', 0.5),
getLineWidth: 0.5,
radius: 1.5
}, 'marker')
mapStore.setData(layerName, null)
}
function removeLayer(obj, vehicleID) {
if (obj[vehicleID]) {
for (let item in obj[vehicleID]) {
map.removeLayer('map', obj[vehicleID][item])
}
}
}
function dealSafe(vehicleID, safe) {
if (!map) return
const { enable, data, dealedData, vehicleType, vehicleLatitude, vehicleLongtitude } = safe
removeLayer(safeObjects, vehicleID)
safeObjects[vehicleID] = {}
if (!enable) return
let safeType = [1, 20, 21].includes(vehicleType) ? 'circle' : 'rectangle'
let zIndex = 16
for (let i = 0; i < dealedData.length; i++) {
let item = JSON.parse(JSON.stringify(dealedData[i]))
map.setLayerSortName('baseLayer', vehicleID + i, 1)
if (safeType === 'rectangle') {
map.creatPolygon({
coordinates: map.coorReverse(item),
}, {
getFillColor: d => map.convertColor(safe_color, 0.4),
getLineColor: d => map.convertColor(safe_color),
getLineWidth: 0.4
}, vehicleID + i)
} else {
map.creatCircle([vehicleLongtitude, vehicleLatitude], {
getFillColor: f => map.convertColor(safe_color, 0.4),
getLineColor: f => map.convertColor(safe_color),
getLineWidth: 0.4,
radius: data[i]
}, vehicleID + i)
}
safeObjects[vehicleID][i] = vehicleID + i
}
}
function dealTraj(vehicleID, traj) {
if (!traj || !map) return
const { trajPathWid, radius, dealedData, vehicleType, vehicleLatitude, vehicleLongtitude } = traj
removeLayer(safeTrajs, vehicleID)
safeTrajs[vehicleID] = {}
// if (!dealedData) return
// if ((dealedData && !dealedData.length) || !radius)) return
if ([1, 20, 21].includes(vehicleType && !radius)) return;
const zIndex = LAYER_PROPOITY['traj']
if ([1, 20, 21].includes(vehicleType) && radius) {
map.creatCircle([vehicleLongtitude, vehicleLatitude], {
getFillColor: f => map.convertColor('#FFA500'),
getLineColor: f => map.convertColor('#FFA500'),
getLineWidth: 1,
radius: radius
}, vehicleID)
safeTrajs[vehicleID]['circle'] = vehicleID
} else {
if (dealedData && !dealedData.length) return;
const lineGeo = turf.lineString([...map.coorReverse(JSON.parse(JSON.stringify(dealedData)))])
// safeTrajs[vehicleID]['path'] = path
let bufferLine = turf.buffer(lineGeo, trajPathWid / 2, { units: "meters" })
const data = {
type: "FeatureCollection",
features: [bufferLine]
}
const attr = {
getFillColor: f => map.convertColor(safe_color, 0.4),
getLineColor: f => map.convertColor(safe_color, 1)
}
safeTrajs[vehicleID]['pathBuffer'] = vehicleID + 'Buffer'
map.setLayerSortName('bufferLayer', vehicleID + 'Buffer', 1)
map.createGeoJsonLayer(data, attr, vehicleID + 'Buffer')
}
}
function dealMapRotate(rotationAngle, center, zoom) {
let rotate = 0
if (rotationAngle) {
rotate = turf.radiansToDegrees(rotationAngle - BASE_RAD)
}
if (compass.value) {
compassRotationAngle.value = rotationAngle
map.setRotation(rotate)
}
center && center.length && map.flyTo(center, zoom, { animate: false })
}
function dealVehiclePosition(value) {
if (!map || !value.length) return
let zoom = map.getZoom()
for (let i = 0; i < value.length; i++) {
const item = value[i]
const { vehicleLatitude, vehicleLongtitude, vehicleHeading, vehicleID, image } = item
let vehiclePosition = [vehicleLatitude, vehicleLongtitude]
let baseObj = {
name: vehicleID,
rotate: vehicleHeading,
coordinates: [vehicleLongtitude, vehicleLatitude],
image: image,
options: {
vehicleHeading: vehicleHeading
}
}
if (vehicles[vehicleID]) {
vehicles[vehicleID] = baseObj
} else {
vehicles[vehicleID] = baseObj
}
if (vehicleID === deviceId.value) {
currentPosition = vehiclePosition
if (navigate.value) {
currentRotation.value = vehicleHeading
dealMapRotate(vehicleHeading, vehiclePosition, zoom <= MAP_ZOOM ? MAP_ZOOM : zoom)
}
}
}
initCar()
}
function initCar() {
map.clearLayer('car')
const nameText = JSON.parse(JSON.stringify(Object.values(vehicles))).map(item => {
item.coordinates = [item.coordinates[0], item.coordinates[1], 10]
return item
})
map.createTextLayer(nameText, {
getSize: 15,
getColor: f => [255, 255, 255, 255],
fontWeight: 400,
fontSettings: {
buffer: 2,
sdf: true,
smoothing: 0.5
},
}, 'carName')
let car = {};
Object.values(vehicles).forEach(item => {
if (car.hasOwnProperty(item.image)) {
car[item.image].push(item)
} else {
car[item.image] = [item]
}
})
for (let key in car) {
// map.setLayerSortName('carLayer', key)
let imageURL = `image/${key}.glb`
map.createCarModel(car[key], { scenegraph: imageURL }, key)
}
}
function dealSingleDatas(datas) {
const { color, coor } = datas
let data = JSON.parse(JSON.stringify(value))
const lineGeo = turf.lineString([...map.coorReverse(JSON.parse(JSON.stringify(data)))])
// safeTrajs[vehicleID]['path'] = path
let bufferLine = turf.buffer(lineGeo, 2, { units: "meters" })
const obj = {
type: "FeatureCollection",
features: [bufferLine]
}
const attr = {
getFillColor: f => map.convertColor(color, 0.4),
getLineColor: f => map.convertColor(color, 1)
}
map.createGeoJsonLayer(obj, attr, layerName)
singlePaths.push(layerName)
}
function dealObtacleData(value) {
if (value && value.length) {
for (let i = 0; i < value.length; i++) {
let obstacle = value[i]
let { typeColor, coordinate, centerLon, centerLat, centerRadius, centerColor } = obstacle
map.creatPolygon({
coordinates: JSON.parse(JSON.stringify(coordinate)),
}, {
getFillColor: d => map.convertColor(typeColor),
getLineColor: d => map.convertColor(typeColor),
getLineWidth: 3
}, 'obstacle')
map.setLayerSortName('buffer', 'obstacleBuffer')
map.creatCircle([centerLon, centerLat], {
getFillColor: f => map.convertColor(centerColor, 0.5),
getLineColor: f => map.convertColor(centerColor, 0.5),
getLineWidth: 0,
radius: centerRadius
}, 'obstacleBuffer')
}
}
}
function dealDynamicDatas(datas) {
let name = 'dynamicLine';
const { color, path } = datas
const lineGeo = turf.lineString([...map.coorReverse(JSON.parse(JSON.stringify(path)))])
// safeTrajs[vehicleID]['path'] = path
let bufferLine = turf.buffer(lineGeo, 2, { units: "meters" })
const obj = {
type: "FeatureCollection",
features: [bufferLine]
}
const attr = {
// getFillColor: f => map.convertColor(color, 0.3),
getLineColor: f => map.convertColor(color, 0.3),
getLineWidth: 30
}
map.createGeoJsonLayer(obj, attr, name)
}
// 直接监听props.isShowBasic 不会触发
watch(() => props.isShowBasic, () => {
nextTick(() => {
// map.invalidateSize(true)
})
})
watch(lanenode, (value) => {
dealDivIcon(value, 'lanenode', '#ff0000')
}, { immediate: true, deep: true })
watch(lane, (value) => {
dealMapLayer(value, '#fff', 'lane')
}, { immediate: true, deep: true })
watch(runablearea, (value) => {
dealMapLayer(value, '#98a0a0', 'runablearea')
}, { immediate: true, deep: true })
watch(centerline, (value) => {
dealMapLayer(value, '#eee', 'centerline')
}, { immediate: true, deep: true })
watch(obstacles, (value) => {
dealDivIcon(value, 'obstacles')
dealMapLayer(value, '#6f9bdd', 'obstacles')
}, { immediate: true, deep: true })
watch(diggingworkarea, (value) => {
dealDivIcon(value, 'diggingworkarea')
dealMapLayer(value, '#886e26', 'diggingworkarea')
}, { immediate: true, deep: true })
watch(dumparea, (value) => {
dealDivIcon(value, 'dumparea')
dealMapLayer(value, '#886e26', 'dumparea')
}, { immediate: true, deep: true })
watch(barricade, (value) => {
dealMapLayer(value, '#0000ff', 'barricade')
}, { immediate: true, deep: true })
watch(stationarea, (value) => {
dealDivIcon(value, 'stationarea')
dealMapLayer(value, '#90ee90', 'stationarea')
}, { immediate: true, deep: true })
watch(parkspot, (value) => {
dealDivIcon(value, 'parkspot')
dealMapLayer(value, '#7e8185', 'parkspot')
}, { immediate: true, deep: true })
watch(staticobjs, (value) => {
dealMapLayer(value, '#98a0a0', 'staticobjs')
}, { immediate: true, deep: true })
watch(electronicFence, (value) => {
dealDivIcon(value, 'electronicFence')
dealMapLayer(value, '#d51d20', 'electronicFence')
}, { immediate: true, deep: true })
watch(nextPathinfo, (value) => {
dealMapPath(value, 'nextPath', nextPathAvailable.value === 1 ? '#19ae19' : '#8B4513')
}, { immediate: true, deep: true })
watch(currPathinfo, (value) => {
dealMapPath(value, 'currentPath', '#19ae19')
}, { immediate: true, deep: true })
watch(avoidancePath, (value) => {
dealMapPath(value, 'avoidancePath', 'blue')
}, { immediate: true, deep: true })
watch(vehiclesPositioninfo, (value) => {
dealVehiclePosition(value)
}, {
immediate: true,
deep: true
})
watch(safeObj, (value) => {
Object.keys(value).forEach(item => {
dealSafe(item, value[item])
})
}, {
immediate: true,
deep: true
})
watch(trajObj, (value) => {
Object.keys(value).forEach(item => {
dealTraj(item, value[item])
})
}, {
immediate: true,
deep: true
})
watch(obstacleData, (value) => {
dealObtacleData(value)
}, { immediate: true, deep: true })
watch(deleteVehicles, (data) => {
if (!map) return
if (data && data.length) {
data.forEach(item => {
// map.removeLayer(vehicles[item])
removeLayer(safeTrajs, item)
removeLayer(safeObjects, item)
delete vehicles[item]
initCar()
})
}
}, {
immediate: true
})
watch(() => props.clearSinglePointEnable, (enable) => {
if (!enable) return
isSinglePreview.value = true
singlePaths.forEach(item => map.removeLayer('map', item))
}, { deep: true })
watch([morepoint, morepath], (pointData, pathData) => {
if (isSinglePreview.value && (pointData || pathData)) {
let datas = pointData.concat(pathData)
for (let i = 0; i < datas.length; i++) {
dealSingleDatas(datas[i])
}
}
}, { deep: true })
watch(dynamicPathinfo, (pathData) => {
if (pathData.length > 0) {
for (let i = 0; i < pathData.length; i++) {
dealDynamicDatas(pathData[i])
}
}
}, { deep: true })
watch(deviceId, (value) => {
if (value && map) {
dealMapRotate(currentRotation.value, currentPosition, map.getZoom())
}
}, { deep: true })
function doUnmount() {
// Object.keys(mapLayers).map(layer => map.removeLayer(mapLayers[layer]))
map.remove()
map = null
}
watch(() => props.reloadData, (value) => {
if (value) {
doUnmount()
}
})
onBeforeUnmount(() => {
doUnmount()
})
</script>
<style lang="less" scope>
.map-contain {
height: 100%;
overflow: hidden;
}
#map {
width: 200% !important;
height: 200% !important;
top: -50%;
left: -50%;
background: #171A23;
position: relative !important;
}
.navigate-preview {
background: #4A75A9;
box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.25);
border-radius: 10px;
opacity: 1;
display: flex;
align-items: center;
justify-content: center;
}
.compass,
.navigate-preview {
position: absolute;
width: 4vw;
height: 4vw;
z-index: 999;
}
.compass {
bottom: 88px;
max-width: 60px;
max-height: 60px;
}
.navigate-preview {
bottom: 24px;
max-width: 60px;
max-height: 60px;
}
</style>
<style lang="less">
.icon-node {
width: 120px !important;
white-space: nowrap;
color: #676565;
// padding-left: -2em !important;
z-index: 1;
font-size: 12px !important;
font-family: "Open Sans Regular", "Arial Unicode MS Regular", sans-serif;
text-transform: uppercase;
text-align: center;
-webkit-text-stroke-display: block;
-webkit-text-stroke-width: 1px;
-webkit-text-stroke-color: rgba(33, 33, 33, 0.8);
}
@media screen and (min-width: 1700px) {
.icon-node {
font-size: 18px !important;
}
}
.icon-node-name {
display: inline-block;
transform: scale(.6);
padding-left: -20px !important;
}
.hide {
display: none !important;
}
.middle-line {
// 为svg设置虚线,数字越大,虚线段越长,
// 设置2个参数,参数1: 虚线的长度 参数2: 虚线和虚线之间的间隔, 如果只设置一个参数,说明两个值一样大小
stroke-dasharray: 15 20;
z-index: 999;
}
.leaflet-tooltip {
color: #fff !important;
background-color: rgba(255, 255, 255, 0) !important;
border: 0 !important;
box-shadow: rgba(0, 0, 0, 0);
font-size: 12px !important;
}
.leaflet-control-attribution {
display: none !important;
}
</style>
\ No newline at end of file
<template>
<div class="map-contain">
<canvas id="map" ref="root"></canvas>
<img src="/image/compass.png" class="compass" ref="compass"
:style="`transform: rotateZ(${compassRotationAngle}rad)`" alt="" @click="changeCompass">
<div class="navigate-preview">
<img src="/image/navigate.png" class="navigate" @click="changeNavigate" alt="" />
</div>
</div>
</template>
<script setup>
import { markRaw, onMounted, watch, ref, computed, onBeforeUnmount, nextTick } from 'vue'
import { useMapStore } from '@/store/MapStore.js'
import { useVehicleStore } from '@/store/VehicleStore'
import { storeToRefs } from 'pinia'
import { vehicleScale } from '../js/tools'
import DeckNew from '@/tools/Deck';
import * as turf from '@turf/turf'
const safe_color = '#FFA500'
const BASE_RAD = 1.5707963267948966
const MAP_ZOOM = 17
const LAYER_PROPOITY = {
runablearea: 1,
staticobjs: 2,
diggingarea: 3,
diggingworkarea: 3,
dumparea: 4,
barricade: 5,
electronicFence: 6,
wetArea: 7,
lane: 8,
obstacles: 9,
stationarea: 10,
parkspot: 11,
lanenode: 12,
currPathinfo: 13,
nextPathinfo: 14,
avoidancePath: 15,
traj: 16,
obstacle: 17
}
const vehicles = {}
let ismousedown = false
let ismousemove = false
let resetTime = null
let obstaclePolygons = []
let dynamicPaths = []
const reNavigateTime = 2.5 * 1000
const props = defineProps({
isShowBasic: Boolean,
clearSinglePointEnable: Boolean,
reloadData: Boolean
})
let map = markRaw({})
let currentPosition = markRaw([])
const root = ref(null)
const mapLayers = markRaw({})
const safeObjects = markRaw({})
const safeTrajs = markRaw({})
const singlePaths = markRaw([])
const navigate = ref(true)
const currentRotation = ref(0)
const markerLayerGroupLists = markRaw({})
const isSinglePreview = ref(false)
const compassRotationAngle = ref(0)
const compass = ref(null)
const mapStore = useMapStore()
const mapStoreToRefs = storeToRefs(mapStore)
const {
lanenode,
lane,
runablearea,
centerline,
obstacles,
diggingworkarea,
dumparea,
barricade,
stationarea,
parkspot,
staticobjs,
electronicFence,
morepoint, // 单机循迹单路径
morepath, // 单机循迹多路径
nextPathinfo,
currPathinfo,
nextPathAvailable,
avoidancePath, // 绕障路径
obstacleData,
dynamicPathinfo, // 车辆动态路权信息
} = mapStoreToRefs
const vehicleStore = useVehicleStore()
const vehicleStoreToRefs = storeToRefs(vehicleStore)
const { vehiclesPositioninfo, safeObj, trajObj, paraminfo, deleteVehicles } = vehicleStoreToRefs
const deviceId = computed(() => {
return paraminfo.value.deviceId
})
const emits = defineEmits(['handleSend'])
onMounted(() => {
//阻止鼠标右键
document.oncontextmenu = f => {
event.returnValue = false
}
let currentCoordinate = []
let bool = false
map = new DeckNew({
initialViewState: {
latitude: document.location.mapCenter[0],
longitude: document.location.mapCenter[1],
zoom: MAP_ZOOM,
// pickingRadius:5,
controller: true,
},
controller: true,
// parent: document.getElementById('mapMain'),
canvas: 'map',
//如果deck滚动条滚动或者拖动地图时,不进行地图角度和等级矫正
onInteractionStateChange: f => {
if (!currentPosition) return
if (f.isZooming || f.isDragging) {
navigate.value = false
clearTimeout(resetTime)
resetTime = window.setTimeout(() => {
if (!navigate.value) {
navigate.value = true
dealVehicleRotate()
currentRotation.value = BASE_RAD
clearTimeout(resetTime)
resetTime = null;
}
}, reNavigateTime)
}
}
})
map.setPitch(40)
emits('handleSend', {
type: 'syncMapVersion',
msg: {}
})
})
function changeNavigate() {
navigate.value = true
dealMapRotate(currentRotation.value, currentPosition, map.getZoom())
}
// 指南针
function changeCompass() {
dealVehicleRotate(0)
currentRotation.value = BASE_RAD
if (navigate.value) {
setTimeout(() => {
dealVehicleRotate()
}, 3 * 1000)
}
}
function dealVehicleRotate(rotate) {
let keys = Object.keys(vehicles)
let target = keys.find(item => item === deviceId.value)
let currentTarget = vehicles[target]
let vehicleHeading = BASE_RAD
let currentOldHeading = currentTarget && currentTarget.options.vehicleHeading
if (typeof rotate === 'number') {
dealMapRotate(0, currentPosition, map.getZoom())
} else {
vehicleHeading = currentOldHeading
currentRotation.value = vehicleHeading
dealMapRotate(vehicleHeading, currentPosition, map.getZoom())
}
}
function dealMapLayer(value, color, layerName) {
if (!value || !map) return
let result = JSON.parse(value)
if (!result) return
let attr = {};
if (layerName === 'barricade') {
attr = {
getLineColor: map.convertColor('#0066ff', 1),
// width: 5
}
} else {
attr = {
getLineColor: feature => {
return layerName === 'lane' ? map.convertColor('#eee', 0.5) : map.convertColor(feature.properties.color, 1)
},
getFillColor: feature => {
let opacity = 0.7;
if (layerName === 'runablearea') {
opacity = 0.5
}
return layerName === 'electronicFence' ? map.convertColor(feature.properties.color, opacity) : color ? map.convertColor(color, opacity) : map.convertColor(feature.properties.color, opacity)
}
}
}
map.createGeoJsonLayer(result, attr, layerName)
mapStore.setData(layerName, null)
}
function dealMapPath(value, layerName, color) {
if (value && value.length) {
let data = JSON.parse(JSON.stringify(value))
let path = map.createPathLayer([
{
path: [...map.coorReverse(data)],
name: layerName,
}
], {
getColor: f => map.convertColor('#ffff00'),
}, layerName)
mapLayers[layerName] = layerName
const lineGeo = turf.lineString([...map.coorReverse(JSON.parse(JSON.stringify(data)))])
let bufferLine = turf.buffer(lineGeo, 6.5, { units: "meters" })
const obj = {
type: "FeatureCollection",
features: [bufferLine]
}
const attr = {
getFillColor: f => map.convertColor(color, 0.6),
getLineColor: f => map.convertColor(color, 1)
}
// map.setLayerSortName('bufferLayer', layerName + 'Buffer')
map.createGeoJsonLayer(obj, attr, layerName + 'Buffer')
mapLayers[`${layerName}Buffer`] = `${layerName}Buffer`
}
}
function dealDivIcon(value, layerName) {
if (!value || !map) return
let result = JSON.parse(value)
if (!result) return
const { features } = result
for (let i = 0; i < features.length; i++) {
let feature = features[i]
let { name, id } = feature.properties
let { coordinates } = feature.geometry
let markerCoor = null
if (layerName === 'lanenode') {
markerCoor = [coordinates[1], coordinates[0]]
} else {
let center = turf.center(feature)
markerCoor = [center.geometry.coordinates[1], center.geometry.coordinates[0]]
}
let texData = {
name: name,
id: id,
coordinates: [markerCoor[1], markerCoor[0], 1],
}
if (markerLayerGroupLists[`${layerName}${id}`]) {
markerLayerGroupLists[`${layerName}${id}`] = texData
} else {
markerLayerGroupLists[`${layerName}${id}`] = texData
}
}
map.createTextLayer([...Object.values(markerLayerGroupLists)], {
getSize: 15
}, 'text')
// map.setLayerSortName('marker', 'marker')
map.setLayerSortName('markerLayer', 'marker')
map.creatCircle(Object.values(markerLayerGroupLists), {
getFillColor: f => map.convertColor('#2aa1fa', 1),
getLineColor: f => map.convertColor('#2aa1fa', 0.5),
getLineWidth: 0.5,
radius: 1.5
}, 'marker')
mapStore.setData(layerName, null)
}
function removeLayer(obj, vehicleID) {
if (obj[vehicleID]) {
for (let item in obj[vehicleID]) {
map.removeLayer('map', obj[vehicleID][item])
}
}
}
function dealSafe(vehicleID, safe) {
if (!map) return
const { enable, data, dealedData, vehicleType, vehicleLatitude, vehicleLongtitude } = safe
removeLayer(safeObjects, vehicleID)
safeObjects[vehicleID] = {}
if (!enable) return
let safeType = [1, 20, 21].includes(vehicleType) ? 'circle' : 'rectangle'
let zIndex = 16
for (let i = 0; i < dealedData.length; i++) {
let item = JSON.parse(JSON.stringify(dealedData[i]))
map.setLayerSortName('polygonLayer', vehicleID + i)
if (safeType === 'rectangle') {
map.creatPolygon({
coordinates: map.coorReverse(item),
}, {
getFillColor: d => map.convertColor(safe_color, 0.4),
getLineColor: d => map.convertColor(safe_color),
getLineWidth: 0.4
}, vehicleID + i)
} else {
map.creatCircle([vehicleLongtitude, vehicleLatitude], {
getFillColor: f => map.convertColor(safe_color, 0.4),
getLineColor: f => map.convertColor(safe_color),
getLineWidth: 0.4,
radius: data[i]
}, vehicleID + i)
}
safeObjects[vehicleID][i] = vehicleID + i
}
}
function dealTraj(vehicleID, traj) {
if (!traj || !map) return
const { trajPathWid, radius, dealedData, vehicleType, vehicleLatitude, vehicleLongtitude } = traj
removeLayer(safeTrajs, vehicleID)
safeTrajs[vehicleID] = {}
// if (!dealedData) return
// if ((dealedData && !dealedData.length) || !radius)) return
if ([1, 20, 21].includes(vehicleType && !radius)) return;
const zIndex = LAYER_PROPOITY['traj']
if ([1, 20, 21].includes(vehicleType) && radius) {
map.creatCircle([vehicleLongtitude, vehicleLatitude], {
getFillColor: f => map.convertColor('#FFA500'),
getLineColor: f => map.convertColor('#FFA500'),
getLineWidth: 1,
radius: radius
}, vehicleID)
safeTrajs[vehicleID]['circle'] = vehicleID
} else {
if (dealedData && !dealedData.length) return;
const lineGeo = turf.lineString([...map.coorReverse(JSON.parse(JSON.stringify(dealedData)))])
// safeTrajs[vehicleID]['path'] = path
let bufferLine = turf.buffer(lineGeo, trajPathWid / 2, { units: "meters" })
const data = {
type: "FeatureCollection",
features: [bufferLine]
}
const attr = {
getFillColor: f => map.convertColor(safe_color, 0.4),
getLineColor: f => map.convertColor(safe_color, 1)
}
safeTrajs[vehicleID]['pathBuffer'] = vehicleID + 'Buffer'
map.setLayerSortName('bufferLayer', vehicleID + 'Buffer', 1)
map.createGeoJsonLayer(data, attr, vehicleID + 'Buffer')
}
}
function dealMapRotate(rotationAngle, center, zoom) {
let rotate = 0
if (rotationAngle) {
rotate = turf.radiansToDegrees(rotationAngle - BASE_RAD)
}
if (compass.value) {
compassRotationAngle.value = rotationAngle
map.setRotation(rotate)
}
center && center.length && map.flyTo(center, zoom, { animate: false })
}
function dealVehiclePosition(value) {
if (!map || !value.length) return
let zoom = map.getZoom()
for (let i = 0; i < value.length; i++) {
const item = value[i]
const { vehicleLatitude, vehicleLongtitude, vehicleHeading, vehicleID, image } = item
let vehiclePosition = [vehicleLatitude, vehicleLongtitude]
let baseObj = {
name: vehicleID,
rotate: vehicleHeading,
coordinates: [vehicleLongtitude, vehicleLatitude],
image: image,
options: {
vehicleHeading: vehicleHeading
}
}
if (vehicles[vehicleID]) {
vehicles[vehicleID] = baseObj
} else {
vehicles[vehicleID] = baseObj
}
if (vehicleID === deviceId.value) {
currentPosition = vehiclePosition
if (navigate.value) {
currentRotation.value = vehicleHeading
dealMapRotate(vehicleHeading, vehiclePosition, zoom <= MAP_ZOOM ? MAP_ZOOM : zoom)
}
}
}
initCar()
}
function initCar() {
map.clearLayer('car')
const nameText = JSON.parse(JSON.stringify(Object.values(vehicles))).map(item => {
item.coordinates = [item.coordinates[0], item.coordinates[1], 10]
return item
})
map.createTextLayer(nameText, {
getSize: 15,
getColor: f => [255, 255, 255, 255],
fontWeight: 400,
fontSettings: {
buffer: 2,
sdf: true,
smoothing: 0.5
},
}, 'carName')
let car = {};
Object.values(vehicles).forEach(item => {
if (car.hasOwnProperty(item.image)) {
car[item.image].push(item)
} else {
car[item.image] = [item]
}
})
for (let key in car) {
// map.setLayerSortName('carLayer', key)
let imageURL = `image/${key}.glb`
map.createCarModel(car[key], { scenegraph: imageURL }, key)
}
}
function dealSingleDatas(datas) {
const { color, coor } = datas
let data = JSON.parse(JSON.stringify(value))
const lineGeo = turf.lineString([...map.coorReverse(JSON.parse(JSON.stringify(data)))])
// safeTrajs[vehicleID]['path'] = path
let bufferLine = turf.buffer(lineGeo, 2, { units: "meters" })
const obj = {
type: "FeatureCollection",
features: [bufferLine]
}
const attr = {
getFillColor: f => map.convertColor(color, 0.4),
getLineColor: f => map.convertColor(color, 1)
}
map.createGeoJsonLayer(obj, attr, layerName)
singlePaths.push(layerName)
}
function dealObtacleData(value) {
if (value && value.length) {
for (let i = 0; i < value.length; i++) {
let obstacle = value[i]
let { typeColor, coordinate, centerLon, centerLat, centerRadius, centerColor } = obstacle
map.creatPolygon({
coordinates: JSON.parse(JSON.stringify(coordinate)),
}, {
getFillColor: d => map.convertColor(typeColor),
getLineColor: d => map.convertColor(typeColor),
getLineWidth: 3
}, 'obstacle')
map.setLayerSortName('buffer', 'obstacleBuffer')
map.creatCircle([centerLon, centerLat], {
getFillColor: f => map.convertColor(centerColor, 0.5),
getLineColor: f => map.convertColor(centerColor, 0.5),
getLineWidth: 0,
radius: centerRadius
}, 'obstacleBuffer')
}
}
}
function dealDynamicDatas(datas) {
let name = 'dynamicLine';
const { color, path } = datas
const lineGeo = turf.lineString([...map.coorReverse(JSON.parse(JSON.stringify(path)))])
// safeTrajs[vehicleID]['path'] = path
let bufferLine = turf.buffer(lineGeo, 2, { units: "meters" })
const obj = {
type: "FeatureCollection",
features: [bufferLine]
}
const attr = {
// getFillColor: f => map.convertColor(color, 0.3),
getLineColor: f => map.convertColor(color, 0.3),
getLineWidth: 30
}
map.createGeoJsonLayer(obj, attr, name)
}
// 直接监听props.isShowBasic 不会触发
watch(() => props.isShowBasic, () => {
nextTick(() => {
// map.invalidateSize(true)
})
})
watch(lanenode, (value) => {
dealDivIcon(value, 'lanenode', '#ff0000')
}, { immediate: true, deep: true })
watch(lane, (value) => {
dealMapLayer(value, '#fff', 'lane')
}, { immediate: true, deep: true })
watch(runablearea, (value) => {
dealMapLayer(value, '#98a0a0', 'runablearea')
}, { immediate: true, deep: true })
watch(centerline, (value) => {
dealMapLayer(value, '#eee', 'centerline')
}, { immediate: true, deep: true })
watch(obstacles, (value) => {
dealDivIcon(value, 'obstacles')
dealMapLayer(value, '#6f9bdd', 'obstacles')
}, { immediate: true, deep: true })
watch(diggingworkarea, (value) => {
dealDivIcon(value, 'diggingworkarea')
dealMapLayer(value, '#886e26', 'diggingworkarea')
}, { immediate: true, deep: true })
watch(dumparea, (value) => {
dealDivIcon(value, 'dumparea')
dealMapLayer(value, '#886e26', 'dumparea')
}, { immediate: true, deep: true })
watch(barricade, (value) => {
dealMapLayer(value, '#0000ff', 'barricade')
}, { immediate: true, deep: true })
watch(stationarea, (value) => {
dealDivIcon(value, 'stationarea')
dealMapLayer(value, '#90ee90', 'stationarea')
}, { immediate: true, deep: true })
watch(parkspot, (value) => {
dealDivIcon(value, 'parkspot')
dealMapLayer(value, '#7e8185', 'parkspot')
}, { immediate: true, deep: true })
watch(staticobjs, (value) => {
dealMapLayer(value, '#98a0a0', 'staticobjs')
}, { immediate: true, deep: true })
watch(electronicFence, (value) => {
dealDivIcon(value, 'electronicFence')
dealMapLayer(value, '#d51d20', 'electronicFence')
}, { immediate: true, deep: true })
watch(nextPathinfo, (value) => {
dealMapPath(value, 'nextPath', nextPathAvailable.value === 1 ? '#19ae19' : '#8B4513')
}, { immediate: true, deep: true })
watch(currPathinfo, (value) => {
dealMapPath(value, 'currentPath', '#19ae19')
}, { immediate: true, deep: true })
watch(avoidancePath, (value) => {
dealMapPath(value, 'avoidancePath', 'blue')
}, { immediate: true, deep: true })
watch(vehiclesPositioninfo, (value) => {
dealVehiclePosition(value)
}, {
immediate: true,
deep: true
})
watch(safeObj, (value) => {
Object.keys(value).forEach(item => {
dealSafe(item, value[item])
})
}, {
immediate: true,
deep: true
})
watch(trajObj, (value) => {
Object.keys(value).forEach(item => {
dealTraj(item, value[item])
})
}, {
immediate: true,
deep: true
})
watch(obstacleData, (value) => {
dealObtacleData(value)
}, { immediate: true, deep: true })
watch(deleteVehicles, (data) => {
if (!map) return
if (data && data.length) {
data.forEach(item => {
// map.removeLayer(vehicles[item])
removeLayer(safeTrajs, item)
removeLayer(safeObjects, item)
delete vehicles[item]
initCar()
})
}
}, {
immediate: true
})
watch(() => props.clearSinglePointEnable, (enable) => {
if (!enable) return
isSinglePreview.value = true
singlePaths.forEach(item => map.removeLayer('map', item))
}, { deep: true })
watch([morepoint, morepath], (pointData, pathData) => {
if (isSinglePreview.value && (pointData || pathData)) {
let datas = pointData.concat(pathData)
for (let i = 0; i < datas.length; i++) {
dealSingleDatas(datas[i])
}
}
}, { deep: true })
watch(dynamicPathinfo, (pathData) => {
if (pathData.length > 0) {
for (let i = 0; i < pathData.length; i++) {
dealDynamicDatas(pathData[i])
}
}
}, { deep: true })
watch(deviceId, (value) => {
if (value && map) {
dealMapRotate(currentRotation.value, currentPosition, map.getZoom())
}
}, { deep: true })
function doUnmount() {
// Object.keys(mapLayers).map(layer => map.removeLayer(mapLayers[layer]))
map.remove()
map = null
}
watch(() => props.reloadData, (value) => {
if (value) {
doUnmount()
}
})
onBeforeUnmount(() => {
doUnmount()
})
</script>
<style lang="less" scope>
.map-contain {
height: 100%;
overflow: hidden;
}
#map {
width: 200% !important;
height: 200% !important;
top: -50%;
left: -50%;
background: #171A23;
position: relative !important;
}
.navigate-preview {
background: #4A75A9;
box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.25);
border-radius: 10px;
opacity: 1;
display: flex;
align-items: center;
justify-content: center;
}
.compass,
.navigate-preview {
position: absolute;
width: 4vw;
height: 4vw;
z-index: 999;
}
.compass {
bottom: 88px;
max-width: 60px;
max-height: 60px;
}
.navigate-preview {
bottom: 24px;
max-width: 60px;
max-height: 60px;
}
</style>
<style lang="less">
.icon-node {
width: 120px !important;
white-space: nowrap;
color: #676565;
// padding-left: -2em !important;
z-index: 1;
font-size: 12px !important;
font-family: "Open Sans Regular", "Arial Unicode MS Regular", sans-serif;
text-transform: uppercase;
text-align: center;
-webkit-text-stroke-display: block;
-webkit-text-stroke-width: 1px;
-webkit-text-stroke-color: rgba(33, 33, 33, 0.8);
}
@media screen and (min-width: 1700px) {
.icon-node {
font-size: 18px !important;
}
}
.icon-node-name {
display: inline-block;
transform: scale(.6);
padding-left: -20px !important;
}
.hide {
display: none !important;
}
.middle-line {
// 为svg设置虚线,数字越大,虚线段越长,
// 设置2个参数,参数1: 虚线的长度 参数2: 虚线和虚线之间的间隔, 如果只设置一个参数,说明两个值一样大小
stroke-dasharray: 15 20;
z-index: 999;
}
.leaflet-tooltip {
color: #fff !important;
background-color: rgba(255, 255, 255, 0) !important;
border: 0 !important;
box-shadow: rgba(0, 0, 0, 0);
font-size: 12px !important;
}
.leaflet-control-attribution {
display: none !important;
}
</style>
\ No newline at end of file
{ {
"SERVICE_IP": "172.16.0.130:1234", "SERVICE_IP": "172.16.0.114:1234",
"MAP_CENTER": [39.74441007068,111.24544532751], "MAP_CENTER": [39.74441007068,111.24544532751],
"version": "1.1.3" "version": "1.1.3"
} }
\ No newline at end of file
...@@ -164,8 +164,8 @@ export default class DeckNew { ...@@ -164,8 +164,8 @@ export default class DeckNew {
} }
let layer = new PolygonLayer(Object.assign(defalutOprion, option)); let layer = new PolygonLayer(Object.assign(defalutOprion, option));
this.setLayerSortName('polygonLayer', layerName) this.setLayerSortName('polygonLayer', layerName)
this.removeLayer('polygon', layerName) this.removeLayer('map', layerName)
this.polygonLayers.push(layer) this.mapLayers.push(layer)
this.initLayer() this.initLayer()
} }
createPathLayer(data, option, layerName) { createPathLayer(data, option, layerName) {
......
...@@ -124,7 +124,7 @@ onMounted(() => { ...@@ -124,7 +124,7 @@ onMounted(() => {
canvas: 'map', canvas: 'map',
//如果deck滚动条滚动或者拖动地图时,不进行地图角度和等级矫正 //如果deck滚动条滚动或者拖动地图时,不进行地图角度和等级矫正
onInteractionStateChange: f => { onInteractionStateChange: f => {
if (!currentPosition) return if (!currentPosition) return
if (f.isZooming || f.isDragging) { if (f.isZooming || f.isDragging) {
navigate.value = false navigate.value = false
...@@ -135,7 +135,7 @@ onMounted(() => { ...@@ -135,7 +135,7 @@ onMounted(() => {
dealVehicleRotate() dealVehicleRotate()
currentRotation.value = BASE_RAD currentRotation.value = BASE_RAD
clearTimeout(resetTime) clearTimeout(resetTime)
resetTime=null; resetTime = null;
} }
}, reNavigateTime) }, reNavigateTime)
} }
...@@ -305,19 +305,24 @@ function dealSafe(vehicleID, safe) { ...@@ -305,19 +305,24 @@ function dealSafe(vehicleID, safe) {
let zIndex = 16 let zIndex = 16
for (let i = 0; i < dealedData.length; i++) { for (let i = 0; i < dealedData.length; i++) {
let item = JSON.parse(JSON.stringify(dealedData[i])) let item = JSON.parse(JSON.stringify(dealedData[i]))
let layer = safeType === 'rectangle' ? map.creatPolygon({ map.setLayerSortName('polygonLayer', vehicleID + i)
coordinates: map.coorReverse(item), if (safeType === 'rectangle') {
}, { map.creatPolygon({
getFillColor: d => map.convertColor(safe_color), coordinates: map.coorReverse(item),
getLineColor: d => map.convertColor(safe_color), }, {
getLineWidth: 1 getFillColor: d => map.convertColor(safe_color, 0.4),
}, 'rectangle'+i) : map.creatCircle([vehicleLongtitude, vehicleLatitude], { getLineColor: d => map.convertColor(safe_color),
getFillColor: f => map.convertColor(safe_color), getLineWidth: 0.4
getLineColor: f => map.convertColor(safe_color), }, vehicleID + i)
getLineWidth: 1, } else {
radius: data[i] map.creatCircle([vehicleLongtitude, vehicleLatitude], {
}, vehicleID+i) getFillColor: f => map.convertColor(safe_color, 0.4),
safeObjects[vehicleID][i] = vehicleID getLineColor: f => map.convertColor(safe_color),
getLineWidth: 0.4,
radius: data[i]
}, vehicleID + i)
}
safeObjects[vehicleID][i] = vehicleID + i
} }
} }
...@@ -392,23 +397,23 @@ function dealVehiclePosition(value) { ...@@ -392,23 +397,23 @@ function dealVehiclePosition(value) {
if (vehicles[vehicleID]) { if (vehicles[vehicleID]) {
vehicles[vehicleID] = baseObj vehicles[vehicleID] = baseObj
} else { } else {
vehicles[vehicleID] = baseObj vehicles[vehicleID] = baseObj
} }
if (vehicleID === deviceId.value) { if (vehicleID === deviceId.value) {
currentPosition = vehiclePosition currentPosition = vehiclePosition
if (navigate.value) { if (navigate.value) {
currentRotation.value = vehicleHeading currentRotation.value = vehicleHeading
dealMapRotate(vehicleHeading, vehiclePosition, zoom <= MAP_ZOOM ? MAP_ZOOM : zoom) dealMapRotate(vehicleHeading, vehiclePosition, zoom <= MAP_ZOOM ? MAP_ZOOM : zoom)
} }
} }
} }
initCar() initCar()
} }
function initCar(){ function initCar() {
map.clearLayer('car') map.clearLayer('car')
const nameText = JSON.parse(JSON.stringify(Object.values(vehicles))).map(item => { const nameText = JSON.parse(JSON.stringify(Object.values(vehicles))).map(item => {
item.coordinates = [item.coordinates[0], item.coordinates[1], 10] item.coordinates = [item.coordinates[0], item.coordinates[1], 10]
...@@ -620,7 +625,7 @@ watch(deleteVehicles, (data) => { ...@@ -620,7 +625,7 @@ watch(deleteVehicles, (data) => {
watch(() => props.clearSinglePointEnable, (enable) => { watch(() => props.clearSinglePointEnable, (enable) => {
if (!enable) return if (!enable) return
isSinglePreview.value = true isSinglePreview.value = true
singlePaths.forEach(item => map.removeLayer('map',item)) singlePaths.forEach(item => map.removeLayer('map', item))
}, { deep: true }) }, { deep: true })
watch([morepoint, morepath], (pointData, pathData) => { watch([morepoint, morepath], (pointData, pathData) => {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment