基于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.zoom
camera: {
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 featurecollection
const blob = new Blob([JSON.stringify(STGeojsonData.value)], {
type: "application/json"
});
// URL reference to the blob
const 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);
// 去除logo
view.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);
}