【cesium】在vue2中使用cesium(持续更新)
在vue2中使用cesium
- 在项目中使用步骤
- 1. npm install cesium --save
- 2. 接入项目 cesium
- 3. index.html中引入cesium
- 4. 完成后重启项目!
- 5. 定义组件并初始化一个简单的cesium
- 功能方法
- 1. 使用天地图影像
- 2. 销毁 cesium
- 3. 地图放大缩小
- 3. 获取可视区域、高度、层级
- 4. 搜索地名后定位到该位置(`高德地图搜索POI功能`)
- 4.1 实现效果图
- 4.2 搜索组件完整代码
- 4.3 cesium与高德地图经纬度不匹配导致定位偏移问题解决
- 4.3.1 安装coordtransform
- 4.3.2 封装转为WGS-84坐标的方法
- 4.3.3 组件中使用转换方法
- 4.4 [高德地图申请key](https://console.amap.com/dev/key/app)
- 5. 标注点添加鼠标移入显示其名称
- 5.1 实现效果图
- 5.2 tooltip组件完整代码
- 5.3 鼠标移入显示其名称-关键代码
在项目中使用步骤
1. npm install cesium --save
2. 接入项目 cesium
node_modules中找到cesium,复制build文件夹下Cesium文件夹到
public
文件夹下。复制完后就是下图
3. index.html中引入cesium
在项目
index.html
文件中,head 标签里面引入 cesium 的全局样式,在body标签中引入cesium 源码。
<link rel="stylesheet" href="./Cesium/Widgets/widgets.css">
<script type="text/javascript" src="./Cesium/Cesium.js"></script>
如下图:
4. 完成后重启项目!
5. 定义组件并初始化一个简单的cesium
<template>
<div id="my-map"></div>
</template>
<script>
export default {
name: "CesiumView",
methods: {
init() {
this.viewer = new Cesium.Viewer("my-map", {
homeButton: false,
sceneModePicker: false,
baseLayerPicker: false, // 影像切换
animation: true, // 是否显示动画控件
infoBox: false, // 是否显示点击要素之后显示的信息
selectionIndicator: false, // 要素选中框
geocoder: false, // 是否显示地名查找控件
timeline: true, // 是否显示时间线控件
fullscreenButton: false,
shouldAnimate: false,
navigationHelpButton: false, // 是否显示帮助信息控件
});
},
},
mounted() {
this.init();
},
};
</script>
<style scoped>
#my-map {
width: 100%;
height: 100%;
background-color: black;
}
</style>
功能方法
1. 使用天地图影像
const imageLayers = this.viewer.scene.imageryLayers;
imageLayers.remove(imageLayers.get(0)); //移除默认影像图层
const TDTTK = "key"; //填入你自己的天地图Key
// 天地图影像
const tdtLayer = new Cesium.WebMapTileServiceImageryProvider({
url: `http://t0.tianditu.com/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=${TDTTK}`,
layer: "tdt",
style: "default",
format: "image/jpeg",
tileMatrixSetID: "w",
maximumLevel: 18,
show: false,
});
this.viewer.imageryLayers.addImageryProvider(tdtLayer);
// 天地图注记
const tdtAnnotionLayer = new Cesium.WebMapTileServiceImageryProvider({
url: `http://t0.tianditu.com/cia_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=${TDTTK}`,
layer: "tdtAnno",
style: "default",
format: "image/jpeg",
tileMatrixSetID: "w",
maximumLevel: 18,
show: false,
});
this.viewer.imageryLayers.addImageryProvider(tdtAnnotionLayer);
使用天地图影像完整初始化代码如下:
<template>
<div id="my-map"></div>
</template>
<script>
export default {
name: "CesiumView",
data() {
return {
TDT_SL: null,
};
},
methods: {
init() {
Cesium.Ion.defaultAccessToken =
"cesium_key";
this.viewer = new Cesium.Viewer("my-map", {
homeButton: true,
sceneModePicker: true,
baseLayerPicker: true, // 影像切换
animation: false, // 是否显示动画控件
infoBox: false, // 是否显示点击要素之后显示的信息
selectionIndicator: false, // 要素选中框
geocoder: true, // 是否显示地名查找控件
timeline: false, // 是否显示时间线控件
fullscreenButton: false,
shouldAnimate: false,
navigationHelpButton: false, // 是否显示帮助信息控件
});
// 注释版权信息
this.viewer._cesiumWidget._creditContainer.style.display = "none";
const imageLayers = this.viewer.scene.imageryLayers;
imageLayers.remove(imageLayers.get(0)); //移除默认影像图层
const TDTTK = "key"; //填入你自己的天地图Key
// 天地图影像
const tdtLayer = new Cesium.WebMapTileServiceImageryProvider({
url: `http://t0.tianditu.com/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=${TDTTK}`,
layer: "tdt",
style: "default",
format: "image/jpeg",
tileMatrixSetID: "w",
maximumLevel: 18,
show: false,
});
this.viewer.imageryLayers.addImageryProvider(tdtLayer);
// 天地图注记
const tdtAnnotionLayer = new Cesium.WebMapTileServiceImageryProvider({
url: `http://t0.tianditu.com/cia_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={TileMatrix}&TILEROW={TileRow}&TILECOL={TileCol}&tk=${TDTTK}`,
layer: "tdtAnno",
style: "default",
format: "image/jpeg",
tileMatrixSetID: "w",
maximumLevel: 18,
show: false,
});
this.viewer.imageryLayers.addImageryProvider(tdtAnnotionLayer);
},
},
mounted() {
this.init();
},
};
</script>
<style scoped>
#my-map {
width: 100%;
height: 100%;
background-color: black;
}
</style>
2. 销毁 cesium
this.viewer.destroy()
3. 地图放大缩小
cesium 的放大缩小和百度地图他们不一样。cesium 的放大缩小其实就是相机高度,相机高度变小就是放大,相机高度变大就是缩小。理解吧?相机高了,视角大了,蓝星上面东西就小了。
/**
* 地图放大
*/
zoomIn() {
// viewer 为 Viewer 对象
let position = this.viewer.camera.position;
let cameraHeight = this.viewer.scene.globe.ellipsoid.cartesianToCartographic(position).height;
// 每次缩小 20 倍,参数可改
let moveRate = cameraHeight / 20.0;
this.viewer.camera.moveForward(moveRate);
}
/**
* 地图缩小
*/
zoomOut() {
// viewer 为 Viewer 对象
let position = this.viewer.camera.position;
let cameraHeight = this.viewer.scene.globe.ellipsoid.cartesianToCartographic(position).height;
// 每次缩小 20 倍,参数可改
let moveRate = cameraHeight / 20.0;
this.viewer.camera.moveBackward(moveRate);
}
3. 获取可视区域、高度、层级
let rectangle = this.viewer.camera.computeViewRectangle();
- 转换为地理坐标:
let rectangle = this.viewer.camera.computeViewRectangle();
let east = Cesium.Math.toDegrees(rectangle.east).toFixed(6); // 转地理坐标
console.log(rectangle, east)
- 获取相机高度,单位是米哈:
let height = Math.ceil(this.viewer.camera.positionCartographic.height).toFixed(0);
console.log("相机高度----->> ", height)
- 获取层级:
let zoom = this.heightToZoom(height).toFixed(0)
console.log("层级----->> ", zoom)
// 定义的方法
heightToZoom(height) {
let A = 40487.57;
let B = 0.00007096758;
let C = 91610.74;
let D = -40467.74;
return Math.round(D + (A - D) / (1 + Math.pow(height / C, B)));
}
4. 搜索地名后定位到该位置(高德地图搜索POI功能
)
4.1 实现效果图
4.2 搜索组件完整代码
<template>
<div class="bs-search">
<div class="bs-title">
<div class="title">搜索</div>
<span class="el-icon-close" @click="searchHandle"></span>
</div>
<div class="search-box">
<div style="margin-top: 15px">
<el-select
v-model="inputV"
filterable
remote
reserve-keyword
placeholder="请输入"
:remote-method="remoteMethod"
:loading="loading"
@change="changeFun"
>
<el-option
v-for="item in options"
:key="item.location"
:label="item.name"
:value="item.location"
>
</el-option>
</el-select>
</div>
</div>
</div>
</template>
<script>
import { mapState, mapMutations } from "vuex";
import searchIcon from "@/assets/largeScreen/searchIcon.png";
import { gcj02ToWgs84 } from "@/utils/coordtransform.js";
export default {
computed: {
...mapState({
bsParams: (state) => state.Layout.bsParams,
}),
},
data() {
return {
inputV: "",
loading: false,
options: [],
lastEntity: null,
};
},
methods: {
...mapMutations(["searchHandle"]),
async remoteMethod(query) {
if (!query) return;
this.loading = true;
try {
const response = await fetch(
`https://restapi.amap.com/v5/place/text?key=${你的高德key}&keywords=${query}`
);
const res = await response.json();
this.options = res?.pois || [];
} catch (error) {
console.error(error);
} finally {
this.loading = false;
}
},
changeFun(val) {
const location = val.split(",");
if (location.length !== 2) {
console.error("无效坐标: ", val);
return;
}
const [longitudeStr, latitudeStr] = location;
const longitude = parseFloat(longitudeStr.trim());
const latitude = parseFloat(latitudeStr.trim());
if (isNaN(longitude) || isNaN(latitude)) {
console.error("无效坐标: ", val);
return;
}
const [wgsLng, wgsLat] = gcj02ToWgs84(longitude, latitude);
if (this.lastEntity) {
window.viewer.entities.remove(this.lastEntity);
this.lastEntity = null;
}
window.viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(wgsLng, wgsLat, 1000),
});
this.lastEntity = window.viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(wgsLng, wgsLat),
billboard: {
image: searchIcon,
width: 32,
height: 32,
scale: 1.0,
disableDepthTestDistance: Number.POSITIVE_INFINITY, // 避免图标被地形遮挡
},
});
},
},
};
</script>
<style lang="scss" scoped>
.bs-search {
background-color: rgba(19, 37, 69, 0.6);
padding: 1.25rem;
border-radius: 0.25rem;
.bs-title{
display: flex;
justify-content: space-between;
align-items: center;
color: #fff;
.title {
font-family: PangMenZhengDao;
font-size: 1.125rem;
}
span {
font-weight: 700;
font-size: 1.125rem;
cursor: pointer;
}
.title:before {
content: "";
display: inline-block;
width: 0.375rem;
height: 1rem;
margin-right: 0.25rem;
background-color: #3ba0ff;
}
}
.search-box {
margin: 0.625rem 0;
.el-select .el-input {
width: 130px;
}
.input-with-select .el-input-group__prepend {
background-color: #fff;
}
}
}
</style>
4.3 cesium与高德地图经纬度不匹配导致定位偏移问题解决
4.3.1 安装coordtransform
npm install coordtransform
4.3.2 封装转为WGS-84坐标的方法
import { gcj02towgs84 } from "coordtransform";
// 修正后的 WGS-84 坐标
export function gcj02ToWgs84(lng, lat) {
return gcj02towgs84(lng, lat);
}
4.3.3 组件中使用转换方法
import { gcj02ToWgs84 } from "@/utils/coordtransform.js"; // 引入
const [wgsLng, wgsLat] = gcj02ToWgs84(longitude, latitude); // 调用
4.4 高德地图申请key
5. 标注点添加鼠标移入显示其名称
5.1 实现效果图
5.2 tooltip组件完整代码
<template>
<div id="tooltip"></div>
</template>
<style scoped>
#tooltip {
position: absolute;
background: #fff;
padding: 5px 10px;
border: 1px solid #ccc;
border-radius: 3px;
pointer-events: none;
display: none;
font-family: Arial, sans-serif;
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2);
z-index: 9999;
}
</style>
5.3 鼠标移入显示其名称-关键代码
// 创建工具提示元素
const tooltip = document.getElementById("tooltip");
// 初始化屏幕空间事件处理器
const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
// 监听鼠标移动事件
handler.setInputAction((movement) => {
// 检测当前鼠标位置的实体
const picked = viewer.scene.pick(movement.endPosition);
if (Cesium.defined(picked) && picked.id && picked.id.name) {
// 获取名称并更新工具提示
tooltip.innerHTML = picked.id.name;
tooltip.style.display = "block";
// 将鼠标坐标转换为Canvas坐标
const canvasPosition =
Cesium.SceneTransforms.wgs84ToWindowCoordinates(
viewer.scene,
picked.id.position.getValue(viewer.clock.currentTime)
);
if (canvasPosition) {
// 定位工具提示
tooltip.style.left = `${canvasPosition.x + 10}px`;
tooltip.style.top = `${canvasPosition.y + 10}px`;
}
} else {
tooltip.style.display = "none";
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
参考文章:https://blog.csdn.net/qq_46123200/article/details/146258229