Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
J
JINRUN-PERPOSITION
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
xinzhedeai
JINRUN-PERPOSITION
Commits
6a08bfbd
Commit
6a08bfbd
authored
Nov 19, 2025
by
xinzhedeai
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add:better + 提示弹窗实体添加
parent
10523982
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
296 additions
and
155 deletions
+296
-155
index.vue
src/views/index.vue
+296
-155
No files found.
src/views/index.vue
View file @
6a08bfbd
...
...
@@ -36,13 +36,15 @@ export default {
},
// 其他人员数据...
],
personModelInterval
:
null
,
intervaler
:
null
,
bgEntities
:
{},
// 所有的key都对应一个实体对象。而人员的实体对应的key不是数字。
};
},
mounted
()
{
// 组件挂载后初始化地图
this
.
initCesium
();
// 监听窗口大小变化
window
.
addEventListener
(
"
resize
"
,
this
.
handleResize
);
},
beforeMount
()
{
localStg
.
set
(
"
token
"
,
222233
);
...
...
@@ -57,152 +59,41 @@ export default {
});
},
beforeDestroy
()
{
// 清理事件监听
window
.
removeEventListener
(
"
resize
"
,
this
.
handleResize
);
// 清理地图资源
if
(
this
.
viewer
)
{
this
.
viewer
.
destroy
();
this
.
viewer
=
null
;
}
// 清理点击事件处理器
if
(
this
.
clickHandler
)
{
this
.
clickHandler
.
destroy
();
this
.
clickHandler
=
null
;
}
// 组件销毁前清理地图资源
if
(
this
.
viewer
)
{
this
.
viewer
.
destroy
();
this
.
viewer
=
null
;
}
// 清理定时器
if
(
this
.
intervaler
)
{
clearInterval
(
this
.
intervaler
);
}
// 清空实体引用
this
.
bgEntities
=
{};
},
methods
:
{
createPersonModel
()
{
// 批次号管理(每次定时器触发时生成一个新的批次号)
// var currentBatch = 0;
// const batchMap = {};
if
(
!
this
.
personModelInterval
)
{
this
.
personModelInterval
=
setInterval
(()
=>
{
console
.
log
(
"
开始获取实时数据
"
);
// currentBatch++; // 每次定时器触发,生成新的批次号
if
(
this
.
bgEntities
)
{
// 新增:清除实体
clearEntities
()
{
if
(
this
.
viewer
&&
this
.
bgEntities
)
{
for
(
let
key
in
this
.
bgEntities
)
{
if
(
isNaN
(
parseFloat
(
key
)))
{
// 非数字键名的是人员实体
this
.
viewer
.
entities
.
remove
(
this
.
bgEntities
[
key
]);
delete
this
.
bgEntities
[
key
];
}
}
}
// 从API获取最新的人员定位数据
this
.
personCardList
((
list
)
=>
{
// let perList = list; // 使用全部人员数据
console
.
log
(
"
人员数据
"
,
this
.
personnelList
);
// 创建新实体
for
(
let
item
of
this
.
personnelList
)
{
let
lng
=
Number
(
item
.
lng
);
let
lat
=
Number
(
item
.
lat
);
let
height
=
Number
(
item
.
height
);
let
position
=
Cesium
.
Cartesian3
.
fromDegrees
(
lng
,
lat
,
height
);
console
.
log
(
item
.
perName
,
position
);
// 创建人员标记
let
entity
=
this
.
viewer
.
entities
.
add
({
position
:
position
,
label
:
{
text
:
item
.
perName
,
font
:
"
16px
"
,
backgroundColor
:
Cesium
.
Color
.
fromCssColorString
(
"
#173349
"
),
showBackground
:
true
,
fillColor
:
Cesium
.
Color
.
YELLOW
,
depthTestAgainstTerrain
:
false
,
// 禁用地形深度测试
// text: "高区管委",
// font: "16px",
// // scale: 0.5,
// backgroundColor: Cesium.Color.fromCssColorString("#173349"),
// color: Cesium.Color.WHITE,
// showBackground: true,
// horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
// verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
// distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
// 1.0,
// 8000.0
// ),
pixelOffset
:
new
Cesium
.
Cartesian2
(
0
,
-
35
),
// fillColor: Cesium.Color.WHITE,
// backgroundColor: new Cesium.Color(0.0, 0.486, 0.65, 0.8),
// disableDepthTestDistance: 5,
// heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
},
billboard
:
{
image
:
"
/poi-marker-default.png
"
,
scale
:
0.5
,
// heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
// disableDepthTestDistance: 5,
// distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
// 1.0,
// 8000.0
// ),
// horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
// verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
},
description
:
`<div><h4>
${
item
.
perName
}${
item
.
status
}
</h4></div>`
,
fixedFrame
:
Cesium
.
Transforms
.
eastNorthUpToFixedFrame
(
position
),
});
entity
.
info
=
item
;
// 添加 info 属性
// entity.batch = currentBatch; // 标记当前批次
this
.
bgEntities
[
item
.
perName
]
=
entity
;
// 存储新实体
}
});
},
10000
);
// 每10秒刷新一次
}
},
personCardList
(
fn
)
{
console
.
log
(
"
人员定位数据
"
,
this
.
personnelList
);
// 将笛卡尔坐标转换为经纬度坐标
const
cartographic
=
Cesium
.
Cartographic
.
fromCartesian
({
x
:
-
2686273.730145489
,
y
:
4293961.185794622
,
z
:
3863430.5618300107
,
});
const
baseLongitude
=
Cesium
.
Math
.
toDegrees
(
cartographic
.
longitude
);
const
baseLatitude
=
Cesium
.
Math
.
toDegrees
(
cartographic
.
latitude
);
const
baseHeight
=
cartographic
.
height
+
1
;
console
.
log
(
"
人员经纬度基准点:
"
,
{
longitude
:
baseLongitude
,
latitude
:
baseLatitude
,
height
:
baseHeight
,
});
// 清除现有的人员列表
this
.
personnelList
=
[];
// 生成10个不同的经纬度坐标,确保它们之间的距离不超过100米
// 在经纬度上,约0.00001度的变化大约对应1米(赤道附近)
// 为了确保不超过100米,我们使用±0.00005度的随机偏移
const
maxOffset
=
0.00005
;
for
(
let
index
=
0
;
index
<
10
;
index
++
)
{
// 生成随机偏移量,确保每个点都不同但距离不远
const
lngOffset
=
(
Math
.
random
()
-
0.5
)
*
2
*
maxOffset
;
const
latOffset
=
(
Math
.
random
()
-
0.5
)
*
2
*
maxOffset
;
this
.
personnelList
.
push
({
lng
:
baseLongitude
+
lngOffset
,
lat
:
baseLatitude
+
latOffset
,
height
:
baseHeight
,
// 高度略有不同,便于区分
perName
:
"
张三
"
+
index
,
status
:
"
online
"
,
// 在线
avatar
:
"
/static/images/avatars/zhangsan.png
"
,
// 头像
});
}
fn
(
this
.
personnelList
);
},
showPersonInfo
(
description
)
{
// 使用 Cesium 的 InfoBox 显示信息
this
.
viewer
.
selectedEntity
=
this
.
viewer
.
entities
.
add
({
description
:
description
,
});
this
.
viewer
.
infoBox
.
frame
.
sandbox
=
"
allow-same-origin allow-top-navigation allow-pointer-lock allow-popups allow-forms allow-scripts
"
;
this
.
viewer
.
infoBox
.
frame
.
src
=
"
about:blank
"
;
this
.
viewer
.
infoBox
.
frame
.
contentDocument
.
write
(
description
);
this
.
viewer
.
infoBox
.
frame
.
contentDocument
.
close
();
this
.
viewer
.
infoBox
.
viewModel
.
showInfo
=
true
;
this
.
viewer
.
scene
.
globe
.
depthTestAgainstTerrain
=
true
;
},
goTarget
(
href
)
{
window
.
open
(
href
,
"
_blank
"
);
},
/**
...
...
@@ -223,12 +114,12 @@ export default {
// 配置是否显示各种控件
animation
:
false
,
// 动画控件
baseLayerPicker
:
true
,
// 底图选择器
fullscreenButton
:
tru
e
,
// 全屏按钮
geocoder
:
tru
e
,
// 地址搜索
homeButton
:
tru
e
,
// 主页按钮
infoBox
:
tru
e
,
// 信息框
sceneModePicker
:
tru
e
,
// 场景模式选择器
selectionIndicator
:
tru
e
,
// 选择指示器
fullscreenButton
:
fals
e
,
// 全屏按钮
geocoder
:
fals
e
,
// 地址搜索
homeButton
:
fals
e
,
// 主页按钮
infoBox
:
fals
e
,
// 信息框
sceneModePicker
:
fals
e
,
// 场景模式选择器
selectionIndicator
:
fals
e
,
// 选择指示器
timeline
:
false
,
// 时间线
navigationHelpButton
:
false
,
// 导航帮助按钮
navigationInstructionsInitiallyVisible
:
false
,
...
...
@@ -236,16 +127,6 @@ export default {
center
:
Cesium
.
Cartesian3
.
fromDegrees
(
104.06
,
30.67
,
10000000
),
});
// 设置相机视图
// this.viewer.camera.setView({
// destination: Cesium.Cartesian3.fromDegrees(104.06, 30.67, 10000000), // 经度、纬度、高度
// orientation: {
// heading: Cesium.Math.toRadians(0.0), // 方向
// pitch: Cesium.Math.toRadians(-90.0), // 倾斜角度
// roll: 0.0, // 翻滚角度
// },
// });
this
.
viewer
.
scene
.
camera
.
setView
({
// 视角-环翠
duration
:
1
,
...
...
@@ -277,6 +158,8 @@ export default {
if
(
tileset
)
{
this
.
tileset
=
tileset
;
this
.
locateToTileset
();
// 添加鼠标点击事件监听器,用于控制人员信息label显示
this
.
addEntityClickHandler
();
}
}
catch
(
error
)
{
console
.
error
(
`加载倾斜摄影模型失败:
${
error
}
`
);
...
...
@@ -287,6 +170,7 @@ export default {
console
.
error
(
"
Cesium地图初始化失败:
"
,
error
);
}
},
/**
* 获取倾斜摄影模型的经纬度并将摄像机视角转向模型上方
*/
...
...
@@ -346,6 +230,8 @@ export default {
duration
:
2
,
// 过渡时间2秒
complete
:
()
=>
{
console
.
log
(
"
相机已成功定位到模型上方
"
);
// this.createPersonModel(); // 定位后创建人员模型
// 根据当前选择的类型创建相应的模型
this
.
createPersonModel
();
// 定位后创建人员模型
},
});
...
...
@@ -353,6 +239,261 @@ export default {
console
.
error
(
"
定位到模型上方失败:
"
,
error
);
}
},
personCardList
(
fn
)
{
// 将笛卡尔坐标转换为经纬度坐标
const
cartographic
=
Cesium
.
Cartographic
.
fromCartesian
({
x
:
-
2686273.730145489
,
y
:
4293961.185794622
,
z
:
3863430.5618300107
,
});
const
baseLongitude
=
Cesium
.
Math
.
toDegrees
(
cartographic
.
longitude
);
const
baseLatitude
=
Cesium
.
Math
.
toDegrees
(
cartographic
.
latitude
);
const
baseHeight
=
cartographic
.
height
+
1
;
console
.
log
(
"
人员经纬度基准点:
"
,
{
longitude
:
baseLongitude
,
latitude
:
baseLatitude
,
height
:
baseHeight
,
});
// 清除现有的人员列表
this
.
personnelList
=
[];
// 生成10个不同的经纬度坐标
const
maxOffset
=
0.00005
;
for
(
let
index
=
0
;
index
<
10
;
index
++
)
{
// 生成随机偏移量
const
lngOffset
=
(
Math
.
random
()
-
0.5
)
*
2
*
maxOffset
;
const
latOffset
=
(
Math
.
random
()
-
0.5
)
*
2
*
maxOffset
;
this
.
personnelList
.
push
({
lng
:
baseLongitude
+
lngOffset
,
lat
:
baseLatitude
+
latOffset
,
height
:
baseHeight
,
perName
:
"
张三
"
+
index
,
status
:
"
online
"
,
// 在线
avatar
:
"
/static/images/avatars/zhangsan.png
"
,
// 头像
});
}
fn
(
this
.
personnelList
);
},
// 修改:更新点击事件处理器,支持车辆显示
addEntityClickHandler
()
{
// 创建鼠标事件处理器
this
.
clickHandler
=
new
Cesium
.
ScreenSpaceEventHandler
(
this
.
viewer
.
canvas
);
// 监听鼠标左键点击事件
this
.
clickHandler
.
setInputAction
((
click
)
=>
{
// 检测点击位置的实体
const
pickedObject
=
this
.
viewer
.
scene
.
pick
(
click
.
position
);
// 修复条件判断:检查是否有info属性
if
(
Cesium
.
defined
(
pickedObject
)
&&
pickedObject
.
id
&&
pickedObject
.
id
.
info
)
{
// 获取点击的实体
const
entity
=
pickedObject
.
id
;
const
entityInfo
=
entity
.
info
;
// 如果已有详细信息label,则移除它
if
(
entity
.
detailLabel
)
{
this
.
viewer
.
entities
.
remove
(
entity
.
detailLabel
);
delete
entity
.
detailLabel
;
return
;
}
console
.
log
(
"
点击实体了
"
,
entityInfo
);
// 根据实体类型显示不同的信息
let
labelText
=
""
;
// 人员信息
labelText
=
`
${
entityInfo
.
perName
}
\n状态:
${
entityInfo
.
status
===
"
online
"
?
"
在线
"
:
"
离线
"
}
\n高度:
${
entityInfo
.
height
.
toFixed
(
2
)}
m`
;
// 创建详细信息label
const
detailLabel
=
this
.
viewer
.
entities
.
add
({
position
:
entity
.
position
.
getValue
(),
label
:
{
text
:
labelText
,
font
:
"
14px 微软雅黑
"
,
backgroundColor
:
Cesium
.
Color
.
fromCssColorString
(
"
#173349
"
),
showBackground
:
true
,
fillColor
:
Cesium
.
Color
.
WHITE
,
pixelOffset
:
new
Cesium
.
Cartesian2
(
0
,
-
60
),
eyeOffset
:
new
Cesium
.
Cartesian3
(
0
,
0
,
-
10
),
horizontalOrigin
:
Cesium
.
HorizontalOrigin
.
CENTER
,
verticalOrigin
:
Cesium
.
VerticalOrigin
.
TOP
,
scaleByDistance
:
new
Cesium
.
NearFarScalar
(
1000
,
1
,
500000
,
0.5
),
disableDepthTestDistance
:
Number
.
POSITIVE_INFINITY
,
// 确保始终显示在最前面
},
});
// 将详细信息label关联到实体,便于后续管理
entity
.
detailLabel
=
detailLabel
;
}
},
Cesium
.
ScreenSpaceEventType
.
LEFT_CLICK
);
},
// 处理窗口大小变化
handleResize
()
{
// 重新调整Cesium视图大小
if
(
this
.
viewer
)
{
this
.
viewer
.
resize
();
}
// 重新绘制图表
const
chartContainer
=
document
.
getElementById
(
"
trendChart
"
);
if
(
chartContainer
&&
chartContainer
.
firstChild
)
{
chartContainer
.
removeChild
(
chartContainer
.
firstChild
);
this
.
drawTrendChart
();
}
},
// 1. 提取通用实体创建函数
createEntity
(
item
,
type
)
{
const
isPerson
=
type
===
"
person
"
;
const
idField
=
isPerson
?
"
perName
"
:
"
vehicleName
"
;
const
labelColor
=
isPerson
?
Cesium
.
Color
.
YELLOW
:
Cesium
.
Color
.
CYAN
;
const
iconPath
=
isPerson
?
"
/poi-marker-default.png
"
:
"
/poi-marker-vehicle.png
"
;
let
lng
=
Number
(
item
.
lng
);
let
lat
=
Number
(
item
.
lat
);
let
height
=
Number
(
item
.
height
);
let
position
=
Cesium
.
Cartesian3
.
fromDegrees
(
lng
,
lat
,
height
);
console
.
log
(
item
[
idField
],
position
);
// 创建实体
let
entity
=
this
.
viewer
.
entities
.
add
({
position
:
position
,
label
:
{
text
:
item
[
idField
],
font
:
"
16px
"
,
backgroundColor
:
Cesium
.
Color
.
fromCssColorString
(
"
#173349
"
),
showBackground
:
true
,
fillColor
:
labelColor
,
depthTestAgainstTerrain
:
false
,
pixelOffset
:
new
Cesium
.
Cartesian2
(
0
,
-
35
),
},
billboard
:
{
image
:
iconPath
,
scale
:
0.5
,
heightReference
:
Cesium
.
HeightReference
.
CLAMP_TO_3D_TILE
,
},
description
:
`<div><h4>
${
item
[
idField
]}${
item
.
status
}
</h4></div>`
,
fixedFrame
:
Cesium
.
Transforms
.
eastNorthUpToFixedFrame
(
position
),
});
entity
.
info
=
item
;
entity
.
type
=
type
;
this
.
bgEntities
[
item
[
idField
]]
=
entity
;
return
entity
;
},
// 2. 提取实体更新函数
updateEntity
(
entity
,
item
)
{
let
position
=
Cesium
.
Cartesian3
.
fromDegrees
(
item
.
lng
,
item
.
lat
,
item
.
height
);
entity
.
position
.
setValue
(
position
);
entity
.
fixedFrame
=
Cesium
.
Transforms
.
eastNorthUpToFixedFrame
(
position
);
},
// 3. 提取批量创建实体的函数
createEntities
(
entityList
,
type
)
{
const
isPerson
=
type
===
"
person
"
;
const
idField
=
isPerson
?
"
perName
"
:
"
vehicleName
"
;
for
(
let
item
of
entityList
)
{
this
.
createEntity
(
item
,
type
);
}
},
// 4. 提取批量更新实体的函数(增量更新模式)
updateEntities
(
entityList
,
type
)
{
const
isPerson
=
type
===
"
person
"
;
const
idField
=
isPerson
?
"
perName
"
:
"
vehicleName
"
;
for
(
let
item
of
entityList
)
{
let
entity
=
this
.
bgEntities
[
item
[
idField
]];
if
(
entity
&&
entity
.
type
===
type
)
{
// 更新现有实体
this
.
updateEntity
(
entity
,
item
);
}
else
{
// 创建新实体
this
.
createEntity
(
item
,
type
);
}
}
},
// 5. 提取定时器逻辑为可重用函数
setupEntityUpdateInterval
(
type
,
dataGenerator
,
interval
=
10000
)
{
// 清除现有定时器
if
(
this
.
intervaler
)
{
clearInterval
(
this
.
intervaler
);
this
.
intervaler
=
null
;
}
// 设置新的定时器
this
.
intervaler
=
setInterval
(()
=>
{
console
.
log
(
`开始获取实时
${
type
===
"
person
"
?
"
人员
"
:
"
车辆
"
}
数据`
);
// 生成或获取最新数据
if
(
typeof
dataGenerator
===
"
function
"
)
{
dataGenerator
();
}
const
entityList
=
type
===
"
person
"
?
this
.
personnelList
:
this
.
vehicleList
;
// 更新实体(这里可以选择清除重建或增量更新)
// 方案1:清除所有实体后重建
this
.
clearEntities
();
this
.
createEntities
(
entityList
,
type
);
// 方案2:增量更新(推荐,性能更好)
// this.updateEntities(entityList, type);
},
interval
);
},
// 修改后的createPersonModel方法
createPersonModel
()
{
// 清除现有定时器
if
(
this
.
intervaler
)
{
clearInterval
(
this
.
intervaler
);
this
.
intervaler
=
null
;
}
// 清除现有实体
this
.
clearEntities
();
// 立即生成并显示人员实体
console
.
log
(
"
立即创建人员实体
"
);
this
.
personCardList
((
list
)
=>
{
console
.
log
(
"
人员数据
"
,
this
.
personnelList
);
this
.
createEntities
(
this
.
personnelList
,
"
person
"
);
});
// 设置定时刷新
this
.
setupEntityUpdateInterval
(
"
person
"
,
()
=>
{
this
.
personCardList
(()
=>
{
console
.
log
(
"
人员数据
"
,
this
.
personnelList
);
});
});
},
},
};
</
script
>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment