花椒和邻居's Blog 花椒和邻居's Blog
首页
前端
开源
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • Java程序员
收藏
关于
随笔
GitHub (opens new window)

花椒和邻居

工作了三年半的前端实习生
首页
前端
开源
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • Java程序员
收藏
关于
随笔
GitHub (opens new window)
  • 前端开发笔记

  • JavaScript

  • 3D地图相关

    • Cesium入门
      • ⭐️Cesium是为3D地图而打造的开源软件
        • 🔨安装
        • 使用
    • Cesium一般使用
  • 前端
  • 3D地图相关
花椒和邻居
2022-03-02
目录

Cesium入门原创

# ⭐️Cesium是为3D地图而打造的开源软件

# 🔨安装

虽然作为一名前端开发人员,但并非gis专业人士,所以推荐这个微信公众号,专门讲解cesium如何使用的 (opens new window)

注意

🐛Cesium并非cnpm i cesium直接就结束了,它需要在webpack中添加额外的参数配置并引入相关资源文件

当前使用的版本号为 "vue": "^2.6.12","cesium": "^1.73.0","@vue/cli-service": "~4.5.0",

module.exports = {
  lintOnSave: false,
  publicPath:
    process.env.NODE_ENV === "production" ? "/\n" + "vue-cesium-example/" : "/",
  configureWebpack: {
    plugins: [
      // Copy Cesium Assets, Widgets, and Workers to a static directory
      new CopyWebpackPlugin({
        patterns: [
          { from: "node_modules/cesium/Build/Cesium/Workers", to: "Workers" },
          {
            from: "node_modules/cesium/Build/Cesium/ThirdParty",
            to: "ThirdParty"
          },
          { from: "node_modules/cesium/Build/Cesium/Assets", to: "Assets" },
          { from: "node_modules/cesium/Build/Cesium/Widgets", to: "Widgets" }
        ]
      }),
      new webpack.DefinePlugin({
        // Define relative base path in cesium for loading assets
        CESIUM_BASE_URL: JSON.stringify("")
      })
    ],
    module: {
      // Removes these errors: "Critical dependency: require function is used in a way in which dependencies cannot be statically extracted"
      // https://github.com/AnalyticalGraphicsInc/cesium-webpack-example/issues/6
      unknownContextCritical: false,
      unknownContextRegExp: /\/cesium\/cesium\/Source\/Core\/buildModuleUrl\.js/
    }
  }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

推荐一套为 GISer 准备的基于 Vue 2.x & Vue 3.x 的 CesiumJS 组件库 VueCesium (opens new window),减少开发工作量.

# 使用

使用vue中的template语法按照官方文档提供的例子即可实现一个如下所示的地图

preview.gif

注意

启动项目后可能会有cesium文件找不到的错误,此时需要将cesium的build包放入public中static文件夹下面,并引用public下面的cesium中js和css, 注意路径的正确性 以保证正常引入

点击查看

<template>
  <div id="cesiumContainer"></div>
</template>

<script>
import "cesium/Build/Cesium/Widgets/widgets.css";
import * as Cesium from "cesium";
import AmapImageryProvider from "@/transform/AmapImageryProvider";
import "./Sandcastle-header";
function startup(Cesium) {
  'use strict';
//Sandcastle_Begin
  const viewer = new Cesium.Viewer("cesiumContainer", {
    terrainProvider: Cesium.createWorldTerrain(),
  });

  const tileset = new Cesium.Cesium3DTileset({
    url: Cesium.IonResource.fromAssetId(40866),
  });
  viewer.scene.primitives.add(tileset);

  tileset.readyPromise.then(function () {
    const boundingSphere = tileset.boundingSphere;
    viewer.camera.viewBoundingSphere(
        boundingSphere,
        new Cesium.HeadingPitchRange(
            0.0,
            -0.5,
            boundingSphere.radius + 500.0
        )
    );
    viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
  });

  const polygon = viewer.entities.add({
    polygon: {
      hierarchy: new Cesium.PolygonHierarchy(
          Cesium.Cartesian3.fromRadiansArray([
            -1.3194369277314022,
            0.6988062530900625,
            -1.3193955980204217,
            0.6988091578771254,
            -1.3193931220959367,
            0.698743632490865,
            -1.3194358224045408,
            0.6987471965556998,
          ])
      ),
      material: Cesium.Color.RED.withAlpha(0.5),
      classificationType: Cesium.ClassificationType.BOTH,
    },
  });

  const polyline = viewer.entities.add({
    polyline: {
      positions: Cesium.Cartesian3.fromDegreesArray([
        -75.60217330403601,
        40.04102882709425,
        -75.59968252414251,
        40.04093615560871,
        -75.598020153828,
        40.04079437042357,
        -75.59674934074435,
        40.040816173283304,
        -75.59630042791713,
        40.03986900370842,
        -75.59563636849978,
        40.03930996506271,
        -75.59492397899098,
        40.03873932846581,
        -75.59457991226778,
        40.038392701955786,
        -75.59424838652453,
        40.03775403572295,
        -75.59387104290336,
        40.03677022167725,
        -75.59355000490342,
        40.03588760913535,
      ]),
      width: 8,
      material: new Cesium.PolylineOutlineMaterialProperty({
        color: Cesium.Color.YELLOW,
        outlineWidth: 2,
        outlineColor: Cesium.Color.BLACK,
      }),
      clampToGround: true,
    },
  });

  const classificationOptions = [
    {
      text: "Classify Both",
      onselect: function () {
        polygon.polygon.classificationType =
            Cesium.ClassificationType.BOTH;
        polyline.polyline.classificationType =
            Cesium.ClassificationType.BOTH;
      },
    },
    {
      text: "Classify Terrain",
      onselect: function () {
        polygon.polygon.classificationType =
            Cesium.ClassificationType.TERRAIN;
        polyline.polyline.classificationType =
            Cesium.ClassificationType.TERRAIN;
      },
    },
    {
      text: "Classify 3D Tiles",
      onselect: function () {
        polygon.polygon.classificationType =
            Cesium.ClassificationType.CESIUM_3D_TILE;
        polyline.polyline.classificationType =
            Cesium.ClassificationType.CESIUM_3D_TILE;
      },
    },
  ];

  const materialOptions = [
    {
      text: "Red Material",
      onselect: function () {
        polygon.polygon.material = Cesium.Color.RED.withAlpha(0.5);
      },
    },
    {
      text: "Textured Material",
      onselect: function () {
        if (
            !Cesium.Entity.supportsMaterialsforEntitiesOnTerrain(
                viewer.scene
            )
        ) {
          window.alert(
              "Terrain Entity materials are not supported on this platform"
          );
        }
        polygon.polygon.material = "../images/Cesium_Logo_Color.jpg";
      },
    },
  ];

  Sandcastle.addToolbarMenu(classificationOptions);
  Sandcastle.addToolbarMenu(materialOptions);
//Sandcastle_End
  Sandcastle.finishedLoading();
}

export default {
  name: "Map",
  mounted() {
    startup(Cesium)
  },
  methods: {
    init() {
      const viewer = new Cesium.Viewer("cesiumContainer", {
        shouldAnimate: true
      });
      const planePosition = Cesium.Cartesian3.fromDegrees(
        -75.59777,
        40.03883,
        800.0
      );
      const particlesOffset = new Cesium.Cartesian3(
        -8.950115473940969,
        34.852766731753945,
        -30.235411095432937
      );
      const cameraLocation = Cesium.Cartesian3.add(
        planePosition,
        particlesOffset,
        new Cesium.Cartesian3()
      );
      const resetCamera = function() {
        viewer.camera.lookAt(
          cameraLocation,
          new Cesium.Cartesian3(-450, -300, 200)
        );
      };
      resetCamera();

      // Draw particle image to a canvas
      let particleCanvas;
      function getImage() {
        if (!Cesium.defined(particleCanvas)) {
          particleCanvas = document.createElement("canvas");
          particleCanvas.width = 20;
          particleCanvas.height = 20;
          const context2D = particleCanvas.getContext("2d");
          context2D.beginPath();
          context2D.arc(8, 8, 8, 0, Cesium.Math.TWO_PI, true);
          context2D.closePath();
          context2D.fillStyle = "rgb(255, 255, 255)";
          context2D.fill();
        }
        return particleCanvas;
      }

      // Add plane to scene
      const hpr = new Cesium.HeadingPitchRoll(
        0.0,
        Cesium.Math.PI_OVER_TWO,
        0.0
      );
      const orientation = Cesium.Transforms.headingPitchRollQuaternion(
        planePosition,
        hpr
      );
      const entity = viewer.entities.add({
        model: {
          uri: "../SampleData/models/CesiumAir/Cesium_Air.glb",
          scale: 3.5
        },
        position: planePosition,
        orientation: orientation
      });

      // creating particles model matrix
      const translationOffset = Cesium.Matrix4.fromTranslation(
        particlesOffset,
        new Cesium.Matrix4()
      );
      const translationOfPlane = Cesium.Matrix4.fromTranslation(
        planePosition,
        new Cesium.Matrix4()
      );
      const particlesModelMatrix = Cesium.Matrix4.multiplyTransformation(
        translationOfPlane,
        translationOffset,
        new Cesium.Matrix4()
      );

      // creating the particle systems
      const rocketOptions = {
        numberOfSystems: 50.0,
        iterationOffset: 0.1,
        cartographicStep: 0.000001,
        baseRadius: 0.0005,

        colorOptions: [
          {
            minimumRed: 1.0,
            green: 0.5,
            minimumBlue: 0.05,
            alpha: 1.0
          },
          {
            red: 0.9,
            minimumGreen: 0.6,
            minimumBlue: 0.01,
            alpha: 1.0
          },
          {
            red: 0.8,
            green: 0.05,
            minimumBlue: 0.09,
            alpha: 1.0
          },
          {
            minimumRed: 1,
            minimumGreen: 0.05,
            blue: 0.09,
            alpha: 1.0
          }
        ]
      };

      const cometOptions = {
        numberOfSystems: 100.0,
        iterationOffset: 0.003,
        cartographicStep: 0.0000001,
        baseRadius: 0.0005,

        colorOptions: [
          {
            red: 0.6,
            green: 0.6,
            blue: 0.6,
            alpha: 1.0
          },
          {
            red: 0.6,
            green: 0.6,
            blue: 0.9,
            alpha: 0.9
          },
          {
            red: 0.5,
            green: 0.5,
            blue: 0.7,
            alpha: 0.5
          }
        ]
      };

      let scratchCartesian3 = new Cesium.Cartesian3();
      let scratchCartographic = new Cesium.Cartographic();
      const forceFunction = function(options, iteration) {
        return function(particle, dt) {
          dt = Cesium.Math.clamp(dt, 0.0, 0.05);

          scratchCartesian3 = Cesium.Cartesian3.normalize(
            particle.position,
            new Cesium.Cartesian3()
          );
          scratchCartesian3 = Cesium.Cartesian3.multiplyByScalar(
            scratchCartesian3,
            -40.0 * dt,
            scratchCartesian3
          );

          scratchCartesian3 = Cesium.Cartesian3.add(
            particle.position,
            scratchCartesian3,
            scratchCartesian3
          );

          scratchCartographic = Cesium.Cartographic.fromCartesian(
            scratchCartesian3,
            Cesium.Ellipsoid.WGS84,
            scratchCartographic
          );

          const angle =
            (Cesium.Math.PI * 2.0 * iteration) / options.numberOfSystems;
          iteration += options.iterationOffset;
          scratchCartographic.longitude +=
            Math.cos(angle) * options.cartographicStep * 30.0 * dt;
          scratchCartographic.latitude +=
            Math.sin(angle) * options.cartographicStep * 30.0 * dt;

          particle.position = Cesium.Cartographic.toCartesian(
            scratchCartographic
          );
        };
      };

      const matrix4Scratch = new Cesium.Matrix4();
      let scratchAngleForOffset = 0.0;
      const scratchOffset = new Cesium.Cartesian3();
      const imageSize = new Cesium.Cartesian2(15.0, 15.0);
      function createParticleSystems(options, systemsArray) {
        const length = options.numberOfSystems;
        for (let i = 0; i < length; ++i) {
          scratchAngleForOffset = (Math.PI * 2.0 * i) / options.numberOfSystems;
          scratchOffset.x +=
            options.baseRadius * Math.cos(scratchAngleForOffset);
          scratchOffset.y +=
            options.baseRadius * Math.sin(scratchAngleForOffset);

          const emitterModelMatrix = Cesium.Matrix4.fromTranslation(
            scratchOffset,
            matrix4Scratch
          );
          const color = Cesium.Color.fromRandom(
            options.colorOptions[i % options.colorOptions.length]
          );
          const force = forceFunction(options, i);

          const item = viewer.scene.primitives.add(
            new Cesium.ParticleSystem({
              image: getImage(),
              startColor: color,
              endColor: color.withAlpha(0.0),
              particleLife: 3.5,
              speed: 0.00005,
              imageSize: imageSize,
              emissionRate: 30.0,
              emitter: new Cesium.CircleEmitter(0.1),
              lifetime: 0.1,
              updateCallback: force,
              modelMatrix: particlesModelMatrix,
              emitterModelMatrix: emitterModelMatrix
            })
          );
          systemsArray.push(item);
        }
      }

      const rocketSystems = [];
      const cometSystems = [];
      createParticleSystems(rocketOptions, rocketSystems);
      createParticleSystems(cometOptions, cometSystems);

      // toolbar elements
      function showAll(systemsArray, show) {
        const length = systemsArray.length;
        for (let i = 0; i < length; ++i) {
          systemsArray[i].show = show;
        }
      }

      const options = [
        {
          text: "Comet Tail",
          onselect: function() {
            showAll(rocketSystems, false);
            showAll(cometSystems, true);
            resetCamera();
          }
        },
        {
          text: "Rocket Thruster",
          onselect: function() {
            showAll(cometSystems, false);
            showAll(rocketSystems, true);
            resetCamera();
          }
        }
      ];
      Sandcastle.addToolbarMenu(options);
    }
  }
};
</script>

<style lang="scss">
#cesiumContainer {
  width: 100vw;
  height: 100vh;
  margin: 0;
  padding: 0;
  overflow: hidden;
}

.cesium-viewer-bottom {
  display: none !important;
}
</style>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
去GitHub编辑 (opens new window)
#Cesium 3D#javascript
上次更新: 2022/03/30, 09:09:08
比typeof运算符更准确的类型判断
Cesium一般使用

← 比typeof运算符更准确的类型判断 Cesium一般使用→

最近更新
01
为什么小程序特立独行
04-23
02
单页应用与前端路由库设计原理
04-23
03
代码构建与 Webpack 必备技能
04-23
更多文章>
Theme by Vdoing | Copyright © 2022-2023 花椒和邻居 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式