vue3+arcgisAPI4案例:智慧林业资源监测分析平台(附源码下载)
基于vue3+arcgisapi4的智慧林业资源监测分析平台简单案例,覆盖功能点包括图层管理,生态环境监测点,防火路径选线以及智能问答等,适合学习arcgisapi4与前端框架结合开发3D可视化项目。
demo源码运行环境以及配置
运行环境:依赖Node安装环境,demo本地Node版本:推荐v18+。 运行工具:vscode或者其他工具。
配置方式:下载demo源码,vscode打开,然后顺序执行以下命令:
(1)下载demo环境依赖包命令:npm install
(2)启动demo命令:npm run dev
(3)打包demo命令: npm run build
技术栈
Vue 3.3.9
Vite 5.0.4
@arcgis/core 4.29.3
示例效果
核心源码
const initMap = () => {esriConfig.assetsPath = "./assets";esriConfig.fontsUrl = "./static.arcgis.com/fonts";// esriConfig.apiKey = 'AAPKca495ea263b64e44b61eaaecdbddebfcwEQjC8k8-6XGMrrXyCie6xzybboRl4REq-TwDQTm8Wz-8sL6REARz1wcm14Kq9ny';// 初始化创建地图对象map = new Map({basemap: basemapBlue_ArcGIS, // 默认显示arcgis在线影像图ground: "world-elevation"});// 初始化创建视图view对象view = new SceneView({container: "viewDiv",map: map,// center: config.mapInitParams.center,// zoom: config.mapInitParams.zoomcamera: {position: {x: config.mapInitParams.center[0], // 经度y: config.mapInitParams.center[1], // 纬度z: 2000 // 高度(米)},tilt: 75}});const labelPolygonClass = new LabelClass({labelExpressionInfo: { expression: "$feature.名称_name" },symbol: {type: "text",color: "#fff",font: {size: 10,weight: "normal",},haloColor: [0, 0, 0, 255],haloSize: 1,},minScale: 288895, // 最小比例尺(最大缩放级别)// maxScale: 577790, // 最大比例尺(最小缩放级别,// labelPlacement: "center-right"});// 老山林场图层LSLCLayer = new FeatureLayer({id: 'LSLCLayer',url: "https://www.geosceneonline.cn/server/rest/services/Hosted/老山林场/FeatureServer/0",renderer: {type: "simple",symbol: {type: "simple-fill",color: [51, 51, 204, 0],style: "solid",outline: {color: "red",width: 2}}},featureReduction: {type: "selection"},labelingInfo: [labelPolygonClass]});map.add(LSLCLayer);const labelClass = new LabelClass({labelExpressionInfo: { expression: "$feature.NAME" },symbol: {type: "text",color: "#fff",font: {size: 10,weight: "normal",},haloColor: [0, 0, 0, 255],haloSize: 1,},minScale: 288895, // 最小比例尺(最大缩放级别)// maxScale: 577790, // 最大比例尺(最小缩放级别,// labelPlacement: "center-right"});// 创建水系图层SXLayer = new FeatureLayer({id: 'SXLayer',url: "https://www.geosceneonline.cn/server/rest/services/Hosted/水系water/FeatureServer/0",renderer: {type: "simple",symbol: {type: "simple-line",color: "#1890ff",width: "4px",style: "solid"}},featureReduction: {type: "selection"},labelingInfo: [labelClass]});map.add(SXLayer);// 创建公路图层GLLayer = new FeatureLayer({id: 'GLLayer',url: "https://www.geosceneonline.cn/server/rest/services/Hosted/公路road/FeatureServer/0",renderer: {type: "simple",symbol: {type: "simple-line",color: "yellow",width: "4px",style: "solid"}},featureReduction: {type: "selection"},labelingInfo: [labelClass]});map.add(GLLayer);// 创建居民地地名图层JMDDMLayer = new FeatureLayer({id: 'JMDDMLayer',url: "https://www.geosceneonline.cn/server/rest/services/Hosted/居民地地名/FeatureServer/0",renderer: {type: "simple",symbol: {type: "simple-marker",size: 8,color: "#edd317",outline: {width: 0.5,color: "white"}}},featureReduction: {type: "selection"},labelingInfo: [labelClass]});map.add(JMDDMLayer);// 创建生态资源监测点图层const labelSTClass = new LabelClass({labelExpressionInfo: { expression: "$feature.name" },symbol: {type: "label-3d",symbolLayers: [{type: "text",material: {color: "white"},halo: {size: 1,color: [50, 50, 50]},size: 10}]}});const verticalOffset = {screenLength: 40,maxWorldLength: 200,minWorldLength: 35};// create a new blob from geojson featurecollectionconst blob = new Blob([JSON.stringify(STGeojsonData.value)], {type: "application/json"});// URL reference to the blobconst url = URL.createObjectURL(blob);monitorPointLayer = new GeoJSONLayer({id: 'monitorPointLayer',// url: "./public/data/monitorPoints.geojson",url: url,labelingInfo: [labelSTClass],featureReduction: {type: "selection"},outFields: ["*"],elevationInfo: {mode: "relative-to-scene"},renderer: {type: 'unique-value',field: 'temperature',defaultSymbol: {type: "point-3d",symbolLayers: [{type: "icon",resource: {href: ParkIMG// href: "https://developers.arcgis.com/javascript/latest/sample-code/visualization-point-styles/live/Park.png"},size: 20,outline: {color: "white",size: 2}}],verticalOffset: verticalOffset,callout: {type: "line",color: "white",size: 2,border: {color: "#40C2B4"}}},// uniqueValueInfos: [// {// value: 35,// symbol: {// type: "simple-fill",// color: '#00c460',// style: "solid",// outline: {// color: '#dcdcdc',// width: 1,// style: "solid"// }// },// }// ]},});map.add(monitorPointLayer);// 创建图形图层用于放置3D模型graphicsLayer3D = new GraphicsLayer({id: 'graphicsLayer3D',elevationInfo: { mode: 'on-the-ground' } // on-the-ground relative-to-ground absolute-height relative-to-scene});map.add(graphicsLayer3D);pathLineGraphicsLayer = new GraphicsLayer({id: 'pathLineGraphicsLayer',// elevationInfo: { mode: 'on-the-ground' }});map.add(pathLineGraphicsLayer);// 创建一个图形图层用于添加点图标pointGraphicsLayer = new GraphicsLayer({id: 'pointGraphicsLayer',// elevationInfo: { mode: 'on-the-ground' }});map.add(pointGraphicsLayer);// 去除logoview.ui.remove(["attribution", "navigation-toggle", "compass", "zoom"]);const popup = {alignment: "top-center",// collapseEnabled: false, // 移除title点击折叠功能visibleElements: {actionBar: false,collapseButton: false,closeButton: false,heading: false},dockOptions: {buttonEnabled: false, // 隐藏固定标签页}};view.popup = popup;// 监听视图view初始化加载完成执行view.when(function () {removeElementById('loader-wrapper');// 初始化创建地图默认视图控件// const homeWidget = new Home({// view: view// });// 初始化创建地图切换控件basemapGallery = new BasemapToggle({view: view,nextBasemap: basemapVec_tianditu});// 控制地图控件位置view.ui.add([{component: basemapGallery,position: "bottom-right",index: 0}]);// 视图地图监听点击事件view.on("immediate-click", (event) => {view.closePopup();const mapPoint = event.mapPoint;console.log('mapPoint:', mapPoint);// 判断是否执行路线规划选择点if (addPointType.value === 1 || addPointType.value === 2) {addPointGraphic(mapPoint, addPointType.value === 1 ? starPointSymbol : endPointSymbol);const position = `${mapPoint.longitude.toFixed(6)},${mapPoint.latitude.toFixed(6)}`;addPointType.value === 1 ? startPoint.value = position : endPoint.value = position;addPointType.value = 0;}view.popupEnabled = false;const opts = {include: monitorPointLayer};view.hitTest(event, opts).then(function (response) {// console.log('response:', response);const graphicHits = response.results?.filter((hitResult) => hitResult.type === "graphic" && hitResult.layer.id.includes("monitorPointLayer"));if (graphicHits?.length > 0) {graphicHits.forEach((graphicHit) => {console.log(graphicHit.graphic.attributes);const attributes = graphicHit.graphic.attributes;typhoonInfo.value = attributes;// 弹窗显示生态资源监测点信息view.openPopup({title: '',location: mapPoint,content: typhoonPopup.value});});}});});// 加载GLB模型loadGlbModel(graphicsLayer3D);});
}
// 添加点图标到地图
const addPointGraphic = (mapPoint, pointSymbol) => {// 清除之前的点图标// pointGraphicsLayer.removeAll();// 移除所有id为特定值的图形const graphicsToRemove = pointGraphicsLayer.graphics.filter(g => g.attributes && g.attributes.id === addPointType.value);pointGraphicsLayer.removeMany(graphicsToRemove);// 创建点图形const pointGraphic = new Graphic({geometry: mapPoint,symbol: pointSymbol,attributes: {id: addPointType.value}});// 将点图形添加到图层pointGraphicsLayer.add(pointGraphic);// console.log("添加了新的点图标,坐标:", mapPoint.longitude, mapPoint.latitude);
};
// 路线规划
const fireRoute = async () => {if (validatenull(startPoint.value)) {ElMessage.warning('请选择起点');return;}if (validatenull(endPoint.value)) {ElMessage.warning('请选择终点');return;}// 坐标转换const url = `${coordinateConvertURL}&locations=${startPoint.value}|${endPoint.value}`;const response = await axios.get(url);console.log('response:', response);const data = response.data;if (data.status === '0') {ElMessage.error('坐标转换失败');return;}const locations = data.locations;// 路线规划const drUrl = `${drivingURL}&origin=${locations.split(';')[0]}&destination=${locations.split(';')[1]}`;const drResponse = await axios.get(drUrl);console.log('drResponse:', drResponse);const resultdata = drResponse.data;if (resultdata.status === '0') {ElMessage.error('路线规划失败');instructionList.value = [];drtip.value = '搜索不到路径规划相关信息';return;}analyzeResponseA(resultdata);
}
const parseCoordinates = (data) =>data.split(';').map(point => point.split(',').map(Number));
const analyzeResponseA = (data) => {const steps = data.route.paths[0].steps;totalDistance.value = data.route.paths[0].distance;totalTime.value = data.route.paths[0].duration;let allPath = [];instructionList.value = [];for (let i = 0; i < steps.length; i++) {const path = steps[i].polyline;const coordinates = parseCoordinates(path);const wgs84coordinates = convertGCJ02ToWGS84(coordinates);console.log('coordinates:',wgs84coordinates);// allPath = [...coordinates];allPath.push(wgs84coordinates);console.log('allPath:',allPath);instructionList.value.push({instruction: steps[i].instruction});}pathLineGraphicsLayer.removeAll();const polyline = {type: "polyline",paths: allPath};const polylineGraphic = new Graphic({geometry: polyline,symbol: pathLineSymbol});pathLineGraphicsLayer.add(polylineGraphic);
}