cesium 点滴探讨记录

251 阅读3分钟

今天,我们来讨论一下 cesium。

总所周知,cesium.js 这个插件是用 javascript 编写的脚本,运行在 canvas 上,于是之前老版本,不支持 canvas 的浏览器,就可以舍弃了;其二,cesium 是一款 集成了 2D, 2.5D, 3D 的地球可视化引擎,可以在此自定义各种可视化的 svg,image,glb,gilt 等可视图形,也可以通过glsl,绘制我们需要的一些区域,例如模拟 雨雪风雾 ,洋流,水流 等等。于是我们也称做此工作的为 webgis

加载 viewer:

yarn add global @vue/cli

vue create x-project (注: 我这里采用 vue2.6.*)

cd x-project

yarn add cesium

app.js


import * as Cesium from 'cesium'

export default {

...

mounted () {

new Cesium.Viewer('cesiumId', {

selectionIndicator: false,

// sceneMode: Cesium.SceneMode.SCENE2D,

shouldAnimate: true,

requestRenderMode: true,

})

}

}

注: 这里采用天地图,密码自己申请,免费的

viewer.imageryLayers.removeAll();

viewer.imageryLayers.addImageryProvider(

new Cesium.WebMapTileServiceImageryProvider({

url: "t0.tianditu.com/img_w/wmts?…",

layer: "tdtBasicLayer",

style: "default",

format: "image/jpeg",

tileMatrixSetID: "GoogleMapsCompatible",

show: false

})

)

npm run serve

诶:这里可能有报错:类似于


Visit http://get.webgl.org to verify that your web browser and hardware support WebGL...

这个错误是没有在 vue.config.js 中增加配置


new CopyWebpackPlugin([{ from: path.join(cesiumSource, 'Workers'), to: 'Workers' }]),

new CopyWebpackPlugin([{ from: path.join(cesiumSource, 'Assets'), to: 'Assets' }]),

new CopyWebpackPlugin([{ from: path.join(cesiumSource, 'ThirdParty'), to: 'ThirdParty' }]),

new CopyWebpackPlugin([{ from: path.join(cesiumSource, 'Widgets'), to: 'Widgets' }]),

new webpack.DefinePlugin({

CESIUM_BASE_URL: JSON.stringify('')

})

开始初始化地球:

// 设置为球的基础颜色

viewer.scene.globe.translucency.backFaceAlpha = 1

viewer.scene.globe.translucency.enabled = true

viewer.scene.globe.translucency.frontFaceAlpha = 1

viewer.scene.skyAtmosphere.show = true

// 初始化去掉 商标水印,下标说明

viewer.cesiumWidget.creditContainer.style.display = 'none'

// 添加图层

let imageryLayers = viewer.imageryLayers

imageryLayers.removeAll();

console.log(1, imageryLayers)

const backMarble = imageryLayers.addImageryProvider(

new Cesium.WebMapTileServiceImageryProvider({

url: "t0.tianditu.com/img_w/wmts?…",

layer: "tdtBasicLayer",

style: "default",

format: "image/jpeg",

tileMatrixSetID: "GoogleMapsCompatible",

show: false

}), 1

)

backMarble.alpha = 1

backMarble.brightness = 1.0

// 将三维球定位到中国

// viewer.camera.flyTo({

// destination: Cesium.Cartesian3.fromDegrees(103.84, 31.15, 17850000),

// orientation: {

// heading : Cesium.Math.toRadians(348.4202942851978),

// pitch : Cesium.Math.toRadians(-89.74026687972041),

// roll : Cesium.Math.toRadians(0)

// },

// complete:function callback() {

// // 定位完成之后的回调函数

// }

// });

// 初始化设置区域

viewer.camera.setView({

destination: Cesium.Rectangle.fromDegrees(70, 20, 123, 60)

})

// 由于线锯齿明显,我们开启抗锯齿

if (Cesium.FeatureDetection.supportsImageRenderingPixelated) {

viewer.resolutionScale = window.devicePixelRatio

}

viewer.scene.postProcessStages.fxaa.enabled = true

\

// sky 盒子,

viewer.scene.skyBox = new Cesium.SkyBox({

sources : {

positiveX : '/asset/skybox/01.jpg',

negativeX : '/asset/skybox/01.jpg',

positiveY : '/asset/skybox/01.jpg',

negativeY : '/asset/skybox/01.jpg',

positiveZ : '/asset/skybox/01.jpg',

negativeZ : '/asset/skybox/01.jpg'

}

});

// 光照

viewer.scene.globe.enableLighting = true

viewer.shadows = true

//

绘制 图标,绘制线条

  1. 绘制标牌

billboardCollection = new Cesium.BillboardCollection();

window.viewer.scene.primitives.add(billboardCollection)

billboardCollection.add({

// 获取或设置世界空间中的对齐轴。对齐的轴是广告牌向上向量指向的单位向量

// 默认值为0

slignedAxis: Cesium.Cartesian3.ZERO,

// 获取 或 设置 与 广告纹理相乘的颜色。这有两个常见的用例

// 颜色 与 透明度,

// 我们一般采用 Cesium.Color.fromCssColorString()

// 透明度,单独的我们采用 withAlpha

color: color,

// 默认是不进行深度测试的,除非有特殊设定

disbaleDepthTestDistance: args.disbaleDepthTestDistance || Cesium.Number.POSITIVE_INFINITY,

// 获取或设置条件,该条件指定将在距摄像机的距离显示此广告牌

distanceDisplayCondition: args.disbaleDepthTestDistance,

// eyeOffset: args.eyeOffset,

// 获取或设置广告牌的宽度、高度。如果未定义,将使用图像高度

width: args.width,

height: args.height,

// 获取或设置此广告牌的高度参考

heightReference: Cesium.HeightReference.NONE,

// 获取或设置此广告牌的水平原点,确定该广告牌是否为在其锚定位置的左侧,中心或右侧。

// horizontalOrigin: ,

// verticalOrigin: ,

// 获取或设置广告牌时返回的用户定义对象 => Object

id: args.id,

image: args.image,

pixelOffset: args.pixelOffset,

pixelOffsetScaleByDistance: args.pixelOffsetScaleByDistance,

// 这里 弧度我们一般采用 Cesium.Cartesian3.fromRadians()

// 经纬度 我们一般采用 Cesium.Cartesian3.fromDegrees()

position: Cesium.Cartesian3.fromDegrees(args.llops[0], args.llops[1]),

rotation: args.rotation || 0,

scale: args.scale || 1,

show: args.show === undefined ? true : args.show

})

一般,这里 image, position,show,rotation 是我们常常修改值的字段

  1. 通过 primitive 绘制 circle

/**

  • DrawPolygonOutline 不规则区域边线,可以修改边线

  • DrawPolygonOutlineManager 不规则区域 manager

  • 使用方法

    1. new DrawPolygonOutlineManager({ instances: [ { pos: [ ...circlePoints([93, 34], 50000).flat() ], color: '#f00' } ] })
  • let circle = new DrawPolygonOutlineManager()

  • circle.init({ instances: [{ pos: [ ...circlePoints([114, 34], 50000).flat() ] }], id: 'polygon_1' })

  • circle.updateInstances([{ pos: [ ...circlePoints([94, 34], 50000).flat() ], color: '#ff0' }], 'polygon_1')

    • */

// import { uuid } from './utils'

import * as Cesium from 'cesium'

class DrawPolygonOutlineManager {

constructor (options) {

this.primitivesPolylineCollection = null

this.init(options)

}

// 初始化,并加载

init (options) {

if (!this.primitivesPolylineCollection) {

this.primitivesPolylineCollection = new Cesium.PrimitiveCollection()

window.viewer.scene.primitives.add(this.primitivesPolylineCollection)

}

if (options) {

this.add(options, 0)

}

}

// 修改图元

updateInstances (instances, id) {

if (!index && !instances) return

let primitive = this.getById(id)

if (primitive) {

primitive.instances = instances

}

}

// 通过 ID 获取 union

getById (id) {

for (let i = 0; i < this.primitivesPolylineCollection.length; i++) {

let item = this.primitivesPolylineCollection.get(i)

console.log('this.primitivesPolylineCollection: getById: ', item)

if (item.id === id) {

return item

}

}

}

// 添加 union

add (options, index) {

if (!index && index !== 0) index = this.primitivesPolylineCollection.length

this.primitivesPolylineCollection.add(new DrawPolygonOutline(options), index)

}

// 全部移除

removeAll () {

this.primitivesPolylineCollection.removeAll()

this.primitivesPolylineCollection = null

}

// 移除指定 union

remove (id) {

let primitive = this.getById(id)

if (primitive) {

this.primitivesPolylineCollection.remove(primitive)

}

}

}

class DrawPolygonOutline {

constructor (options) {

this.instances = options.instances

this.color = '#fff'

this.alpha = 1

this.width = options.width || 1.5

this.id = options.id

}

getGeotryInstance (arr) {

let instances = []

for (let item of arr) {

instances.push(new Cesium.GeometryInstance({

geometry: new Cesium.GroundPolylineGeometry({

positions: Cesium.Cartesian3.fromDegreesArray([...item.pos]),

loop: true,

width: this.width

}),

attributes: {

color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.fromCssColorString(item.color || this.color).withAlpha(item.alpha || this.alpha))

},

}))

}

return instances

}

getPrimitive () {

return new Cesium.GroundPolylinePrimitive({

geometryInstances: this.getGeotryInstance(this.instances),

releaseGeometryInstances: false,

allowPicking: false,

appearance: new Cesium.PolylineColorAppearance()

})

}

update (context, frameState, commandList) {

if (JSON.stringify(this._instances) !== JSON.stringify(this.instances)) {

this._instances = this.instances;

this._primitive = this._primitive && this._primitive.destroy()

this._primitive = this.getPrimitive()

if (!this._primitive) return

}

this._primitive.update(context, frameState, commandList)

}

}

export default DrawPolygonOutlineManager