ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

定制化天地图-叠加静态图层-并让它动起来

2022-01-02 20:00:10  阅读:363  来源: 互联网

标签:它动 projection 化天 ol new import 图层 图片


天地图提供了网络地图开发接口,同时有部分web开发的插件,但是本文遇到的场景并不考虑使用天地图本身的插件,而是使用openlayer6.x完成需求。

需求

  • 加载天地图影像图层
  • 加载天地图矢量图层
  • 在图层上叠加静态图片,以增强展示效果
  • 希望图片能动起来-旋转以实现雷达图的效果

技术选型

天地图服务注册

这里使用的是天地图的地图服务数据api,api提供了较多开源接口,大家可以按需使用。

注:开发者需要注册webkey,并受到日访问次数限制,生产环境使用,可以升级企业级或政府部门级别,以减少限制。

依赖引入

这里只是openlayer的依赖,vue相关的暂不赘述

//这里只是openlayer的依赖,vue相关的暂不赘述
//openlayer官网的示例的依赖比这里要多,其他的用不到,不需要引入
"ol": "6.9.0"

模块导入

  import 'ol/ol.css';
  import Map from 'ol/Map';
  import TileLayer from 'ol/layer/Tile';
  //WMTS的图层模块
  import WMTS from 'ol/source/WMTS';
  import WMTSTileGrid from 'ol/tilegrid/WMTS';
  //坐标模块
  import {get as getProjection} from 'ol/proj';
  import {getTopLeft, getWidth} from 'ol/extent';
  import View from 'ol/View';
  //图片图层
  import ImageLayer from 'ol/layer/Image';
  import Static from 'ol/source/ImageStatic';
  
  //静态图片的路径
  import mapXWImg from '@/assets/test3.png';

构造影像图层

引入天地图的影响图层

      //影像图层
      let wmtsLayer = new TileLayer({
        opacity: 1,
        source: new WMTS({
          attributions:
            'Tiles © <a href="#"' +
            ' target="_blank">skyocar</a>',
          url: 'http://t{0-7}.tianditu.gov.cn/img_c/wmts?tk=' + this.webKey,
          layer: 'img',
          matrixSet: 'c',
          format: 'image/png',
          projection: this.projection,
          tileGrid: new WMTSTileGrid({
            origin: getTopLeft(projectionExtent),
            resolutions: resolutions,
            matrixIds: matrixIds,
          }),
          style: 'default',
          wrapX: true,
        }),
      });

构造矢量图层

矢量图层的加载是为了地图上展示出地理位置标识等。

//这个是矢量标绘图层,标注底图中的各文字信息
      let cvaLayer = new TileLayer({
        opacity: 0.7,
        source: new WMTS({
          url: 'http://t{0-7}.tianditu.gov.cn/cva_c/wmts?tk=' + this.webKey,
          layer: 'cva',
          matrixSet: 'c',
          format: 'tiles',
          projection: this.projection,
          tileGrid: new WMTSTileGrid({
            origin: getTopLeft(projectionExtent),
            resolutions: resolutions,
            matrixIds: matrixIds,
          }),
          style: 'default',
          wrapX: true,
        }),
      });

加载静态图片层

静态图片的加入可以应对局部地图增强。主要的难点在于中心点定位,这里采用中心定位法,让图片的中心定位到当前屏幕地图中心位置,并设置特定比例的缩放。利用中心点控制、缩放控制,把图片完美的覆盖到地图特定的点位(这也是此次的核心诉求)。

图片图层定位的方法是尝试出来的,并没有找到准确的定位策略,如下。

这里的  -- this.mapCenter = [118.6504, 32.0143]

        /** 叠加图片图层 */
      getImageLayer: function () {
        let p = 0.0001; //图片的缩放尺寸,通过调整图片的加载尺寸和中心点位置,可以调整图片到合适的位置加载
        let w = 1210, h = 1210; //图片的宽、高
        const imageExtent = [
          this.mapCenter[0] - w * p / 2, this.mapCenter[1] - h * p / 2,
          this.mapCenter[0] + w * p / 2, this.mapCenter[1] + h * p / 2
        ];
        return new ImageLayer({
          className: "image_css",
          extent: imageExtent,
          source: new Static({
            url: mapXWImg,
            projection: this.projection,
            imageExtent: imageExtent,
            dragPan: false
          }),
        })
      },

加载地图主类

<template>
  <div class="app-container">
    <div id="map" class="map" ref="rootmap">

    </div>
  </div>
</template>
<style lang='scss'>
  .map {
    width: 100%;
    height: 800px;
  }

  #mouse-position {
    float: right;
    position: absolute;
    right: 3px;
    width: 200px;
    height: 20px;
    /* 将z-index设置为显示在地图上层 */
    z-index: 2000;
  }

</style>
      this.pageMap = new Map({
        layers: [
          wmtsLayer,
          cvaLayer,
          imageLayer,
        ],
        target: 'map',
        view: new View({
          center: this.mapCenter,
          projection: this.projection,
          zoom: 13,
        }),
      });

效果如下: 

让静态图片层动起来

这里是为了应对雷达图的效果,请UI同学切了个雷达图片,然后我控制旋转,就完成了雷达图了。这里是使用css3让地图动起来的,代码如下:

 @-webkit-keyframes rotation {
    from {
      -webkit-transform: rotate(0deg);
    }
    to {
      -webkit-transform: rotate(360deg);
    }
  }

  .image_css {
    -webkit-transform: rotate(360deg);
    animation: rotation 3s linear infinite;
    -moz-animation: rotation 3s linear infinite;
    -webkit-animation: rotation 3s linear infinite;
    -o-animation: rotation 3s linear infinite;
  }

效果如下: 

 

完整的代码

<template>
  <div class="app-container">
    <div id="map" class="map" ref="rootmap">

    </div>
  </div>
</template>

<script>
  import 'ol/ol.css';
  import Map from 'ol/Map';
  import TileLayer from 'ol/layer/Tile';
  import WMTS from 'ol/source/WMTS';
  import WMTSTileGrid from 'ol/tilegrid/WMTS';
  import {get as getProjection} from 'ol/proj';
  import {getTopLeft, getWidth} from 'ol/extent';
  import View from 'ol/View';
  import ImageLayer from 'ol/layer/Image';
  import Static from 'ol/source/ImageStatic';
  //静态图片的路径
  import mapXWImg from '@/assets/test3.png';

  export default {
    name: 'OlMap',
    props: ['tableData', 'targetPoint'],
    data() {
      return {
        map1: null,
        view: null,
        vectorSource: null,
        mousePositionControl: null,
        /** webKey 来源于天地图的开发者密钥,个人开发者有访问限制(每天1万次),
         * 上线项目应该使用客户的信息申请企业或政府,以解除访问限制 https://console.tianditu.gov.cn/api/traffic */
        webKey: '369e7d3985dee029f58564a7747e0dd0',
        // webKey: '2a7fadcac8665927c912c4de29ada090',
        mapCenter: [118.6504, 32.0143], //底图初始中心点
        projection: getProjection('EPSG:4326'),
        pageMap: null
      }
    },
    created() {
    },
    activated() {
    },
    mounted() {
      const projectionExtent = this.projection.getExtent();
      const size = getWidth(projectionExtent) / 256;
      const resolutions = new Array(19);
      const matrixIds = new Array(19);
      for (let z = 0; z < 19; ++z) {
        // generate resolutions and matrixIds arrays for this WMTS
        resolutions[z] = size / Math.pow(2, z);
        matrixIds[z] = z;
      }
      let imageLayer = this.getImageLayer();
      imageLayer.on("change", function (event) {

      });

      //影像图层
      let wmtsLayer = new TileLayer({
        opacity: 1,
        source: new WMTS({
          attributions:
            'Tiles © <a href="#"' +
            ' target="_blank">skyocar</a>',
          url: 'http://t{0-7}.tianditu.gov.cn/img_c/wmts?tk=' + this.webKey,
          layer: 'img',
          matrixSet: 'c',
          format: 'image/png',
          projection: this.projection,
          tileGrid: new WMTSTileGrid({
            origin: getTopLeft(projectionExtent),
            resolutions: resolutions,
            matrixIds: matrixIds,
          }),
          style: 'default',
          wrapX: true,
        }),
      });
      //这个是矢量标绘图层,标注底图中的各文字信息
      let cvaLayer = new TileLayer({
        opacity: 0.7,
        source: new WMTS({
          url: 'http://t{0-7}.tianditu.gov.cn/cva_c/wmts?tk=' + this.webKey,
          layer: 'cva',
          matrixSet: 'c',
          format: 'tiles',
          projection: this.projection,
          tileGrid: new WMTSTileGrid({
            origin: getTopLeft(projectionExtent),
            resolutions: resolutions,
            matrixIds: matrixIds,
          }),
          style: 'default',
          wrapX: true,
        }),
      });

      this.pageMap = new Map({
        layers: [
          wmtsLayer,
          cvaLayer,
          imageLayer,
        ],
        target: 'map',
        view: new View({
          center: this.mapCenter,
          projection: this.projection,
          zoom: 13,
        }),
      });

    },
    methods: {

      /** 叠加图片图层 */
      getImageLayer: function () {
        let p = 0.0001; //图片的缩放尺寸,通过调整图片的加载尺寸和中心点位置,可以调整图片到合适的位置加载
        let w = 1210, h = 1210; //图片的宽、高
        const imageExtent = [
          this.mapCenter[0] - w * p / 2, this.mapCenter[1] - h * p / 2,
          this.mapCenter[0] + w * p / 2, this.mapCenter[1] + h * p / 2
        ];
        return new ImageLayer({
          className: "image_css",
          extent: imageExtent,
          source: new Static({
            url: mapXWImg,
            projection: this.projection,
            imageExtent: imageExtent,
            dragPan: false
          }),
        })
      },

    }

  };
</script>
<style lang='scss'>

  .map {
    width: 100%;
    height: 800px;
  }
  @-webkit-keyframes rotation {
    from {
      -webkit-transform: rotate(0deg);
    }
    to {
      -webkit-transform: rotate(360deg);
    }
  }
  .image_css {
    -webkit-transform: rotate(360deg);
    animation: rotation 3s linear infinite;
    -moz-animation: rotation 3s linear infinite;
    -webkit-animation: rotation 3s linear infinite;
    -o-animation: rotation 3s linear infinite;
  }
</style>

未解决的问题

虽然实现了效果,但依然有瑕疵未完全解决,对于球面坐标系和桌面坐标系的理解依然不足,希望有心人可以指导一二。

  1. 因地图坐标系和桌面坐标系的不同,暂时未找到保持一致的算法,一旦地图拖动,会导致雷达图旋转点错位;
  2. 静态图片叠加的定位算法有待优化,需要找到更适合的算法,以便于快速定位。

标签:它动,projection,化天,ol,new,import,图层,图片
来源: https://blog.csdn.net/lkmtao/article/details/122279316

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有