index.vue 9.11 KB
<template>
  <div class="app-container">
    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
      <el-form-item label="车牌号" prop="trashType">
        <treeselect v-model="queryParams.carCode" :options="options" placeholder="请选择" style="width:200px;"/>
      </el-form-item>
      <el-form-item label="时间段" prop="latitude">
        <el-date-picker
          v-model="createTime"
          type="datetimerange"
          range-separator="至"
          start-placeholder="开始日期"
          end-placeholder="结束日期">
        </el-date-picker>
      </el-form-item>
      <el-form-item>
        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
      </el-form-item>
    </el-form>

    <el-row :gutter="10" class="mb8">
      <el-col :span="1.5">
        <el-button
          type="primary"
          size="mini"
          @click="startAnimation"
          v-hasPermi="['gps:trajectory:add']"
        >开始回放
        </el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="success"
          size="mini"
          @click="resumeAnimation"
          v-hasPermi="['gps:trajectory:remove']"
        >继续
        </el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="danger"
          size="mini"
          @click="pauseAnimation"
          v-hasPermi="['gps:trajectory:edit']"
        >暂停
        </el-button>
      </el-col>
      <el-col :span="1.5">
        <el-button
          type="primary"
          size="mini"
          @click="accelerate"
          v-hasPermi="['gps:trajectory:edit']"
        >{{ speed }}倍速
        </el-button>
      </el-col>
      <el-col :span="1.5">
        <el-tooltip class="item" effect="light" placement="right">
          <div slot="content" class="tooltipsContent1">
            选择倍速后,需重新开始回放
          </div>
          <div class="tips">
              <span class="tipsSpan">
                倍速提示
              </span>
            <i class="el-icon-question"></i>
          </div>
        </el-tooltip>
      </el-col>
      <!--      <el-col :span="1.5">-->
      <!--        <el-button-->
      <!--          type="warning"-->
      <!--          icon="el-icon-download"-->
      <!--          size="mini"-->
      <!--          @click="stopAnimation"-->
      <!--          v-hasPermi="['gps:trajectory:export']"-->
      <!--        >暂停</el-button>-->
      <!--      </el-col>-->
      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
    </el-row>
    <el-row>
      <el-col :span="24">
        <div id="trajectoryMap" class="am-map" style="width:100%;height: 750px"></div>
      </el-col>
    </el-row>
  </div>
</template>

<script>
import {listTrajectory} from "@/api/gps/trajectory";
import {listCarInfo} from "@/api/unit/carInfo";
import AMapLoader from '@amap/amap-jsapi-loader';
import Treeselect from "@riophae/vue-treeselect";
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
import gcoord from 'gcoord';

export default {
  name: "Trajectory",
  components: {Treeselect},
  data() {
    return {
      // 遮罩层
      loading: true,
      // 选中数组
      ids: [],
      // 非单个禁用
      single: true,
      // 非多个禁用
      multiple: true,
      // 显示搜索条件
      showSearch: true,
      // 总条数
      total: 0,
      // gps数据轨迹回放表格数据
      trajectoryList: [],
      // 弹出层标题
      title: "",
      // 是否显示弹出层
      open: false,
      // 查询参数
      queryParams: {
        terminalNumber: null,
        longitude: null,
        latitude: null,
        createTime: null,
        createTimeStart: null,
        createTimeEnd: null,
        carCode: null
      },
      createTime: null,
      // 表单参数
      form: {},
      // 表单校验
      rules: {},
      map: null,
      marker: null,
      polyline: null,
      options: [],//车牌号
      speed: 1,
      lineArr: []
    };
  },
  created() {
    listCarInfo(null).then(res => {
      //将res.rows转换成options
      this.options = res.rows.map(item => {
        return {
          id: item.carCode,
          label: item.carCode
        }
      })
    })
  },
  mounted() {
    this.initMap();
  },
  methods: {
    getDistanceFromLatLonInKm(lat1, lon1, lat2, lon2) {
      var R = 6371; // 地球的半径,单位是千米
      var dLat = this.deg2rad(lat2 - lat1);
      var dLon = this.deg2rad(lon2 - lon1);
      var a =
        Math.sin(dLat / 2) * Math.sin(dLat / 2) +
        Math.cos(this.deg2rad(lat1)) * Math.cos(this.deg2rad(lat2)) *
        Math.sin(dLon / 2) * Math.sin(dLon / 2)
      ;
      var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
      var d = R * c; // 距离(千米)
      return d;
    },

    deg2rad(deg) {
      return deg * (Math.PI / 180)
    },
    getList() {

      console.log(this.queryParams)
      if (this.queryParams.carCode != null && this.createTime != null) {
        this.queryParams.createTimeStart = this.parseTime(this.createTime[0], '{y}-{m}-{d} {h}:{i}:{s}');
        this.queryParams.createTimeEnd = this.parseTime(this.createTime[1], '{y}-{m}-{d} {h}:{i}:{s}');
        listTrajectory(this.queryParams).then(res => {
          this.lineArr = [];
          this.lineArr = res.map(item => {
            //WGS84坐标转GCJ02坐标
            var result = gcoord.transform(
              [item.longitude, item.latitude],    // 经纬度坐标
              gcoord.WGS84,               // 当前坐标系
              gcoord.GCJ02                 // 目标坐标系
            );
            return result
          }).filter((item, index, array) => {
            if (index === 0) return true; // 永远保持第一点
            const prevItem = array[index - 1];
            const distance = this.getDistanceFromLatLonInKm(prevItem[1], prevItem[0], item[1], item[0]);
            return distance <= 10; // 最大允许距离10km
          }),
          this.initMap();
        })
      } else {
        this.$message.warning("请选择车牌号和时间段");
      }

    },
    startAnimation() {
      this.marker.moveAlong(this.lineArr, 500 * this.speed);
    },
    pauseAnimation() {
      this.marker.pauseMove();
    },
    resumeAnimation() {
      this.marker.resumeMove();
    },
    accelerate() {
      this.speed = this.speed * 2;
      if (this.speed > 16) {
        this.speed = 1;
      }
    },
    initMap() {
      const _this = this
      // 加载高德地图
      AMapLoader.load({
        key: _this.$aMapKey,  //设置高德地图申请的key
        version: "1.4.15",  // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
        plugins: ['AMap.ToolBar', 'AMap.PolygonEditor', 'AMap.Polyline', 'AMap.Marker', 'AMap.MoveAnimation'], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
        AMapUI: {
          version: "1.1",
          plugins: []
        },
        Loca: {
          version: "1.4.15"
        },
      }).then(async (AMap) => {
        _this.map = await new AMap.Map("trajectoryMap", { //设置地图容器id
          center: [113.01814545605467, 28.201039299894283], // 初始化地图中心点位置
          zoom: 11, //初始化地图层级
          resizeEnable: true,
        });
        if (_this.lineArr.length !== 0) {
          _this.marker = new AMap.Marker({
            map: _this.map,
            position: _this.lineArr[0],
            icon: require("../../../assets/image/car2.png"),
            offset: new AMap.Pixel(-26, -13),
            autoRotaton: true,
            // angle: -90,
          })

          // 绘制轨迹
          _this.polyline = new AMap.Polyline({
            map: _this.map,
            path: _this.lineArr,
            showDir: true,
            strokeColor: "#28F",  //线颜色
            // strokeOpacity: 1,     //线透明度
            strokeWeight: 6,      //线宽
            // strokeStyle: "solid"  //线样式
          });

          _this.passedPolyline = new AMap.Polyline({
            map: _this.map,
            // path: lineArr,
            strokeColor: "#AF5",  //线颜色
            // strokeOpacity: 1,     //线透明度
            strokeWeight: 6,      //线宽
            // strokeStyle: "solid"  //线样式
          });
          _this.marker.on('moving', function (e) {
            _this.passedPolyline.setPath(e.passedPath);
          });
        }
        _this.map.setFitView();


      }).catch(e => {
        console.log(e);
      });
    },
    // 取消按钮
    cancel() {
      this.open = false;
      this.reset();
    },
    // 表单重置
    reset() {
      this.form = {
        id: null,
        terminalNumber: null,
        longitude: null,
        latitude: null,
        createTime: null
      };
      this.resetForm("form");
    },
    /** 搜索按钮操作 */
    handleQuery() {
      this.queryParams.pageNum = 1;
      this.getList();
    },
    /** 重置按钮操作 */
    resetQuery() {
      this.resetForm("queryForm");
      this.handleQuery();
    },
  }
};
</script>