今天,我们来讨论一下 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
//
绘制 图标,绘制线条
- 绘制标牌
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 是我们常常修改值的字段
- 通过 primitive 绘制 circle
/**
-
DrawPolygonOutline 不规则区域边线,可以修改边线
-
DrawPolygonOutlineManager 不规则区域 manager
-
使用方法
-
- 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