vue3+arcgisAPI4示例:轨迹点模拟移动(附源码下载)

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实现达到轨迹点模拟圆滑移动效果。

核心部分代码

javascript 复制代码
<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
  });
  // 去除logo
  view.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而不是文件URL
  const 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而不是文件URL
  const 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; // 控制动画速度,相当于之前的100ms
  const 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>
相关推荐
十启树5 天前
QGis开发环境部署
开发语言·gis·qgis
rainstop_313 天前
为 Claude Code 开发自定义 Skill:解决中国地图坐标系转换痛点
gis·ai编程·claude
GIS开发特训营14 天前
Cesium Shader 实战:三维 GIS 可视化进阶教程
gis·cesium·gis开发·webgis
GIS好难学19 天前
【分享】120套开源数据可视化大屏H5模板
信息可视化·webgis
深紫色的三北六号20 天前
射线法判断一个坐标点(经纬度)是否在一个多边形区域内部
java·算法·gis
GIS学姐嘉欣20 天前
Cesium进阶教程(2)线性高度雾
javascript·cesium·gis开发·webgis
牛老师讲GIS20 天前
终于,Leaflet WIKI发布上线了
leaflet·webgis
图扑可视化20 天前
WebGIS 智慧交通——路网运行态势 BI 可视化大屏
gis·数字孪生·智慧交通·智慧高速
GISBox21 天前
一站式体验GISBox 2.1.3:矢量样式扩展与3DTiles位置优化
gis·cesium·倾斜摄影·ifc·osgb·gisbox·切片转换
那年那棵树21 天前
【WebGis】基于WebGis的系统设计与开发
gis·openlayers·cesium·地理信息系统