demo源碼運行環境以及配置
運行環境:依賴Node安裝環境,需要安裝Node。 運行工具:vscode或者其他工具。
配置方式:下載demo源碼,vscode打開,然后順序執行以下命令:
(1)下載demo環境依賴包命令:npm install -g
(2)yarn install
(3)啟動demo命令:yarn dev
(4)打包demo命令: yarn build:prod
示例效果
實現思路
使用模擬數據線圖層geojson,獲取線的點集合數據,然后點和點之間直線插值點,獲取到插值點數據集,最后結合arcgis api
4實現達到軌跡點模擬圓滑移動效果。
核心部分代碼
<template><div id="viewDiv"></div><div class="titleContainer center"><span>vue3+arcgisAPI4示例:軌跡點模擬移動效果</span></div><el-button type="primary" class="buttonRight btn1" @click="starBtn">開始模擬</el-button><el-button type="primary" class="buttonRight btn2" @click="clearBtn">清除模擬</el-button>
</template>
<script setup>
import { onMounted, onUnmounted, ref } from "vue";
import "@arcgis/core/assets/esri/themes/light/main.css";
import Map from "@arcgis/core/Map";
import MapView from "@arcgis/core/views/MapView";
import Basemap from "@arcgis/core/Basemap.js";
import esriConfig from "@arcgis/core/config";
import GeoJSONLayer from "@arcgis/core/layers/GeoJSONLayer.js";
import GraphicsLayer from "@arcgis/core/layers/GraphicsLayer";
import GroupLayer from "@arcgis/core/layers/GroupLayer.js";
import Graphic from "@arcgis/core/Graphic.js";
import Point from "@arcgis/core/geometry/Point.js";
import { distance } from "@arcgis/core/geometry/geometryEngine.js";
import { geographicToWebMercator } from "@arcgis/core/geometry/support/webMercatorUtils.js";
import { removeElementById } from '@/utils/index';
import axios from "axios";
let view, map, graphicsLayer = null;
let animationFrameId = null; // 動畫幀ID
let features = []; // 存儲軌跡點
onMounted(() => {initMap();
});
// 組件卸載時取消動畫
onUnmounted(() => {if (animationFrameId) {cancelAnimationFrame(animationFrameId);animationFrameId = null;}
});
const initMap = () => {esriConfig.apiKey = 'AAPKca495ea263b64e44b61eaaecdbddebfcwEQjC8k8-6XGMrrXyCie6xzybboRl4REq-TwDQTm8Wz-8sL6REARz1wcm14Kq9ny';// 初始化創建地圖對象const novaLayer = Basemap.fromId("arcgis-imagery-standard");map = new Map({// basemap: "satellite",basemap: novaLayer,});// 初始化創建視圖view對象view = new MapView({container: "viewDiv",map: map,center: [111.69795926864639, 23.2026556059399],zoom: 15});// 去除logoview.ui.remove(["attribution", "zoom"]);// 監聽視圖view初始化加載完成執行view.when(function () {removeElementById('loader-wrapper');loadPointLineLayer();});
}
const loadPointLineLayer = async () => {// 使用axios請求獲取GeoJSON數據const response = await axios.get("./src/views/carTrack/carTrackPoint.geojson");const geojsonData = response.data;features = geojsonData.features;// 創建GeoJSON圖層,使用blob URL而不是文件URLconst blob = new Blob([JSON.stringify(geojsonData)], { type: "application/json" });const blobUrl = URL.createObjectURL(blob);let pointsLayer = new GeoJSONLayer({url: blobUrl})const response1 = await axios.get("./src/views/carTrack/carTrackLine.geojson");const geojsonData1 = response1.data;// 創建GeoJSON圖層,使用blob URL而不是文件URLconst blob1 = new Blob([JSON.stringify(geojsonData1)], { type: "application/json" });const blobUrl1 = URL.createObjectURL(blob1);let lineLayer = new GeoJSONLayer({url: blobUrl1})const groupLayer = new GroupLayer({layers: [pointsLayer,lineLayer]});map.add(groupLayer);graphicsLayer = new GraphicsLayer({ id: 'graphicsLayer' });map.add(graphicsLayer);
}
const starBtn = () => {// 讀取模擬車輛軌跡數據let points = [];// 取消可能存在的動畫if (animationFrameId) {cancelAnimationFrame(animationFrameId);animationFrameId = null;}// 生成所有軌跡點for (let i = 0; i < features.length; i++) {const feature = features[i];if (i !== features.length - 1) {points = points.concat(getPointSAlongLine(feature, features[i + 1], 1))}else {points = points.concat(getPointSAlongLine(feature, feature, 1))}}// 使用requestAnimationFrame實現動畫let currentIndex = 0;let lastTimestamp = 0;const frameInterval = 100; // 控制動畫速度,相當于之前的100msconst animate = (timestamp) => {// 計算時間差if (!lastTimestamp) lastTimestamp = timestamp;const elapsed = timestamp - lastTimestamp;// 當經過的時間超過幀間隔時更新位置if (elapsed >= frameInterval) {lastTimestamp = timestamp;if (currentIndex < points.length) {refreshAlarmPoint(points[currentIndex]);currentIndex++; // 繼續動畫animationFrameId = requestAnimationFrame(animate);} else {// 動畫結束animationFrameId = null;}} else {// 如果時間間隔不夠,繼續等待animationFrameId = requestAnimationFrame(animate);}};// 啟動動畫animationFrameId = requestAnimationFrame(animate);
}
const clearBtn = () => {// 取消可能存在的動畫if (animationFrameId) {cancelAnimationFrame(animationFrameId);animationFrameId = null;}if (graphicsLayer) {graphicsLayer.removeAll();}
}
// 刷新繪制實時報警點
const refreshAlarmPoint = (point) => {if (graphicsLayer) {graphicsLayer.removeAll();}// 創建節點圓圈符號const symbol = {type: "simple-marker",style: "circle",color: [255, 255, 255], // 白色填充size: 12,outline: {color: [66, 135, 245], // 藍色邊框width: 2}};const graphic = new Graphic({geometry: point,symbol: symbol});graphicsLayer.add(graphic);
}
/*** 計算起點和終點連線上距離起點指定距離的坐標點* @param {Array} startPoint - 起點坐標* @param {Array} endPoint - 終點坐標* @param {Number} dis- 距離起點的距離,單位:米* @returns {Array} - 計算得到的坐標點*/
……
</script>