官方示例:
- Callback Property - 计算线段长度 文字居中
- Billboards + Points - 往地图上加点
- Labels + Map Pins + Picking - 往地球上加标签
- Polyline - 连线
- Polyline Dash + Polygon - 画面
功能描述:
- 选择测距,点击地图,出现点并显示标号,两点间以线连接,线端中间显示距离,点击右键结束测量
- 选择测量面积,点击地图,出现点并显示标号,两点间以线连接,三点及以上成面,围成的面积的具体数据显示在中心,点击右键结束测量
- 选择清空绘制,地图上的标记全部消失
功能代码:
1、初始化
Init () {
// 引入个人token
= 'xxxx'
// 设置取景器
= new ('cesiumContainer', {
terrainProvider: (),
selectionIndicator: false, // 不显示指示器小部件
infoBox: false, // 不显示信息框
sceneModePicker: false, // 不显示模式切换选项
baseLayerPicker: false,
navigationHelpButton: false,
animation: false,
shouldAnimate: false,
timeline: false,
geocoder: false,
homeButton: false,
// 添加ArcGIS在线影像底图
imageryProvider: new ({
url: '/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
subdomains: ['0', '1', '2', '3'],
tilingScheme: new ()
})
})
// 若浏览器不支持pickPosition,显示报错信息
if (!) {
('This browser does not support pickPosition.')
}
// 载入OSM建筑物
// const osmBuildings = (()) // eslint-disable-line no-unused-vars
// 初始化镜头
(
Cesium.(-122.2058, 46.1955, 1000.0),
new Cesium.Cartesian3(5000.0, 5000.0, 5000.0)
)
(Cesium.)
}
2、测距
/* 空间两点距离计算函数 */
getLength (start, end) {
// 将起点与终点位置信息从笛卡尔坐标形式转换为Cartographic形式
let startCartographic = (start)
let endCartographic = (end)
// 初始化测地线
let geodesic = new ()
// 设置测地线起点和终点,EllipsoidGeodesic中setEndPoints常与surfaceDistance搭配使用
(startCartographic, endCartographic)
// 获取起点和终点之间的表面距离,单位为km,规定四舍五入保留两位小数
// surfaceDistance返回number 单位为m,带小数
// (( / 1000).toFixed(2))
return ( / 1000).toFixed(2)
},
/* 空间两点计算中点函数 */
getMidpoint (start, end) {
let startPoint = (start)
let endPoint = (end)
let geodesic = new ()
(startPoint, endPoint)
let geoPoint = (0.5)
(.(geoPoint))
return .(geoPoint)
},
/* 在线段中点处添加标签,显示长度 */
addLabel (midPoint, labelLength) {
let viewer =
return ({
name: '中点',
position: midPoint,
label: {
text: labelLength + 'km',
font: '20px sans-serif',
fillColor: ,
outlineWidth: 2,
backgroundColor: ,
showBackground: true,
style: ,
verticalOrigin: ,
horizontalOrigin: ,
heightReference: .CLAMP_TO_GROUND,
disableDepthTestDistance: Number.POSITIVE_INFINITY
}
})
},
3、测面
/* 测量空间面积 */
// 方向
Bearing (from, to) {
let fromCartographic = (from)
let toCartographic = (to)
let lat1 =
let lon1 =
let lat2 =
let lon2 =
let angle = -Math.atan2((lon1 - lon2) * (lat2), (lat1) * (lat2) - (lat1) * (lat2) * (lon1 - lon2))
if (angle < 0) {
angle += * 2.0
}
return angle
},
// 角度
pointAngle (point1, point2, point3) {
let bearing21 = (point2, point1)
let bearing23 = (point2, point3)
let angle = bearing21 - bearing23
if (angle < 0) {
angle += * 2.0
}
return angle
},
/* 计算空间面积 */
getArea (positions) {
let res = 0
for (let i = 0; i < - 2; i++) {
let j = (i + 1) %
let k = (i + 2) %
let totalAngle = (positions[i], positions[j], positions[k])
let tempLength1 = (positions[j], positions[0])
let tempLength2 = (positions[k], positions[0])
res += tempLength1 * tempLength2 * (totalAngle) / 2
}
res = (2)
// (res)
res = parseFloat(res)
// ((res))
return (res)
},
/* 在最后一个点处添加标签,显示面积 */
addArea (area, positions) {
let viewer =
return ({
name: '多边形面积',
position: positions[ - 1],
label: {
text: area + '平方公里',
font: '20px sans-serif',
fillColor: ,
outlineWidth: 2,
backgroundColor: ,
showBackground: true,
style: ,
pixelOffset: new Cesium.Cartesian2(60, -60),
verticalOrigin: ,
horizontalOrigin: ,
heightReference: .CLAMP_TO_GROUND,
disableDepthTestDistance: Number.POSITIVE_INFINITY
}
})
}
4、地图生成线和面部分
/* 绘制函数 */
drawPointLabel (position, pointNum) {
let viewer =
// 本质上就是添加一个点的实体
return ({
name: '点几何对象',
position: position,
point: {
color: ,
pixelSize: 5,
outlineWidth: 3,
disableDepthTestDistance: Number.POSITIVE_INFINITY, //
heightReference: .CLAMP_TO_GROUND // 规定贴地
},
label: {
text: pointNum,
font: '30px sans-serif',
fillColor: ,
outlineWidth: 2,
backgroundColor: ,
showBackground: true,
style: ,
verticalOrigin: ,
horizontalOrigin:
}
})
},
drawPoint (position) {
let viewer =
// 本质上就是添加一个点的实体
return ({
position: position,
point: {
color: ,
pixelSize: 5,
outlineWidth: 3,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
heightReference: .CLAMP_TO_GROUND // 规定贴地
}
})
},
drawPolyline (positions) {
let viewer =
if ( < 1) return
return ({
name: '线几何对象',
polyline: {
positions: positions,
width: 5.0,
material: new ({
// eslint-disable-next-line new-cap
color:
}),
depthFailMaterial: new ({
// eslint-disable-next-line new-cap
color:
}),
clampToGround: true
}
})
},
drawPolygon (positions) {
let viewer =
if ( < 2) return
return ({
name: '面几何对象',
polygon: {
hierarchy: positions,
// eslint-disable-next-line new-cap
material: new (
(0.4)
)
}
})
},
5、清除绘制
/* 清除实体 */
clearAllDrawn () {
let viewer =
= []
= 0
()
},
created () {
},
6、按钮绑定
/* 根据类型绘制对象
* @param type point polyline polygon */
draw (type) {
let that = this
let viewer =
// let pointNum =
// (pointNum)
let tempEntities =
let floatingPoint =
let activeShape =
let position = []
let tempPoints = []
let activeShapePoints = []
// 开启深度检测
= true
// 创建场景的HTML canvas元素
let handler = new ()
switch (type) {
// 绘制线
case 'Polyline':
// 取消鼠标双击事件
(.LEFT_DOUBLE_CLICK)
// 监听鼠标移动
(function (movement) {
if ((floatingPoint)) {
let newPosition = ()
if ((newPosition)) {
(newPosition)
()
(newPosition)
}
}
}, .MOUSE_MOVE)
// 左键单击开始画线
(function (click) {
let earthPosition = ()
if ((earthPosition)) {
floatingPoint = (earthPosition)
}
// 获取位置信息
// 从相机位置创建一条射线,这条射线通过世界中像素所在的坐标,返回Cartesian3坐标
let ray = ()
// 找到射线与渲染的地球表面之间的交点。射线必须以世界坐标给出。返回Cartesian3坐标
position = (ray, )
(position) // 记录点位
+= 1
let tempLength = // 记录点数
// 调用绘制点的接口
let point = (tempPoints[ - 1], ())
(point)
// 存在超过一个点时
if (tempLength > 1) {
// 绘制线
let pointLength = (tempPoints[ - 2], tempPoints[ - 1])
let midPosition = (tempPoints[ - 2], tempPoints[ - 1])
let pointline = ([tempPoints[ - 2], tempPoints[ - 1]])
let pointLabel = (midPosition, pointLength)
(pointline) // 保存记录
(pointLabel)
}
}, .LEFT_CLICK)
// 右键单击结束画线
(function (click) {
()
()
(activeShapePoints)
(floatingPoint)
tempPoints = [] // 清空点位记录
()
handler = null
floatingPoint = undefined
activeShape = undefined
activeShapePoints = []
()
}, .RIGHT_CLICK)
break
// 绘制面
case 'Polygon':
// 取消鼠标双击事件
(.LEFT_DOUBLE_CLICK)
// 监听鼠标移动
(function (movement) {
if ((floatingPoint)) {
let newPosition = ()
if ((newPosition)) {
(newPosition)
()
(newPosition)
}
}
}, .MOUSE_MOVE)
// 左键单击开始画线
(function (click) {
let earthPosition = ()
if ((earthPosition)) {
if ( === 0) {
floatingPoint = (earthPosition)
(earthPosition)
const dynamicPositions = new (function () {
return new (activeShapePoints)
}, false)
activeShape = (dynamicPositions)
}
(earthPosition)
}
// 获取位置信息
let ray = ()
position = (ray, )
(position) // 记录点位
let tempLength = // 记录点数
+= 1
// 调用绘制点的接口
let point = (tempPoints[ - 1], ())
(point)
// 存在超过一个点时
if (tempLength > 1) {
// 绘制线
let pointline = ([tempPoints[ - 2], tempPoints[ - 1]])
(pointline) // 保存记录
}
}, .LEFT_CLICK)
// 右键单击结束画面
(function (click) {
// 选择一个椭球或地图
let cartesian = (, )
if (cartesian) {
let tempLength =
if (tempLength < 3) {
alert('闭合操作需要至少3个点嗷')
} else {
// 闭合最后一条线
let pointline = ([tempPoints[0], tempPoints[ - 1]])
(pointline)
(tempPoints)
let pointArea = (tempPoints)
((pointArea), tempPoints)
(tempPoints)
()
handler = null
}
}
()
(activeShapePoints)
(floatingPoint)
floatingPoint = undefined
activeShapePoints = []
}, .RIGHT_CLICK)
break
}
}
7、完整代码(可直接引用查看Demo效果)
<template>
<div >
<div ></div>
<div class="btnContainer">
<button @click="draw('Polyline')">标点测距</button>
<button @click="draw('Polygon')">标点测面</button>
<button @click="clearAllDrawn()">清空数据</button>
<div class="tip">
<p>点击按钮后,在场景内单击左键标点,单击右键结束测量。</p>
<p>点击“标点测距”按钮后在场景内单击鼠标左键加点,在两点间显示距离,单击右键结束测量。</p>
<p>点击“标点测面”按钮后在场景内单击鼠标左键加点,单击右键在勾出的范围中显示面积。</p>
<p>点击“清空数据”按钮删除所有数据。</p>
</div>
</div>
</div>
</template>
<script>
import * as Cesium from 'cesium/Cesium'
import * as widgets from 'cesium/Widgets/'
export default {
name: 'App',
data () {
return {
viewer: undefined,
tempEntities: [],
pointNum: 0,
floatingPoint: undefined,
activeShape: undefined
}
},
mounted () {
()
},
methods: {
/* 初始化 */
Init () {
// 引入个人token
= 'xxxx'
// 设置取景器
= new ('cesiumContainer', {
terrainProvider: (),
selectionIndicator: false, // 不显示指示器小部件
infoBox: false, // 不显示信息框
sceneModePicker: false, // 不显示模式切换选项
baseLayerPicker: false,
navigationHelpButton: false,
animation: false,
shouldAnimate: false,
timeline: false,
geocoder: false,
homeButton: false,
// 添加ArcGIS在线影像底图
imageryProvider: new ({
url: '/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
subdomains: ['0', '1', '2', '3'],
tilingScheme: new ()
})
})
// 若浏览器不支持pickPosition,显示报错信息
if (!) {
('This browser does not support pickPosition.')
}
// 载入OSM建筑物
// const osmBuildings = (()) // eslint-disable-line no-unused-vars
// 初始化镜头
(
Cesium.(-122.2058, 46.1955, 1000.0),
new Cesium.Cartesian3(5000.0, 5000.0, 5000.0)
)
(Cesium.)
},
/* 空间两点距离计算函数 */
getLength (start, end) {
// 将起点与终点位置信息从笛卡尔坐标形式转换为Cartographic形式
let startCartographic = (start)
let endCartographic = (end)
// 初始化测地线
let geodesic = new ()
// 设置测地线起点和终点,EllipsoidGeodesic中setEndPoints常与surfaceDistance搭配使用
(startCartographic, endCartographic)
// 获取起点和终点之间的表面距离,单位为km,规定四舍五入保留两位小数
// surfaceDistance返回number 单位为m,带小数
// (( / 1000).toFixed(2))
return ( / 1000).toFixed(2)
},
/* 空间两点计算中点函数 */
getMidpoint (start, end) {
let startPoint = (start)
let endPoint = (end)
let geodesic = new ()
(startPoint, endPoint)
let geoPoint = (0.5)
(.(geoPoint))
return .(geoPoint)
},
addLabel (midPoint, labelLength) {
let viewer =
return ({
name: '中点',
position: midPoint,
label: {
text: labelLength + 'km',
font: '20px sans-serif',
fillColor: ,
outlineWidth: 2,
backgroundColor: ,
showBackground: true,
style: ,
verticalOrigin: ,
horizontalOrigin: ,
heightReference: .CLAMP_TO_GROUND,
disableDepthTestDistance: Number.POSITIVE_INFINITY
}
})
},
/* 测量空间面积 */
// 方向
Bearing (from, to) {
let fromCartographic = (from)
let toCartographic = (to)
let lat1 =
let lon1 =
let lat2 =
let lon2 =
let angle = -Math.atan2((lon1 - lon2) * (lat2), (lat1) * (lat2) - (lat1) * (lat2) * (lon1 - lon2))
if (angle < 0) {
angle += * 2.0
}
return angle
},
// 角度
pointAngle (point1, point2, point3) {
let bearing21 = (point2, point1)
let bearing23 = (point2, point3)
let angle = bearing21 - bearing23
if (angle < 0) {
angle += * 2.0
}
return angle
},
getArea (positions) {
let res = 0
for (let i = 0; i < - 2; i++) {
let j = (i + 1) %
let k = (i + 2) %
let totalAngle = (positions[i], positions[j], positions[k])
let tempLength1 = (positions[j], positions[0])
let tempLength2 = (positions[k], positions[0])
res += tempLength1 * tempLength2 * (totalAngle) / 2
}
res = (2)
// (res)
res = parseFloat(res)
// ((res))
return (res)
},
addArea (area, positions) {
let viewer =
return ({
name: '多边形面积',
position: positions[ - 1],
label: {
text: area + '平方公里',
font: '20px sans-serif',
fillColor: ,
outlineWidth: 2,
backgroundColor: ,
showBackground: true,
style: ,
pixelOffset: new Cesium.Cartesian2(60, -60),
verticalOrigin: ,
horizontalOrigin: ,
heightReference: .CLAMP_TO_GROUND,
disableDepthTestDistance: Number.POSITIVE_INFINITY
}
})
},
/* 绘制函数 */
drawPointLabel (position, pointNum) {
let viewer =
// 本质上就是添加一个点的实体
return ({
name: '点几何对象',
position: position,
point: {
color: ,
pixelSize: 5,
outlineWidth: 3,
disableDepthTestDistance: Number.POSITIVE_INFINITY, //
heightReference: .CLAMP_TO_GROUND // 规定贴地
},
label: {
text: pointNum,
font: '30px sans-serif',
fillColor: ,
outlineWidth: 2,
backgroundColor: ,
showBackground: true,
style: ,
verticalOrigin: ,
horizontalOrigin:
}
})
},
drawPoint (position) {
let viewer =
// 本质上就是添加一个点的实体
return ({
position: position,
point: {
color: ,
pixelSize: 5,
outlineWidth: 3,
disableDepthTestDistance: Number.POSITIVE_INFINITY,
heightReference: .CLAMP_TO_GROUND // 规定贴地
}
})
},
drawPolyline (positions) {
let viewer =
if ( < 1) return
return ({
name: '线几何对象',
polyline: {
positions: positions,
width: 5.0,
material: new ({
// eslint-disable-next-line new-cap
color:
}),
depthFailMaterial: new ({
// eslint-disable-next-line new-cap
color:
}),
clampToGround: true
}
})
},
drawPolygon (positions) {
let viewer =
if ( < 2) return
return ({
name: '面几何对象',
polygon: {
hierarchy: positions,
// eslint-disable-next-line new-cap
material: new (
(0.4)
)
}
})
},
/* 清除实体 */
clearAllDrawn () {
let viewer =
= []
= 0
()
},
created () {
},
/* 根据类型绘制对象
* @param type point polyline polygon */
draw (type) {
let that = this
let viewer =
// let pointNum =
// (pointNum)
let tempEntities =
let floatingPoint =
let activeShape =
let position = []
let tempPoints = []
let activeShapePoints = []
// 开启深度检测
= true
// 创建场景的HTML canvas元素
let handler = new ()
switch (type) {
// 绘制线
case 'Polyline':
// 取消鼠标双击事件
(.LEFT_DOUBLE_CLICK)
// 监听鼠标移动
(function (movement) {
if ((floatingPoint)) {
let newPosition = ()
if ((newPosition)) {
(newPosition)
()
(newPosition)
}
}
}, .MOUSE_MOVE)
// 左键单击开始画线
(function (click) {
let earthPosition = ()
if ((earthPosition)) {
floatingPoint = (earthPosition)
}
// 获取位置信息
// 从相机位置创建一条射线,这条射线通过世界中像素所在的坐标,返回Cartesian3坐标
let ray = ()
// 找到射线与渲染的地球表面之间的交点。射线必须以世界坐标给出。返回Cartesian3坐标
position = (ray, )
(position) // 记录点位
+= 1
let tempLength = // 记录点数
// 调用绘制点的接口
let point = (tempPoints[ - 1], ())
(point)
// 存在超过一个点时
if (tempLength > 1) {
// 绘制线
let pointLength = (tempPoints[ - 2], tempPoints[ - 1])
let midPosition = (tempPoints[ - 2], tempPoints[ - 1])
let pointline = ([tempPoints[ - 2], tempPoints[ - 1]])
let pointLabel = (midPosition, pointLength)
(pointline) // 保存记录
(pointLabel)
}
}, .LEFT_CLICK)
// 右键单击结束画线
(function (click) {
()
()
(activeShapePoints)
(floatingPoint)
tempPoints = [] // 清空点位记录
()
handler = null
floatingPoint = undefined
activeShape = undefined
activeShapePoints = []
()
}, .RIGHT_CLICK)
break
// 绘制面
case 'Polygon':
// 取消鼠标双击事件
(.LEFT_DOUBLE_CLICK)
// 监听鼠标移动
(function (movement) {
if ((floatingPoint)) {
let newPosition = ()
if ((newPosition)) {
(newPosition)
()
(newPosition)
}
}
}, .MOUSE_MOVE)
// 左键单击开始画线
(function (click) {
let earthPosition = ()
if ((earthPosition)) {
if ( === 0) {
floatingPoint = (earthPosition)
(earthPosition)
const dynamicPositions = new (function () {
return new (activeShapePoints)
}, false)
activeShape = (dynamicPositions)
}
(earthPosition)
}
// 获取位置信息
let ray = ()
position = (ray, )
(position) // 记录点位
let tempLength = // 记录点数
+= 1
// 调用绘制点的接口
let point = (tempPoints[ - 1], ())
(point)
// 存在超过一个点时
if (tempLength > 1) {
// 绘制线
let pointline = ([tempPoints[ - 2], tempPoints[ - 1]])
(pointline) // 保存记录
}
}, .LEFT_CLICK)
// 右键单击结束画面
(function (click) {
// 选择一个椭球或地图
let cartesian = (, )
if (cartesian) {
let tempLength =
if (tempLength < 3) {
alert('闭合操作需要至少3个点嗷')
} else {
// 闭合最后一条线
let pointline = ([tempPoints[0], tempPoints[ - 1]])
(pointline)
(tempPoints)
let pointArea = (tempPoints)
((pointArea), tempPoints)
(tempPoints)
()
handler = null
}
}
()
(activeShapePoints)
(floatingPoint)
floatingPoint = undefined
activeShapePoints = []
}, .RIGHT_CLICK)
break
}
}
}
}
</script>
<style>
html,
body {
width: 100%;
height: 100%;
padding: 0;
margin: 0;
}
#app,#cesiumContainer {
font-family: "Avenir", Helvetica, Arial, sans-serif;
width: 100%;
height: 100%;
overflow: hidden;
}
.btnContainer {
position: absolute;
left: 15px;
top: 80px;
padding: 10px 15px;
/*添加圆角边框*/
border-radius: 5px;
border: 1px solid rgba(128,128,128, 0.5);
color: #ffffff;
background: rgba(0, 0, 0,0.4);
box-shadow: 0 4px 8px rgb(128 128 128 / 50%);
max-width: 300px;
}
button {
background: transparent;
border: 1px solid #00d0ffb8;
color: white;
padding: 7px 9px;
border-radius: 3px;
cursor: pointer;
}
.tip p{
margin: 2px 0px;
padding: 5px 1px;
}
</style>