OpenLayers使用高德导航接口实现动画animate

需求:项目需要做一个救援动画效果
技术栈:react、openlayer、高德导航接口、天地图导航接口

零、选择导航接口

老大最开始建议使用天地图导航接口,测试后接口响应时间大约为30秒以上,达不到商用条件。因此选择高德的接口。

一、调用高德接口

1、1申请key

在高德官网注册用户,创建应用,申请key
地址:https://lbs.amap.com/api/webservice/summary
点击【获取key】,按提示进入控制台,创建应用,创建key
在这里插入图片描述
在这里插入图片描述
创建应用,在应用下边添加key。我需要调用webapi中的【路径规划API】所以选择的是Web服务
在这里插入图片描述

1.2测试接口

https://restapi.amap.com/v3/direction/driving?origin=[出发经度],[出发纬度]&destination=[目标经度],[目标纬度]&extensions=all&output=json&key=[key]
在这里插入图片描述

二、实现导航

2.1、拾取爆点坐标

爆点的样式:对点要素的样式设置为pipeBroken图片

const pipeBrokenStyle = new Style({
  image: new Icon({
    anchor: [0.5, 20],
    anchorXUnits: 'fraction',
    anchorYUnits: 'pixels',
    src: pipeBroken,
  }),
});

处理点击地图事件。获取鼠标点击的坐标,构建点要素,绘制到地图上。同时写入state。构建查询资源的参数

 beginGetFeatureInfo = (event) => {
    const {map} = this.props;
    const {featuresVectorSource, clickFeature} = this.state;
    if (clickFeature) {
      if (featuresVectorSource.getFeatures().length > 0) {
        try {
          clearMap(map);
        } catch (e) {
          console.log(e);
        }
      }
    }
    const pipeBrokenFeature = new Feature({
      geometry: new Point(event.coordinate),
    });
    pipeBrokenFeature.setStyle(pipeBrokenStyle);
    const pointInfo = `point(${event.coordinate[0]} ${event.coordinate[1]})`;
    this.setState({clickFeature: pipeBrokenFeature, pointInfo,}, () => {
      featuresVectorSource.addFeature(pipeBrokenFeature);
      this.getResources();
    });
  };

2.2、获取资源坐标

调用业务系统接口查询资源的坐标,此部分按自己的业务系统处理即可,不做展示。

2.3、坐标转换

此时具备了资源坐标和爆点的坐标,构造高德导航参数即可。但是项目中使用的是3857坐标系,需要进行转换。
3857转4326使用的是proj4组件
4326转gcj02使用的是coordtransform组件(
https://www.npmjs.com/package/coordtransform
https://github.com/wandergis/coordtransform)
从3857转到4326再转换到gcj02(高德使用的是gcj02)

   trans3857To4326 = (coordinate) => {
    return proj4('EPSG:3857', 'EPSG:4326', coordinate);
  }
  // 进行坐标转换 3857转wgs84
    const coordClick = this.trans3857To4326(clickFeature.getGeometry().getCoordinates());  
    // 84再转gcj02
    const clickCoord = coordtransform.wgs84togcj02(coordClick[0], coordClick[1]);   

2.4、调用接口

调用接口。建议使用axios而不是Fetch。最开始使用fetch总是调用失败,卡了一天。同事说试试axios,一下就通了

  /**
   * 导航
   */
  navigationRequest = (origin, destination) => {
    // 高德
    const url = `https://restapi.amap.com/v3/direction/driving?origin=${origin[0]},${origin[1]}&destination=${destination[0]},${destination[1]}&extensions=all&output=json&key=[自己的key]`
    return axios.get(url)
      .then(function (response) {
        return response;
      })
      .catch(function (error) {
        console.log(error)
        return error;
      });
  }

2.5、解析数据

返回数据的结构参见接口说明。我只需要【行驶距离】、【预计行驶时间】和路径坐标。
在这里插入图片描述

返回的数据需要坐标转换。从gcj02转4326,再转3857.转换函数如下


  trans4326To3857 = (coordinate) => {
    return proj4('EPSG:4326', 'EPSG:3857', coordinate);
  }
// 生成轨迹要素
  drawLineFeature = (steps) => {
    // 取出所有polyline拼接为键值对
    let polylines = "";
    for (let i = 0; i < steps.length; i++) {
      polylines += steps[i].polyline;
      polylines += ";";
    }
    const points = polylines.split(";");
    const pointList = [];
    const pointList3857 = [];
    for (let i = 0; i < points.length - 1; i++) {
      pointList.push(points[i].split(","));
      pointList3857.push(this.trans4326To3857(coordtransform.gcj02towgs84(points[i].split(",")[0], points[i].split(",")[1])));
    }

    return new Feature({geometry: new LineString(pointList3857)});
  }

2.6、生成动效

动效需要路径要素:reliefSuppliesDriveLine、移动的点:reliefSuppliesCarFeatureTemp。在图层reliefSuppliesCarVL中对要素reliefSuppliesCarFeatureTemp添加动画路径anim,获得控制器reliefSuppliesPlayController。
控制器可以用于终止动画


  /**
   * 开始物资动画
   */
  startReliefSuppliesAnimation = () => {
    const {
      selectedReliefSupplies, reliefSuppliesDriveLine, reliefSuppliesCarVS, reliefSuppliesCarVL, reliefSuppliesCarFeature,
    } = this.state;

    const anim = new Path({
      path: reliefSuppliesDriveLine,
      rotate: true,
      easing: linear,
      duration: 0.25 * 60 * 1000,
      revers: false,
      repeat: 99999999,
    });
    
    reliefSuppliesCarVS.addFeature(reliefSuppliesDriveLine);
    if (!reliefSuppliesCarFeature) {
      const reliefSuppliesCarFeatureTemp = new Feature({
        zIndex: 999999999999,
        geometry: new Point(selectedReliefSupplies.getGeometry().getCoordinates()),
      });
      reliefSuppliesCarVS.addFeature(reliefSuppliesCarFeatureTemp);
      // 动画
      const reliefSuppliesPlayController = reliefSuppliesCarVL.animateFeature(reliefSuppliesCarFeatureTemp, anim);
      this.setState({reliefSuppliesCarFeature: reliefSuppliesCarFeatureTemp, reliefSuppliesPlayController});
    }
  }

有效代码:reliefSuppliesPlayController.stop();

  /**
   * 清除救援物资动画
   */
  clearReliefSuppliesAnimation = () => {
    const {
      reliefSuppliesCarVS, reliefSuppliesDriveLine, reliefSuppliesCarFeature, reliefSuppliesPlayController,
    } = this.state;
    if (reliefSuppliesPlayController) {
      reliefSuppliesPlayController.stop();
    }
    if (reliefSuppliesCarFeature) {
      reliefSuppliesCarVS.removeFeature(reliefSuppliesCarFeature);
      this.setState({reliefSuppliesCarFeature: null});
    }
    if (reliefSuppliesDriveLine) {
      reliefSuppliesCarVS.removeFeature(reliefSuppliesDriveLine);
      this.setState({reliefSuppliesDriveLine: null});
    }
    reliefSuppliesCarVS.clear();
  }
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值