BIGEMPA Js API示例中心

KML纠偏源代码展示

代码编辑区 运行 下载 还原
<!DOCTYPE html>
<html>

<head>
  <meta charset='UTF-8' />
  <meta name='viewport' content='initial-scale=1,maximum-scale=1,user-scalable=no' />
  <!--
        以下CSS地址请在安装软件了替换成本地的地址
        CSS地址请使用:
        http://192.168.1.222:9000/bigemap.js/v2.1.0/bigemap.css
        软件下载地址 http://www.bigemap.com/reader/download/detail201802017.html
    -->
  <link href='http://www.bigemap.com:9000/bigemap.js/v2.1.0/bigemap.css' rel='stylesheet' />
  <link href="http://www.bigemap.com/Public/css/button.min.css" rel="stylesheet">
  <!--
        JS地址请使用:
        http://192.168.1.222:9000/bigemap.js/v2.1.0/bigemap.js
    -->
  <script src='http://www.bigemap.com:9000/bigemap.js/v2.1.0/bigemap.js'></script>
  <!--
        引入加载KML的JS插件
    -->
  <script type="text/javascript" src="http://www.bigemap.com/mapoffline/js/togeojson.js"></script>
  <!-- 引入Geojson转换KML的js插件 -->
  <script src="http://demo.bigemap.com/static/map/js/tokml.js"></script>
  <style>
    body {
      margin: 0;
      padding: 0;
    }

    #map {
      position: absolute;
      top: 0;
      bottom: 0;
      width: 100%;
    }

    .tool {
      position: absolute;
      z-index: 10;
      right: 10px;
      top: 60px;
    }

    .info {
      position: fixed;
      top: 40px;
      color: #8a6d3b;
      z-index: 99;
      margin: 0;
      background-color: #fcf8e3;
      border-color: #faebcc;
      left: 0;
      right: 0;
      text-align: center;
    }

    #ceng {
      position: absolute;
      top: 120px;
      left: 0;
      z-index: 10;

    }

    #ceng::before {
      content: '当前地图源:';
      position: absolute;
      left: 0;
      right: 0;
      bottom: -10px;
      padding: 5px 10px;
      top: -40px;
      background-color: #369;
      border-radius: 5px;
      font-size: 14px;
      color: #fff;
      z-index: -1;
    }

    #checkExport {
      display: none;
      position: absolute;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
      width: 600px;
      height: 400px;
      background-color: skyblue;
      border: slategrey 1px solid;
      z-index: 10000;
      padding: 10px 0 0 10px;
    }

    #checkExport>div {
      padding: 10px;
      outline: turquoise 1px solid;
    }

    #checkExport>button {
      position: absolute;
      right: 0;
      top: 0;
      margin: 5px 5px 0 0;
    }
  </style>
  <title>切换图层</title>
</head>

<body>
  <p class="info">
    数据保存在本地,刷新会消失,仅仅用作测试,左侧仅供纠偏效果展示使用,切换会清楚当前覆盖物
  </p>
  <p class="tool">
    <a id="satellite" class="button button-tiny button-rounded button-primary" href="javascript:void (0);">导入KML</a>
    <a id="export" class="button button-tiny button-rounded button-primary" href="javascript:void (0);">导出</a>
    <input type="file" accept=".kml,.json" style="display: none" id="upload">
  </p>
  <div id="ceng">
    <a href="javascript:void(0)" data-type="arcgis-satellite" data-map="arcgis"
      class="button button-tiny button-rounded">arcgis(wgs 84)</a>
    <a href="javascript:void(0)" data-type="baidu-map" data-map="baidu"
      class="button button-tiny button-rounded">百度(bd09)</a>
    <a href="javascript:void(0)" data-type="amap-map" data-map="amap"
      class="button button-tiny button-rounded button-primary">高德(gcj02)</a>
  </div>
  <div id="checkExport">
    <div>
      <span>导入数据坐标系</span>
      <select name="" id="from">
        <option value="">请选择</option>
        <option value="WGS84">WGS84(无偏移)</option>
        <option value="Gcj-02">火星坐标系(Gcj-02)</option>
        <option value="BD-09">百度坐标系(BD-09)</option>
      </select>
    </div>
    <div>
      <span>导出数据源</span>
      <select name="" id="to" autofocus>
        <option value="">请选择</option>
        <option value="WGS84">WGS84(无偏移)</option>
        <option value="Gcj-02">火星坐标系(Gcj-02)</option>
        <option value="BD-09">百度坐标系(BD-09)</option>
      </select>
    </div>
    <div>
      <span>导出格式</span>
      <select name="" id="form" autofocus>
        <option value="">请选择</option>
        <option value="geoJSON">geoJSON</option>
        <option value="kml">kml</option>
      </select>
    </div>
    <a href="javascript:void(0)" class="button button-tiny button-rounded button-primary"
      download="javascript:void(0)">确认导出</a>
    <button>x</button>
  </div>
  <a download="" style="display: none;" id="download"></a>
  <div id='map'></div>
  <script src="http://www.bigemap.com/Public/common/js/jquery.min.js"></script>
  <script src="http://demo.bigemap.com/static/map/js/tokml.js"></script>
  <script type="text/javascript">
    // 软件配置信息地址,软件安装完成之后使用本地地址,如:http://192.168.1.222:9000
    BM.Config.HTTP_URL = 'http://www.bigemap.com:9000';
    // 在ID为map的元素中实例化一个地图,并设置地图的ID号为 bigemap.baidu-map,ID号程序自动生成,无需手动配置,并设置地图的投影为百度地图 ,中心点,默认的级别和显示级别控件
    var map = BM.map('map', 'bigemap.amap-map', {
      center: [30.66, 104.001],
      zoom: 15,
      zoomControl: true,
      attributionControl: false,
      preferCanvas: true, //适用于数据量大时 地图反应速度加快
    });
    var btns = document.querySelectorAll('#ceng a');
    $('#ceng').on('click', 'a', function () {
      $('#ceng a').removeClass('button-primary');
      $(this).addClass('button-primary');
      var type = $(this).data('map');
      var crs = type === 'baidu' ? BM.CRS.Baidu : BM.CRS.EPSG3857;
      geo && geo.remove(), geo = null;
      map.remove();
      map = BM.map('map', 'bigemap.{id}'.replace('{id}', $(this).data('type')), {
        crs,
        center: [30.66, 104.001],
        zoom: 15,
        preferCanvas: true,
        zoomControl: true
      });

      if (cacheData) {
        geo = BM.geoJSON(cacheData, {
          style: function (feature) { }
        }).bindPopup(function (layer) {
          return `<div><h4>${layer.feature.properties.name}</h4>
             <p>${layer.feature.properties.description}</p></div>`
        }).addTo(map);
        map.fitBounds(geo.getBounds());
      }
    });
    var blob, href, geo, cacheData, geo_copy;
    var bdcj = {
      features: [],
      type: "FeatureCollection"
    },
      cjbd = {
        features: [],
        type: "FeatureCollection"
      };
      var filename;
    $('#upload').on('change', function () {
      var file = this.files[0];
      var extension = file.name.split('.');
      filename=extension[0];
      extension = extension.pop();
      if (extension !== 'kml' && extension !== 'json') {
        alert('只能是KML或json格式');
        return;
      }
      var reader = new FileReader();
      reader.readAsText(file);
      reader.onload = function () {
        var dom, geojsonFeature = JSON.parse(this.result);
        cacheData = geojsonFeature;
        if (extension == 'kml') {
          dom =
            (new DOMParser()).parseFromString(this.result, 'text/xml');
          geojsonFeature =
            toGeoJSON.kml(dom);
        }
        geo && geo.remove();
        geo = BM.geoJSON(geojsonFeature, {
          style: function (feature) { },
        }).bindPopup(function (layer) {
          return `<div><h4>${layer.feature.properties.name}</h4>
            <p>${layer.feature.properties.description}</p></div>`
        }).addTo(map);
        map.fitBounds(geo.getBounds());
      }
    });
    $('#satellite').on('click', function () { //显示上传
      $('#upload').click();
    });
    $('#export').click(function () {
      $('#checkExport').show();
    })
    $('#checkExport>button').click(function () {
      $('#from').val('');
      $('#to').val('');
      $('#form').val('');
      $('#checkExport').hide();
    })
    $('#checkExport>a').click(function () {
      let from = $('#from').val(); //从
      let to = $('#to').val(); //到
      let form = $('#form').val(); //格式
      if (from && to && form && geo) {
        let fn
        if (from == to) {
          fn = (lat, lng) => {
            return [lat, lng]
          }
          transform(fn);
        } else {
          if (from == 'WGS84') {
            if (to == 'Gcj-02') {
              fn = wgs84togcj02;
              transform(fn);
            } else {
              fn = (lat, lng) => {
                return gcj02tobd09(...wgs84togcj02(lat, lng))
              }
              transform(fn);
            }
          } else if (form == 'Gcj-02') {
            if (to == 'WGS84') {
              fn = gcj02towgs84
              transform(fn);
            } else {
              fn = gcj02tobd09
              transform(fn);
            }
          } else {
            if (to == 'WGS84') {
              fn = (lat, lng) => {
                return gcj02towgs84(...bd09togcj02(lat, lng))
              }
              transform(fn);
            } else {
              fn = bd09togcj02
              transform(fn);
            }
          }
        }

        $('#checkExport>button').click(); //清空选项

        if (form == 'kml') {
          var blob = new Blob([tokml(geo1.toGeoJSON())]);
          var href = URL.createObjectURL(blob);
          $('#download').prop('href', href);
          $('#download').prop('download', `${filename}.kml`);
          document.querySelector('#download').click();
        } else {
          var blob = new Blob([JSON.stringify(geo1.toGeoJSON())]);
          var href = URL.createObjectURL(blob);
          $('#download').prop('href', href);
          $('#download').prop('download', `${filename}.geojson`);
          document.querySelector('#download').click();
        }
      } else {
        alert('巧妇难为无米之炊哦,把数据和选项整好再点呗')
      }
    })

    function transform(fn) {
      geo1 = BM.geoJSON(cacheData, {
        coordsToLatLng(feature, index) {
          let latlng = fn(feature[1], feature[0]);
          return BM.latLng(latlng[0], latlng[1]);
        }
      })
    }
    //定义一些常量用于算法纠偏
    var x_PI = 3.14159265358979324 * 3000.0 / 180.0;
    var PI = 3.1415926535897932384626;
    var a = 6378245.0;
    var ee = 0.00669342162296594323;

    /**
     * 百度坐标系 (BD-09) 与 火星坐标系 (GCJ-02)的转换
     * 即 百度 转 谷歌、高德
     */
    function bd09togcj02(bd_lat, bd_lon) {
      var x_pi = 3.14159265358979324 * 3000.0 / 180.0;
      var x = bd_lon - 0.0065;
      var y = bd_lat - 0.006;
      var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * x_pi);
      var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * x_pi);
      var gg_lng = z * Math.cos(theta);
      var gg_lat = z * Math.sin(theta);
      return [gg_lat, gg_lng]
    }

    /**
     * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换
     * 即谷歌、高德 转 百度
     */
    function gcj02tobd09(lat, lng) {
      var z = Math.sqrt(lng * lng + lat * lat) + 0.00002 * Math.sin(lat * x_PI);
      var theta = Math.atan2(lat, lng) + 0.000003 * Math.cos(lng * x_PI);
      var bd_lng = z * Math.cos(theta) + 0.0065;
      var bd_lat = z * Math.sin(theta) + 0.006;
      return [bd_lat, bd_lng]
    }

    /**
     * WGS84转GCj02
     */
    function wgs84togcj02(lat, lng) {
      if (out_of_china(lng, lat)) {
        return [lat, lng]
      } else {
        var dlat = transformlat(lng - 105.0, lat - 35.0);
        var dlng = transformlng(lng - 105.0, lat - 35.0);
        var radlat = lat / 180.0 * PI;
        var magic = Math.sin(radlat);
        magic = 1 - ee * magic * magic;
        var sqrtmagic = Math.sqrt(magic);
        dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI);
        dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI);
        var mglat = lat + dlat;
        var mglng = lng + dlng;
        return [mglat, mglng]
      }
    }

    /**
     * GCJ02 转换为 WGS84
     */
    function gcj02towgs84(lat, lng) {
      if (out_of_china(lng, lat)) {
        return [lat, lng]
      } else {
        var dlat = transformlat(lng - 105.0, lat - 35.0);
        var dlng = transformlng(lng - 105.0, lat - 35.0);
        var radlat = lat / 180.0 * PI;
        var magic = Math.sin(radlat);
        magic = 1 - ee * magic * magic;
        var sqrtmagic = Math.sqrt(magic);
        dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * PI);
        dlng = (dlng * 180.0) / (a / sqrtmagic * Math.cos(radlat) * PI);
        mglat = lat + dlat;
        mglng = lng + dlng;
        return [lat * 2 - mglat, lng * 2 - mglng]
      }
    }

    function transformlat(lng, lat) {
      var ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));
      ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
      ret += (20.0 * Math.sin(lat * PI) + 40.0 * Math.sin(lat / 3.0 * PI)) * 2.0 / 3.0;
      ret += (160.0 * Math.sin(lat / 12.0 * PI) + 320 * Math.sin(lat * PI / 30.0)) * 2.0 / 3.0;
      return ret
    }

    function transformlng(lng, lat) {
      var ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));
      ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;
      ret += (20.0 * Math.sin(lng * PI) + 40.0 * Math.sin(lng / 3.0 * PI)) * 2.0 / 3.0;
      ret += (150.0 * Math.sin(lng / 12.0 * PI) + 300.0 * Math.sin(lng / 30.0 * PI)) * 2.0 / 3.0;
      return ret
    }

    /**
     * 判断是否在国内,不在国内则不做偏移
     */
    function out_of_china(lng, lat) {
      return (lng < 72.004 || lng > 137.8347) || ((lat < 0.8293 || lat > 55.8271) || false);
    }
  </script>
</body>

</html>