Cesium实战记录(七)添加arcgis 矢量服务后二维变三维

前言:

cesium 加载矢量地图后,在三维模式下会平铺在地面上,我们配好的标注也会变形,非常影响效果。如下图所示:加载的arcgis 矢量服务后。

需求:

我们想要加载普通的矢量服务后也要有三维的效果,点图标是立起来的,标注是三维始终面向用户的,面和线是可以在地形上的。

看下渲染的三维效果:

思路:

针对arcgis mapserver :

1、获取屏幕范围

2、获取屏幕范围内的要素点

3、重新渲染

其中第二点可以调用它的服务 query 接口 ,找到一个mapserver ,点进去具体的server ,拉到最下面有个query 点进去,然后在where 一栏中 输入 1 = 1 ,看下地址栏参数,这个页面右上角有help 也可以看下帮助手册。

代码实现:

今天心情不错,直接贴源码吧。提前祝大家新年快乐~~~

<!--加载arcgis server mapserver 矢量-->
<template>
  <div class="box">
    <div class="map-tool">
      <el-button @click="rendererArcisMapserver">开启渲染</el-button>
    </div>
    <div id="mapContainter"></div>
  </div>
</template>


<script>
import * as Cesium from 'cesium';
import "cesium/widgets.css";
import {car3ToDegress} from '@/moudules/common/commonUtils'
import LayerApi from "@/api/layers/LayerApi";
import {markerPoint} from "@/moudules/config/symbolConfig";

var viewer = null;
var arcgisLayer = null;
var billboardC = null;
var labelC = null;
export default {
  name: "statrMapbackup",
  data() {
    return {
      url: 'http://server.mars3d.cn/arcgis/rest/services/mars/hfghss/MapServer',
    }
  },
  mounted() {
    this.initMap();
  },
  methods: {
    initMap() {
      Cesium.Ion.defaultAccessToken = this.CesiumToken;
      //初始化视图
      viewer = new Cesium.Viewer(
          "mapContainter",
          {
            // animation:false
            selectionIndicator: false,//是否创建选择指示符小部件,也就是在选择实体时实体本身会出现一个绿色方块。如果设置为false,则不创建选择指示符小部件
            timeline: false,//时间轴,默认值 true
            infoBox: false,//显示信息框
            imageryProvider: new Cesium.WebMapTileServiceImageryProvider({
              url: 'http://{s}.tianditu.gov.cn/img_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=' + this.tdtToken,
              layer: 'img',
              style: 'default',
              format: 'tiles',
              tileMatrixSetID: 'w',
              subdomains: ['t0', 't1', 't2', 't3', 't4', 't5', 't6', 't7'],
              credit: new Cesium.Credit('天地图影像'),
              maximumLevel: 21
            }),
            terrainProvider: new Cesium.CesiumTerrainProvider({
              url: Cesium.IonResource.fromAssetId(1),
              requestVertexNormals: true,//顶点法线效果
              requestWaterMask: true,//水效果
            })
          }
      )
      // 显示帧率
      viewer.scene.debugShowFramesPerSecond = true;

      //正常加载
      this.addArcgisLayer();
    },
    addArcgisLayer() {
      arcgisLayer = viewer.imageryLayers.addImageryProvider(
          new Cesium.ArcGisMapServerImageryProvider({
            url: this.url,
            rectangle: new Cesium.Rectangle.fromDegrees(
                116.86790296682878,
                31.594039369049813,
                117.55673693657434,
                32.10242163337958
            )
          }),
      );
      viewer.camera.flyTo({
        destination: Cesium.Cartesian3.fromDegrees(117.28, 31.86, 1000000)
      });
    },
    //先获取屏幕区域,再获取区域内要素点,最后渲染
    rendererArcisMapserver() {
      viewer.scene.globe.depthTestAgainstTerrain = true;
      viewer.camera.moveEnd.addEventListener(() => {
        let bounds = this.getCurrentBounds();
        // console.log(bounds)
        let p = {
          'f': 'json',
          'geometry': bounds,
          'geometryType': 'esriGeometryEnvelope',
          'spatialRel': 'esriSpatialRelIntersects',//相交
          "returnGeometry": "true",
          "outFields": "*"
        }
        let url = this.url + '/1/query';
        LayerApi.arcgisQuery(url, p).then((res) => {
          if (res.data.features && res.data.features.length > 0) {
            this.clearLast();
            console.log(res.data.features)
            res.data.features.forEach((item) => {
              let g = item.geometry;
              this.addMarkerPoint(g.x, g.y, item.attributes['设施类型'])
            })
          }
        })
      })

    },
    getCurrentBounds() {
      let bounds = [];
      let car3_lt = viewer.scene.globe.pick(viewer.camera.getPickRay(new Cesium.Cartesian2(0, 0)), viewer.scene);
      let car3_rb = viewer.scene.globe.pick(viewer.camera.getPickRay(new Cesium.Cartesian2(viewer.scene.canvas.width, viewer.scene.canvas.height)), viewer.scene);
      if (!car3_lt) return;
      if (!car3_rb) return;
      let degrees_lt = car3ToDegress(car3_lt);
      let degress_rb = car3ToDegress(car3_rb);
      bounds = {
        "xmin": degrees_lt[0],
        "ymin": degress_rb[1],
        "xmax": degress_rb[0],
        "ymax": degrees_lt[1],
      };
      return bounds;
    },
    clearLast() {
      if (billboardC) {
        billboardC.removeAll();
      } else {
        billboardC = viewer.scene.primitives.add(
            new Cesium.BillboardCollection({
              scene: viewer.scene
            })
        );
      }
      if (labelC) {
        labelC.removeAll();
      } else {
        labelC = viewer.scene.primitives.add(
            new Cesium.LabelCollection({
              scene: viewer.scene
            })
        )
      }
    },
    addMarkerPoint(lng, lat, val) {
      //添加billboard
      billboardC.add({
        position: Cesium.Cartesian3.fromDegrees(lng, lat, 5),
        ...markerPoint.billBoard
      });
      labelC.add({
        position: Cesium.Cartesian3.fromDegrees(lng, lat, 5),
        text: val,
        ...markerPoint.label
      })
    },
  },
  components: {}
}
</script>

<style scoped>
html,
#mapContainter {
  width: 100%;
  height: 98vh;
}
</style>

 markerPoint  配置:

/**
 * @Description: 符号集合
 * @author MrKuang
 * @VX k792794653
 * @date 2022/8/22 0022
*/
import * as Cesium from "cesium";

/**
 * 点图片+点标签
 * @type {{label: {fillColor: Color, outlineWidth: number, verticalOrigin: VerticalOrigin.BOTTOM, showBackground: boolean, outlineColor: module:cesium.Color, horizontalOrigin: HorizontalOrigin.LEFT, style: LabelStyle.FILL_AND_OUTLINE, pixelOffset: module:cesium.Cartesian2, font: string}, billBoard: {image: *, verticalOrigin: VerticalOrigin.BOTTOM, width: number, heightReference: HeightReference.RELATIVE_TO_GROUND, height: number}}}
 */
const markerPoint ={
    billBoard:{
        image:require('@/assets/billboard.png'),
        verticalOrigin:Cesium.VerticalOrigin.BOTTOM,
        heightReference:Cesium.HeightReference.RELATIVE_TO_GROUND,
        height:40,
        width:35,
    },
    label:{
        font : '18px sans-serif',
        fillColor:Cesium.Color.WHITE,
        outlineColor :  new Cesium.Color(0 / 255, 229 / 255, 255 / 255, 0.8),
        outlineWidth : 0.5,
        style:Cesium.LabelStyle.FILL_AND_OUTLINE,
        showBackground:false,
        pixelOffset:new Cesium.Cartesian2(-20,-40),//像素偏移
        horizontalOrigin:Cesium.HorizontalOrigin.LEFT,//相对于对象的原点的水平位置
        verticalOrigin:Cesium.VerticalOrigin.BOTTOM,//相对于对象的原点的垂直位置
    }
}

export {
    markerPoint
}

car3ToDegress 方法:

export const car3ToDegress=(v)=>{
    let c = Cesium.Cartographic.fromCartesian(v);
    let d1 = Cesium.Math.toDegrees(c.longitude);
    let d2 = Cesium.Math.toDegrees(c.latitude);
    return [d1,d2];
}
LayerApi.arcgisQuery 是我自己封装的get 请求,一个参数 是url ,另个参数 是params ,代码里有, 你自己根据ajax 或者 axios 去请求都行

哦了~~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Giser_往事随风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值