cesium1.95版本结合typescript整合vue版本配置搭建开发环境,开箱即用
需要项目代码架子可以联系博主
vue.config.js
const {defineConfig} = require('@vue/cli-service')
const CopyWebpackPlugin = require("copy-webpack-plugin");
const webpack = require("webpack");
const path = require("path");
let cesiumSource = "./node_modules/cesium/Source";
let cesiumWorkers = "Workers";
module.exports = defineConfig({
transpileDependencies: true,
lintOnSave: false,
configureWebpack: {
externals: {
'cesium': 'Cesium',
},
output: {
sourcePrefix: " ", // 让webpack 正确处理多行字符串配置 amd参数
},
amd: {
toUrlUndefined: true, // webpack在cesium中能友好的使用require
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
"@": path.resolve("src"),
cesium: path.resolve(__dirname, cesiumSource),
}
},
plugins: [
new CopyWebpackPlugin({
patterns: [
{from: path.join(cesiumSource, cesiumWorkers), to: "Workers"},
{from: path.join(cesiumSource, "Assets"), to: "Assets"},
{from: path.join(cesiumSource, "Widgets"), to: "Widgets"},
{from: path.join(cesiumSource, "ThirdParty/Workers"), to: "ThirdParty/Workers"}
]
}),
new webpack.DefinePlugin({
CESIUM_BASE_URL: JSON.stringify("./"),
}),
],
module: {
unknownContextCritical: false,
unknownContextRegExp: /\/cesium\/cesium\/Source\/Core\/buildModuleUrl\.js/,
rules: [
{
test: /\.js$/,
use: {
loader: '@open-wc/webpack-import-meta-loader',
},
},
]
},
},
devServer: {
hot: true,
open: true,
// 代理
proxy: {
'/api': {
target: 'http://localhost:8080/',
changeOrigin: true,
ws: true,
pathRewrite: {
'^/api': ''
}
}
},
port: 9999,
}
})
main.ts
import Vue from 'vue'
import App from './App.vue'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import 'cesium/Widgets/widgets.css';
Vue.config.productionTip = false
Vue.use(ElementUI);
new Vue({
render: h => h(App),
}).$mount('#app')
helloworld.vue
<template>
<div style="width: 100%;height: 100%;">
<div id="cesiumContainer">
</div>
</div>
</template>
<script lang="ts">
import {Component, Vue} from 'vue-property-decorator'; // ts装饰器
import axios from 'axios';
import FeatureSilhouette from '../FeatureSilhouette'
import CustomBubbleWindow from './CustomBubbleWindow.vue'
@Component({
components: {CustomBubbleWindow},
})
export default class HelloWorld extends Vue {
private options: any = {
url: "/model/8564/tileset.json",
maximumScreenSpaceError: 20, //最大屏幕空间误差
maximumNumberOfLoadedTiles: 10000, //最大加载瓦片个数
}
private selectedFeature: any;
private elementMap: any = {};
public viewer: any = null;
private params: any = {}
private bathElements: any = [];//加载模型时使用的批量入库的
private bathParams: any = [];
private childThis: any = null;//子组件
private keyword: any = null;//搜索的关键词
private isSearch: boolean = false;
private records: any = [];//搜索的记录
mounted() {
this.viewer = new Cesium.Viewer('cesiumContainer', {
animation: false, //左下角的动画仪表盘
baseLayerPicker: false, //右上角的图层选择按钮
geocoder: false, //搜索框
homeButton: false, //home按钮
sceneModePicker: false, //模式切换按钮
timeline: false, //底部的时间轴
navigationHelpButton: false, //右上角的帮助按钮,
fullscreenButton: false, //右下角的全屏按钮
infoBox: false
})
// 去除版权信息
this.viewer._cesiumWidget._creditContainer.style.display = "none";
//加载模型
this.viewer.scene.primitives.add(new Cesium.Cesium3DTileset(this.options)).readyPromise.then((tileset: any) => {
//监听加载与卸载bim
tileset.tileLoad.addEventListener((tile: any) => {
this.processTileFeatures(tile, this.loadFeature);
});
//视口定位
this.viewer.zoomTo(tileset, new Cesium.HeadingPitchRange(0.0, -0.5, tileset.boundingSphere.radius * 4));
})
//描边
let featureSilhouette = new FeatureSilhouette(this.viewer);
featureSilhouette.initHighLightSilhouette(this.clickCallBack);
}
//接收子组件对象
childThisReceive(childThis: any) {
this.childThis = childThis
}
//选中回调函数
private selectedCallBack(feature: any) {
}
//鼠标点击回调
private clickCallBack(feature: any, position: any) {
console.log(feature.getProperty("element"));
console.log(position)
//显示点击查询到的面板
this.childThis.showInfo(position, feature, this.viewer);
}
//发送搜索请求,得到搜索结果
private onSearch() {
//之前选中的清理掉
this.unselectFeature(this.selectedFeature)
if (this.keyword) {
//根据关键字查询bim
this.searchFeature(this.keyword);
}
}
//重置
private onReset() {
this.keyword = null;
this.isSearch = false;
this.records = [];
this.unselectFeature(this.selectedFeature)
}
//处理搜索框选中高亮
private handleSelectFeature(item: any) {
console.log(item);
if (item) {
let element = item.element;
//根据三维场景中加载好的object对象,和element,查找搜索到的bim
let feature = this.elementMap[element][0];
if (feature) {
//选择高亮
let color = item.status==1?Cesium.Color.RED:item.status==2?Cesium.Color.YELLOW:Cesium.Color.BLUE;
this.selectFeature(feature,color);
}
}
}
private mouseSelectFeature() {
let handler = this.viewer.screenSpaceEventHandler;
handler.setInputAction((movement: any) => {
const feature = this.viewer.scene.pick(movement.endPosition);
this.unselectFeature(this.selectedFeature);
if (feature instanceof Cesium.Cesium3DTileFeature) {
this.selectFeature(feature,null);
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
}
private selectFeature(feature: any,color:any) {
const element = feature.getProperty("element");
this.setElementColor(element, color);
this.selectedFeature = feature;
}
private unselectFeature(feature: any) {
if (!Cesium.defined(feature)) {
return;
}
const element = feature.getProperty("element");
this.setElementColor(element, Cesium.Color.WHITE);
if (feature === this.selectedFeature) {
this.selectedFeature = undefined;
}
}
private setElementColor(element: any, color: any) {
const featuresToColor = this.elementMap[element];
const length = featuresToColor.length;
for (let i = 0; i < length; ++i) {
const feature = featuresToColor[i];
feature.color = Cesium.Color.clone(color, feature.color);
}
}
private getElement(feature: any) {
return parseInt(feature.getProperty("element"), 10);
}
private unloadFeature(feature: any) {
this.unselectFeature(feature);
const element = this.getElement(feature);
const features = this.elementMap[element];
const index = features.indexOf(feature);
if (index > -1) {
features.splice(index, 1);
}
}
private loadFeature(feature: any) {
const element = this.getElement(feature);
let features = this.elementMap[element];
if (!Cesium.defined(features)) {
features = [];
this.elementMap[element] = features;
}
features.push(feature);
}
private processContentFeatures(content: any, callback: any) {
const featuresLength = content.featuresLength;
for (let i = 0; i < featuresLength; ++i) {
const feature = content.getFeature(i);
callback(feature);
}
}
private processTileFeatures(tile: any, callback: any) {
const content = tile.content;
const innerContents = content.innerContents;
if (Cesium.defined(innerContents)) {
const length = innerContents.length;
for (let i = 0; i < length; ++i) {
this.processContentFeatures(innerContents[i], callback);
}
} else {
this.processContentFeatures(content, callback);
}
}
//保存BIM模型属性信息到数据库
private saveFeatureToDB(features: any) {
for (const feature of features) {
let center = feature.tileset.boundingSphere.center;
this.params = {}
if (center) {
this.params.x = center.x;//x坐标
this.params.y = center.y;//y坐标
this.params.z = center.z;//z坐标
}
var propertyNames = feature.getPropertyNames();
var length = propertyNames.length;
for (var i = 0; i < length; ++i) {
var propertyName = propertyNames[i];
console.log(propertyName + ': ' + feature.getProperty(propertyName));
this.params[propertyName] = feature.getProperty(propertyName)
}
this.bathParams.push(this.params)
}
axios.post('/api/bim/save', this.bathParams).then((response) => {
console.log(response);
this.bathElements = [];
}).catch(function (error) {
console.log(error);
});
}
//查询BIM模型
private searchFeature(keyword: string): any {
//发送的ajax请求
axios.get('/api/bim/list', {
params: {
keyword: keyword
}
}).then((response) => {
console.log(response.data.data.records);
if (response.data && response.data.data && response.data.data.records) {
// todo 渲染列表
this.records = response.data.data.records;
this.isSearch = true;
}
}).catch(function (error) {
console.log(error);
});
}
}
</script>
<style lang="less" scoped>
#cesiumContainer {
width: 100%;
height: 100%;
overflow: hidden;
}
</style>
App.vue
<template>
<div id="app">
<HelloWorld/>
</div>
</template>
<script lang="ts">
import {Component, Vue} from 'vue-property-decorator'; // ts装饰器
import HelloWorld from './components/HelloWorld.vue'
@Component({
components: {
HelloWorld
}
})
export default class App extends Vue {
}
</script>
<style>
html, body, #app {
padding: 0px;
margin: 0px;
width: 100%;
height: 100%;
overflow: hidden;
}
</style>
shims-tsx.d.ts
import Vue, {VNode} from 'vue'
declare global {
namespace JSX {
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface Element extends VNode {
}
// eslint-disable-next-line @typescript-eslint/no-empty-interface
interface ElementClass extends Vue {
}
interface IntrinsicElements {
[elem: string]: any;
}
}
interface Window {
__wxjs_environment: any;
WebViewJavascriptBridge: any;
_czc: any;
}
}
shims-vue.d.ts
declare module '*.vue' {
import Vue from 'vue'
export default Vue
}