CesiumJS 结合天地图,让你的 3D 建筑模型展现在这茫茫地球上

已收录   阅读次数: 472
2023-04-2110:17:26 发表评论
摘要

好久没分享地图相关的内容了,本篇文章就来介绍一个可以让 3D 模型出现在地球上的库——CesiumJS,结合天地图来实现,那么该如何实现呢?效果如封面图所示,请看本篇文章……

分享至:
CesiumJS 结合天地图,让你的 3D 建筑模型展现在这茫茫地球上

开篇寄语

好久没分享地图相关的内容了,本篇文章就来介绍一个可以让 3D 模型出现在地球上的库——CesiumJS,结合天地图来实现,那么该如何实现呢?效果如封面图所示,请看本篇文章。

前情提要

准备要素

内容详情

准备好以上这些,可以将下面的代码复制粘贴到你的比如 VScode 之类的代码编辑器,将 Cesium Token 和 天地图的 Token 替换成自己的,然后运行就可以了,完整代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <!-- Include the CesiumJS JavaScript and CSS files -->
  <script src="https://unpkg.com/[email protected]/Build/Cesium/Cesium.js"></script>
  <link href="https://unpkg.com/[email protected]/Build/Cesium/Widgets/widgets.css" rel="stylesheet" />
  <script src="https://api.tianditu.gov.cn/cdn/plugins/cesium/cesiumTdt.js"></script>
  <style>
    html,
    body,
    #cesiumContainer {
      padding: 0;
      margin: 0;
      height: 100%;
    }

    #zoomToTileset {
      left: 20px;
      top: 20px;
      position: absolute;
      z-index: 2
    }
  </style>
</head>

<body>
  <button id="zoomToTileset">跳转到九龙</button>
  <div id="cesiumContainer"></div>
  <script>
    // Your access token can be found at: https://ion.cesium.com/tokens.
    // This is the default access token from your ion account

    Cesium.Ion.defaultAccessToken = '你的CesiumJS的token';
    const token = "你的天地图的token"
    var tdtUrl = 'https://t{s}.tianditu.gov.cn/'
    var subdomains = ['0', '1', '2', '3', '4', '5', '6', '7']
    // Initialize the Cesium Viewer in the HTML element with the `cesiumContainer` ID.
    const viewer = new Cesium.Viewer('cesiumContainer', {
      terrainProvider: Cesium.createWorldTerrain(),
      animation: false, //是否创建动画小器件,左下角仪表
      baseLayerPicker: false, //是否显示图层选择器
      fullscreenButton: true, //是否显示全屏按钮
      geocoder: false, //是否显示geocoder小器件,右上角查询按钮
      homeButton: false, //是否显示Home按钮
      infoBox: false, //是否显示信息框
      sceneModePicker: false, //是否显示3D/2D选择器
      selectionIndicator: false, //是否显示选取指示器组件
      timeline: false, //是否显示时间轴
      navigationHelpButton: false //是否显示右上角的帮助按钮
    });
    // Create the tileset in the viewer
    const tileset = viewer.scene.primitives.add(
      new Cesium.Cesium3DTileset({
        url: "./dataTwo/tileset.json",
        projectionTransform: new Cesium.WebMercatorProjection()
      })
    );

    tileset.modelMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(
      Cesium.Cartesian3.fromDegrees(120, 40, 0.0)
    );
    viewer.zoomTo(tileset);
    viewer.camera.flyTo({
      destination: Cesium.Cartesian3.fromDegrees(114.16109523122268,22.289904950356182, 2000),
      orientation: {
        heading: Cesium.Math.toRadians(-90),
        pitch: Cesium.Math.toRadians(-105),
        roll: 0.0
      }
    });
    const zoomToTilesetButton = document.getElementById("zoomToTileset");
    zoomToTilesetButton.addEventListener("click", function () {
      viewer.zoomTo(tileset);
    });
    let heightOffset = 0;
    viewer.scene.preUpdate.addEventListener(function () {
      heightOffset = 0;
      const transform = Cesium.Matrix4.fromTranslation(
        new Cesium.Cartesian3(0, 0, heightOffset)
      );
      tileset.modelMatrix = transform;
    });
    const point = viewer.entities.add({
            position: Cesium.Cartesian3.fromDegrees(114.16199523122268,22.283304950356182),
            point: {
                pixelSize: 10,
                color: Cesium.Color.YELLOW
            }
        });
    //去除版权信息
    viewer._cesiumWidget._creditContainer.style.display = "none";
    // //点击获取光标所在的经纬度
    // var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
    // handler.setInputAction(function (click) {
    //   var cartesian = viewer.camera.pickEllipsoid(click.position, viewer.scene.globe.ellipsoid);
    //   if (cartesian) {
    //     var cartographic = Cesium.Cartographic.fromCartesian(cartesian);
    //     var longitude = Cesium.Math.toDegrees(cartographic.longitude);
    //     var latitude = Cesium.Math.toDegrees(cartographic.latitude);
    //     console.log(longitude, latitude);
    //   }
    // }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
    // 叠加影像服务
    var imgMap = new Cesium.UrlTemplateImageryProvider({
      url: tdtUrl + "DataServer?T=img_w&x={x}&y={y}&l={z}&tk=" + token,
      subdomains: subdomains,
      tilingScheme: new Cesium.WebMercatorTilingScheme(),
      maximumLevel: 18
    });
    viewer.imageryLayers.addImageryProvider(imgMap);

    // 叠加国界服务
    var iboMap = new Cesium.UrlTemplateImageryProvider({
      url: tdtUrl + "DataServer?T=ibo_w&x={x}&y={y}&l={z}&tk=" + token,
      subdomains: subdomains,
      tilingScheme: new Cesium.WebMercatorTilingScheme(),
      maximumLevel: 10
    });
    viewer.imageryLayers.addImageryProvider(iboMap);

    // 叠加地形服务
    var terrainUrls = new Array();

    for (var i = 0; i < subdomains.length; i++) {
      var url =
        tdtUrl.replace("{s}", subdomains[i]) + "mapservice/swdx?tk=" + token;
      terrainUrls.push(url);
    }

    var provider = new Cesium.GeoTerrainProvider({
      urls: terrainUrls
    });

    viewer.terrainProvider = provider;
    // 叠加三维地名服务
    var wtfs = new Cesium.GeoWTFS({
      viewer,
      subdomains: subdomains,
      metadata: {
        boundBox: {
          minX: -180,
          minY: -90,
          maxX: 180,
          maxY: 90
        },
        minLevel: 1,
        maxLevel: 20
      },
      aotuCollide: true, //是否开启避让
      collisionPadding: [5, 10, 8, 5], //开启避让时,标注碰撞增加内边距,上、右、下、左
      serverFirstStyle: true, //服务端样式优先
      labelGraphics: {
        font: "28px sans-serif",
        fontSize: 28,
        fillColor: Cesium.Color.WHITE,
        scale: 0.5,
        outlineColor: Cesium.Color.BLACK,
        outlineWidth: 5,
        style: Cesium.LabelStyle.FILL_AND_OUTLINE,
        showBackground: false,
        backgroundColor: Cesium.Color.RED,
        backgroundPadding: new Cesium.Cartesian2(10, 10),
        horizontalOrigin: Cesium.HorizontalOrigin.MIDDLE,
        verticalOrigin: Cesium.VerticalOrigin.TOP,
        eyeOffset: Cesium.Cartesian3.ZERO,
        pixelOffset: new Cesium.Cartesian2(0, 8)
      },
      billboardGraphics: {
        horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
        verticalOrigin: Cesium.VerticalOrigin.CENTER,
        eyeOffset: Cesium.Cartesian3.ZERO,
        pixelOffset: Cesium.Cartesian2.ZERO,
        alignedAxis: Cesium.Cartesian3.ZERO,
        color: Cesium.Color.WHITE,
        rotation: 0,
        scale: 1,
        width: 18,
        height: 18
      }
    });

    //三维地名服务,使用wtfs服务
    wtfs.getTileUrl = function () {
      return tdtUrl + "mapservice/GetTiles?lxys={z},{x},{y}&tk=" + token;
    };

    wtfs.initTDT([
      {
        x: 6,
        y: 1,
        level: 2,
        boundBox: { minX: 90, minY: 0, maxX: 135, maxY: 45 }
      },
      {
        x: 7,
        y: 1,
        level: 2,
        boundBox: { minX: 135, minY: 0, maxX: 180, maxY: 45 }
      },
      {
        x: 6,
        y: 0,
        level: 2,
        boundBox: { minX: 90, minY: 45, maxX: 135, maxY: 90 }
      },
      {
        x: 7,
        y: 0,
        level: 2,
        boundBox: { minX: 135, minY: 45, maxX: 180, maxY: 90 }
      },
      { x: 5, y: 1, level: 2, boundBox: { minX: 45, minY: 0, maxX: 90, maxY: 45 } },
      { x: 4, y: 1, level: 2, boundBox: { minX: 0, minY: 0, maxX: 45, maxY: 45 } },
      {
        x: 5,
        y: 0,
        level: 2,
        boundBox: { minX: 45, minY: 45, maxX: 90, maxY: 90 }
      },
      { x: 4, y: 0, level: 2, boundBox: { minX: 0, minY: 45, maxX: 45, maxY: 90 } },
      {
        x: 6,
        y: 2,
        level: 2,
        boundBox: { minX: 90, minY: -45, maxX: 135, maxY: 0 }
      },
      {
        x: 6,
        y: 3,
        level: 2,
        boundBox: { minX: 90, minY: -90, maxX: 135, maxY: -45 }
      },
      {
        x: 7,
        y: 2,
        level: 2,
        boundBox: { minX: 135, minY: -45, maxX: 180, maxY: 0 }
      },
      {
        x: 5,
        y: 2,
        level: 2,
        boundBox: { minX: 45, minY: -45, maxX: 90, maxY: 0 }
      },
      { x: 4, y: 2, level: 2, boundBox: { minX: 0, minY: -45, maxX: 45, maxY: 0 } },
      { x: 3, y: 1, level: 2, boundBox: { minX: -45, minY: 0, maxX: 0, maxY: 45 } },
      {
        x: 3,
        y: 0,
        level: 2,
        boundBox: { minX: -45, minY: 45, maxX: 0, maxY: 90 }
      },
      {
        x: 2,
        y: 0,
        level: 2,
        boundBox: { minX: -90, minY: 45, maxX: -45, maxY: 90 }
      },
      {
        x: 0,
        y: 1,
        level: 2,
        boundBox: { minX: -180, minY: 0, maxX: -135, maxY: 45 }
      },
      {
        x: 1,
        y: 0,
        level: 2,
        boundBox: { minX: -135, minY: 45, maxX: -90, maxY: 90 }
      },
      {
        x: 0,
        y: 0,
        level: 2,
        boundBox: { minX: -180, minY: 45, maxX: -135, maxY: 90 }
      }
    ]);
  </script>
  </div>
</body>

</html>

温馨提示

天地图使用的 CensiumJS 有版本需求,推荐使用版本为 1.63.1,切记,切记。

  • 我的微信
  • 微信扫一扫加好友
  • weinxin
  • 我的微信公众号
  • 扫描关注公众号
  • weinxin

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: