arcgis js for JavaScript 4.X 3D小车移动轨迹动画

1 篇文章 0 订阅
1 篇文章 0 订阅

前言:
本人公司要求我研究arcgis.js,现在阶段第一个功能研究完成,小车根据坐标轨迹行驶,我发布的内容仅供互相学习参考,一切产生的后果与我无关。本人用的是vue

小车是3d的,也可以做成图片的形式
先上视频
在这里插入图片描述

<template>
  <div id="SceneView">
    <div id="viewDiv"></div>
    <div class="box1">
      <button @click="start">开始</button>
      <button @click="pause">暂停</button>
      <button @click="goOn">继续</button>
      <button @click="back">返回</button>
    </div>
  </div>
</template>

<script>
import { loadModules } from 'esri-loader'
import coordtransform from 'coordtransform'

export default {
  name: 'home',
  data() {
    return {
      carPaths: [
        [115.21947154300005, 32.735979284000052],
        [115.22809709000001, 32.746389426000064],
        [115.24980967100009, 32.749958617000061],
        [115.26616846600007, 32.749363752000079],
        [115.29739889100006, 32.74876888700004],
        [115.3241678280001, 32.746686858000032],
        [115.33398310400003, 32.737763880000045],
        [115.33130621100008, 32.713374404000035],
        [115.32089606900001, 32.699395071000026],
        [115.28279788700002, 32.69116676200008],
        [115.22660992600004, 32.703856560000077],
        [115.20162558600009, 32.705046291000031],
        [115.18913341600012, 32.69047209200005],
        [115.19567693300007, 32.66994924100004],
        [115.20251788400003, 32.66459545400005],
        [115.25516345900007, 32.657457071000067],
        [115.35809497600007, 32.659182180000073],
        [115.36332979000008, 32.647760767000079],
        [115.34572177900009, 32.639670600000045],
        [115.29622899000003, 32.63015275600003],
        [115.22056213000008, 32.633959893000053],
        [115.18344253800001, 32.62682151000007],
        [115.17154523300007, 32.603502792000029],
        [115.18058718500004, 32.583991212000058],
        [115.20628536400011, 32.575425152000037],
        [115.26719956500006, 32.575425152000037],
        [115.30669861800004, 32.574473368000042],
        [115.36095032900005, 32.584942997000041],
        [115.38807618500005, 32.611117068000055],
        [115.39664224400008, 32.630628648000027],
        [115.38063254500008, 32.673934838000037],
        [115.3885520770001, 32.702488370000026],
        [115.38093780200006, 32.755788297000038],
        [115.38046190900002, 32.77625166100006],
        [115.36190211400003, 32.794811457000037],
        [115.30527094200011, 32.808612331000063],
        [115.22436926700004, 32.809564115000057],
        [115.14489527000001, 32.793383781000045],
        [115.10254086400005, 32.760547219000046],
        [115.0863605290001, 32.727710657000046],
        [115.08160160700004, 32.694398203000048],
        [115.09207123500005, 32.64918844400006],
        [115.1030167560001, 32.631104540000024],
        [115.14584705400011, 32.64490541400005],
        [115.16250328100011, 32.635863462000032],
        [115.14203991700003, 32.610165283000072],
        [115.11538995300009, 32.588750134000065],
        [115.11824530700005, 32.558293033000041],
        [115.14299170100003, 32.537353776000032],
        [115.19533984300006, 32.570691286000035],
        [115.27433794900003, 32.530691286000035],
        [115.31526467800006, 32.544492159000072],
        [115.32716198300011, 32.579708182000047],
        [115.32145127600006, 32.61206885200005],
        [115.27528973300002, 32.623490265000044],
        [115.24340495500007, 32.632532217000062],
        [115.19914698100001, 32.657754503000035],
        [115.14523300007, 32.674886623000077],
        [115.16821398800005, 32.684880359000033],
        [115.17344880200005, 32.701536586000032],
        [115.20485768700007, 32.714385675000074],
        [115.15393722200008, 32.741035639000074],
        [115.12395601300011, 32.727710657000046],
        [115.12205244400002, 32.71057853800005],
        [115.13918456300007, 32.711054430000047],
        [115.15917203600009, 32.722951735000038],
        [115.17297291000011, 32.739132070000039],
        [115.18820146000007, 32.74341510000005],
        [115.21947154300005, 32.735979284000052],
      ],
      Graphic: null,
      // 移动图层
      moveLayer: null,
      moveCarGra: null,
      moving: null,
      startingPoint: {},
      startNum: 0,
      endNum: 0,
    }
  },
  mounted() {
    let options = {
      url: 'https://js.arcgis.com/4.15/',
      css: 'https://js.arcgis.com/4.15/esri/themes/light/main.css',
    }
    loadModules(['esri/Map', 'esri/geometry/Polyline', 'esri/layers/GraphicsLayer', 'esri/views/SceneView', 'esri/layers/ElevationLayer', 'esri/geometry/Circle', 'esri/layers/BaseElevationLayer', 'esri/layers/FeatureLayer', 'esri/symbols/SimpleFillSymbol', 'esri/layers/support/LabelClass', 'esri/symbols/ExtrudeSymbol3DLayer', 'esri/symbols/TextSymbol', 'esri/Graphic', 'esri/Camera', 'dojo/on', 'dojo/domReady!'], options).then(([Map, Polyline, GraphicsLayer, SceneView, ElevationLayer, Circle, FeatureLayer, TextSymbol, ExtrudeSymbol3DLayer, SimpleFillSymbol, LabelClass, BaseElevationLayer, Graphic, on, Camera]) => {
      this.Graphic = Graphic
      const map = new Map({
        basemap: 'streets-night-vector',
        showLabels: true,
        maxZoom: 15,
        zoom: 7,
        minZoom: 6,
        logo: false,
        height: '100%',
        fadeOnZoom: true,
      })

      const view = new SceneView({
        container: 'viewDiv',
        map: map,
        scale: 50000000,
        center: [121.480812, 31.230129],
        qualityProfile: 'high',
        environment: {
          lighting: {
            directShadowsEnabled: true,
            ambientOcclusionEnabled: true,
          },
          atmosphere: {
            quality: 'high',
          },
        },
      })
      view.on('click', function (event) {
        var screenPoint = {
          //当前点击的经纬度
          x: event.x,
          y: event.y,
        }
        view.hitTest(screenPoint).then(function (response) {
          //搜索与指定屏幕坐标相交的图形。
          if (response.results.length > 0 && response.results[0].graphic) {
            console.log(response.results)
            //如果当前点击位置存在点位
            for (var i = 0; i < dataArr.length; i++) {
              if (response.results[0].graphic.attr.id === i + 1) {
                //执行点位信息动画
                alert(i + 1)
              }
            }
          }
        })
      })
      view.when(
        () => {
          // 地图加载完成
          setTimeout(() => {
            view.goTo({
              // 视角切换动画
              center: [this.carPaths[0][0], this.carPaths[0][1]], //终点坐标
              heading: 360, // 面向正南
              z: 10000,
              tilt: 40, //视图角度cos
              zoom: 13, //放大等级
            })
          }, 1000)
        },
        function (error) {
          console.error(error)
          alert('加载失败,稍后重新加载')
          window.reload()
        }
      )
      let polyline = {
        type: 'polyline', // autocasts as new Polyline()
        paths: this.carPaths,
      }
      let lineSymbol = {
        type: 'simple-line', // autocasts as SimpleLineSymbol()
        color: [226, 119, 40],
        width: 2,
      }
      var polylineGraphic = new Graphic({
        geometry: polyline,
        symbol: lineSymbol,
      })
      view.graphics.add(polylineGraphic)
      // 开始创建小车
      // 初始化车辆
      let modelCar = this.initModelCar()
      this.moveLayer = new GraphicsLayer({
        id: 'moveLayer',
      })
      map.add(this.moveLayer)
      this.moveCarGra = new Graphic({
        geometry: this.startingPoint,
        symbol: modelCar,
      })
      this.moveLayer.add(this.moveCarGra)
    })
  },
  methods: {
    // 根据坐标计算角度
    calcAngle(x1, y1, x2, y2) {
      let tan = (Math.atan(Math.abs((y2 - y1) / (x2 - x1))) * 180) / Math.PI + 90
      if (x2 > x1 && y2 > y1) {
        return -tan + 180
      } else if (x2 > x1 && y2 < y1) {
        return tan
      } else if (x2 < x1 && y2 > y1) {
        return tan - 180
      } else {
        return -tan
      }
    },
    move(start, end) {
      let x1 = this.carPaths[start][0]
      let y1 = this.carPaths[start][1]
      let x2 = this.carPaths[end][0]
      let y2 = this.carPaths[end][1]

      //斜率
      let p = (y2 - y1) / (x2 - x1)
      //速度
      let v = 0.002 // 过小会导致线路偏移
      this.moving = setInterval(() => {
        this.moveLayer.removeAll()
        this.startNum = start
        this.endNum = end
        //分别计算 x,y轴的方向和速度
        if (Math.abs(p) == Number.POSITIVE_INFINITY) {
          //垂直的时候斜率无穷大
          this.moveCarGra.geometry.y += v
        } else {
          if (x2 < x1) {
            this.moveCarGra.geometry.x -= (1 / Math.sqrt(1 + p * p)) * v
            this.moveCarGra.geometry.y -= (p / Math.sqrt(1 + p * p)) * v
            // 创建行驶车辆
            let modelNewCar = this.setModelCar(x1, y1, x2, y2)
            this.moveLayer.add(
              new this.Graphic({
                geometry: this.moveCarGra.geometry,
                symbol: modelNewCar,
              })
            )
          } else {
            this.moveCarGra.geometry.x += (1 / Math.sqrt(1 + p * p)) * v
            this.moveCarGra.geometry.y += (p / Math.sqrt(1 + p * p)) * v
            // 创建行驶车辆
            let modelNewCar = this.setModelCar(x1, y1, x2, y2)
            this.moveLayer.add(
              new this.Graphic({
                geometry: this.moveCarGra.geometry,
                symbol: modelNewCar,
              })
            )
          }
        }
        if (Math.abs(this.moveCarGra.geometry.x - x2) <= v && Math.abs(this.moveCarGra.geometry.y - y2) <= v) {
          clearInterval(this.moving)
          this.startNum = start++
          this.endNum = end++
          if (end < this.carPaths.length) {
            this.move(start, end)
          }
        }
      }, 50)
    },
    // 开始
    start() {
      if (this.moving != undefined) {
        clearInterval(this.moving) //清除移动
      }
      this.moveCarGra.geometry = this.startingPoint
      this.move(0, 1)
    },
    // 暂停
    pause() {
      clearInterval(this.moving)
    },
    // 继续
    goOn() {
      if (this.moving != undefined) {
        clearInterval(this.moving) //清除移动
      }
      this.move(this.startNum, this.endNum)
    },
    // 返回
    back() {
      if (this.moving != null) {
        clearInterval(this.moving) //清除移动
      }
      this.moveLayer.removeAll()
      // 初始化车辆
      let modelNewCar = this.initModelCar()
      this.moveLayer.add(
        new this.Graphic({
          geometry: this.startingPoint,
          symbol: modelNewCar,
        })
      )
    },
    // 初始化车辆
    initModelCar() {
      let x1 = this.carPaths[0][0]
      let y1 = this.carPaths[0][1]
      let x2 = this.carPaths[1][0]
      let y2 = this.carPaths[1][1]
      // 设置起点
      this.startingPoint = {
        type: 'point',
        longitude: this.carPaths[0][0],
        latitude: this.carPaths[0][1],
      }
      let modelNewCar = {
        type: 'point-3d',
        symbolLayers: [
          {
            type: 'object',
            // width: 300, //模型宽度ssss
            height: 468, //模型高度
            resource: {
              href: 'gltf/red_car.gltf',
            },
            heading: this.calcAngle(x1, y1, x2, y2) + 180, //朝向
          },
        ],
      }
      return modelNewCar
    },
    // 创建车辆
    setModelCar(x1, y1, x2, y2) {
      let modelNewCar = {
        type: 'point-3d',
        symbolLayers: [
          {
            type: 'object',
            // width: 300, //模型宽度ssss
            height: 468, //模型高度
            resource: {
              href: 'gltf/red_car.gltf',
            },
            heading: this.calcAngle(x1, y1, x2, y2) + 180, //朝向
          },
        ],
      }
      return modelNewCar
    },
  },
}
</script>

<style>
@import 'https://js.arcgis.com/4.15/esri/css/main.css';

html,
body,
#viewDiv {
  padding: 0;
  margin: 0;
  height: 100%;
  width: 100%;
}
.dot_box {
  z-index: 2;
  position: fixed;
  width: 20px;
  height: 20px;
  background: #0080ff;
  border-radius: 50%;
}
.line_ele {
  z-index: 2;
  position: absolute;
  top: 50%;
  left: 0;
  margin-top: -1px;
  height: 1px;
  border-bottom: 1px solid #0080ff;
}
.box {
  z-index: 2;
  display: none;
  position: fixed;
  width: 300px;
  height: 300px;
  border: 2px solid #ddd;
}
.box1 {
  position: absolute;
  top: 20px;
  right: 20px;
  z-index: 9;
}
#SceneView {
  position: absolute;
  width: 100%;
  height: 100%;
}
.esri-component.esri-attribution.esri-widget {
  display: none;
}
</style>

  • 7
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
以下是一个基于 ArcGIS JavaScript API 4.x 实现移动轨迹动画的示例代码: ```javascript require([ "esri/Map", "esri/views/MapView", "esri/Graphic", "esri/geometry/Point", "esri/layers/GraphicsLayer", "esri/symbols/SimpleMarkerSymbol", "esri/symbols/SimpleLineSymbol", "esri/geometry/Polyline", "esri/geometry/support/webMercatorUtils", "dojo/domReady!" ], function(Map, MapView, Graphic, Point, GraphicsLayer, SimpleMarkerSymbol, SimpleLineSymbol, Polyline, webMercatorUtils) { // 定义起点和终点的经纬度坐标 var startPoint = [-122.414, 37.776]; var endPoint = [-122.426, 37.776]; // 创建地图和地图视图 var map = new Map({ basemap: "streets-navigation-vector" }); var view = new MapView({ container: "viewDiv", map: map, center: startPoint, zoom: 14 }); // 创建图形图层,并添加到地图中 var graphicsLayer = new GraphicsLayer(); map.add(graphicsLayer); // 创建起点和终点的点图形,并添加到图形图层中 var startSymbol = new SimpleMarkerSymbol({ color: "green", size: "8px" }); var endSymbol = new SimpleMarkerSymbol({ color: "red", size: "8px" }); var startPointGraphic = new Graphic({ geometry: new Point({ longitude: startPoint[0], latitude: startPoint[1] }), symbol: startSymbol }); var endPointGraphic = new Graphic({ geometry: new Point({ longitude: endPoint[0], latitude: endPoint[1] }), symbol: endSymbol }); graphicsLayer.addMany([startPointGraphic, endPointGraphic]); // 创建轨迹线的符号,并添加到图形图层中 var lineSymbol = new SimpleLineSymbol({ color: "blue", width: 4 }); var polylineGraphic = new Graphic({ geometry: new Polyline(), symbol: lineSymbol }); graphicsLayer.add(polylineGraphic); // 计算移动轨迹的点集合 var points = []; for (var i = 0; i <= 100; i++) { var lon = startPoint[0] + (endPoint[0] - startPoint[0]) * i / 100; var lat = startPoint[1] + (endPoint[1] - startPoint[1]) * i / 100; points.push([lon, lat]); } // 定义当前移动到的点的索引 var currentIndex = 0; // 定义移动函数,每隔一段时间移动到下一个点 function move() { polylineGraphic.geometry.addPath(points.slice(currentIndex, currentIndex + 2)); currentIndex += 1; if (currentIndex < points.length - 1) { setTimeout(move, 50); } } // 将经纬度坐标转换为 WebMercator 坐标系 points = points.map(function(point) { return webMercatorUtils.geographicToWebMercator(new Point({ longitude: point[0], latitude: point[1] })); }); // 开始移动 move(); }); ``` 在这个示例代码中,我们首先创建了一个地图和地图视图,并在地图上添加了一个图形图层。然后,我们创建了起点和终点的点图形,并将它们添加到图形图层中。接着,我们创建了轨迹线的符号,并将其添加到图形图层中。接下来,我们计算了移动轨迹的点集合,并定义了一个移动函数,每隔一段时间移动到下一个点。最后,我们将经纬度坐标转换为 WebMercator 坐标系,并开始移动。 需要注意的是,该示例代码中的移动函数仅是一个简单的实现,实际应用中可能需要更加复杂的实现,例如根据实时数据更新移动轨迹等。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Alex-Gdd

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值