做了大概三个月的基于cesium地图开发的应用场景和大屏;主要想从cesium基本的入门到一些简单的场景交互做一个代码分享。
Cesium是三维地图开发的一个前端gis引擎;支持wtms、影像、模型、地形、倾斜摄影的数据加载。并通过对点线面、材质、视角等图形学知识对它进行一个真实三维场景的一个复现。
包括一些最
- 基本的创建地图、创建点位、点位聚合、数据源组、创建图层、加载gif,相机视角;
- 加载图层、绘制点、线、面,调节情景参数;
- 对接天地图、高德地图、百度地图;
- 事件:点击事件、移除事件、移除事件、拖拽事件
- 弹框:视频弹框、详情弹框、报警弹框
- 轨迹:动态轨迹、轨迹漫游
- 流线图:喷泉、流线图
- 热力图
- 场景:模拟下雪、下雨、雷达图
- 基本工具箱:放大、缩小,定位、画线
- kml、geojson文件转换和加载
- 性能优化
常用工具方法
1、基本的创建地图
viewer = new Cesium.Viewer('maps', {
animation: false, //是否创建动画小器件,左下角仪表
baseLayerPicker: false, //是否显示图层选择器
fullscreenButton: false, //是否显示全屏按钮
geocoder: false, //是否显示geocoder小器件,右上角查询按钮
homeButton: false, //是否显示Home按钮
infoBox: false, //是否显示信息框
sceneModePicker: false, //是否显示3D/2D选择器
selectionIndicator: false, //是否显示选取指示器组件
timeline: false, //是否显示时间轴
sceneMode: Cesium.SceneMode.SCENE3D, //设定3维地图的默认场景模式:Cesium.SceneMode.SCENE2D、Cesium.SceneMode.SCENE3D、Cesium.SceneMode.MORPHING
navigationHelpButton: false, //是否显示右上角的帮助按钮
scene3DOnly: true, //如果设置为true,则所有几何图形以3D模式绘制以节约GPU资源
navigationInstructionsInitiallyVisible: false,
showRenderLoopErrors: false, //是否显示渲染错误
shouldAnimate: true,//允许动画 //这个得必须有!
})
- 创建的点位:
- layer && layer.entities.add({
id: item.id,
name: item.name,
type: "marker",
featureType: type,
feature: item.feature,
lon: item.lon,
lat: item.lat,
mapTools: tools,//地图右边按钮
position: Cesium.Cartesian3.fromDegrees(parseFloat(lon), parseFloat(lat), height),
billboard: {
image: new Cesium.CallbackProperty(() => {
return _self.superGif.get_canvas().toDataURL("image/png");
}, false),
scale: 1,
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
width: 60,
height: imageheight
},
label: {
text: type == "wrj" ? `${item.name}` : "",
font: '14pt 微软雅黑',
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
// backgroundColor: Cesium.Color.YELLOW,
// showBackground: true,
outlineColor: new Cesium.Color.fromCssColorString("tranparent"),
fillColor: new Cesium.Color.fromCssColorString("#fff"),
outlineWidth: 5,
verticalOrigin: Cesium.VerticalOrigin.CENTER,
pixelOffset: new Cesium.Cartesian2(-110, -25)
},
})
点位聚合
function addPoint(Entities, featureKey, viewer,markersLayer) { // let markersLayer = new Cesium.CustomDataSource(featureKey.layer_name) for (let i = 0; i < Entities.length; i++) { let _data = Entities[i] // let _strokeColor = JSON.parse(featureKey.strokeColor); // let _fillColor = JSON.parse(featureKey.fillColor); let lon = _data.lon || _data.longitude, lat = _data.lat || _data.latitude let cartographic = Cesium.Cartographic.fromDegrees(lon, lat) let height = viewer.scene.globe.getHeight(cartographic), scale = 0.4 let image = require(`@static/biz/event/event.png`) let width = 60, imageheight = 60 if (!lon || !lat) return width = 47 imageheight = 59 switch (_data.equipmentType) { case 0: image = require(`@static/biz/type/icon-qiangji.png`) break default: image = require(`@static/biz/type/icon-ball.png`) break } markersLayer.entities.add({ name: _data.name, id: 'point_' + featureKey.layer_name + '_' + _data.id, featureData: _data, type: 'marker', position: Cesium.Cartesian3.fromDegrees(lon, lat, height), _lng: lon, _lat: lat, _obj: _data, billboard: { image: image, scale: 0.9, horizontalOrigin: Cesium.HorizontalOrigin.CENTER, verticalOrigin: Cesium.VerticalOrigin.BOTTOM, width: width, height: imageheight } }) } var dataSourcePromise = viewer.dataSources.add(markersLayer) dataSourcePromise.then(function(dataSource) { // alert(dataSource.name); var pixelRange = 105 var minimumClusterSize = 3 var enabled = featureKey.clusters_enabled if (enabled === 'false') { enabled = false } else { enabled = true } console.log(featureKey) dataSource.clustering.enabled = enabled dataSource.clustering.pixelRange = pixelRange dataSource.clustering.minimumClusterSize = minimumClusterSize var removeListener // var pinBuilder = new Cesium.PinBuilder() // var singleDigitPins = new Array(8) // for (var i = 0; i < singleDigitPins.length; ++i) { // singleDigitPins[i] = pinBuilder // .fromText('' + (i + 2), Cesium.Color.fromCssColorString(featureKey.clusters_color), 48) // .toDataURL() // } // var pinBuilder = new Cesium.PinBuilder(); // var pin200 = pinBuilder.fromText('200+', Cesium.Color.fromCssColorString(featureKey.clusters_color), 48).toDataURL(); // var pin50 = pinBuilder.fromText('50+', Cesium.Color.fromCssColorString(featureKey.clusters_color), 48).toDataURL(); // var pin40 = pinBuilder.fromText('40+', Cesium.Color.fromCssColorString(featureKey.clusters_color), 48).toDataURL(); // var pin30 = pinBuilder.fromText('30+',Cesium.Color.fromCssColorString(featureKey.clusters_color), 48).toDataURL(); // var pin20 = pinBuilder.fromText('20+', Cesium.Color.fromCssColorString(featureKey.clusters_color), 48).toDataURL(); // var pin10 = pinBuilder.fromText('10+', Cesium.Color.fromCssColorString(featureKey.clusters_color), 48).toDataURL(); function customStyle() { if (Cesium.defined(removeListener)) { removeListener() removeListener = undefined } else { removeListener = dataSource.clustering.clusterEvent.addEventListener(function(clusteredEntities, cluster) { // cluster.billboard.show = false // cluster.billboard.id = cluster.label.id // cluster.billboard.verticalOrigin = Cesium.VerticalOrigin.BOTTOM cluster.point.show= true; cluster.point.outlineColor= Cesium.Color.fromCssColorString(featureKey.clusters_color).withAlpha(0.2); cluster.point.color= Cesium.Color.fromCssColorString("#2d87f9"); cluster.point.pixelSize= 35; cluster.point.outlineWidth= 5; cluster.label.font = '16pt Source Han Sans CN' cluster.label.show = true cluster.label.color = Cesium.Color.fromCssColorString('#fff'); cluster.label.horizontalOrigin = Cesium.HorizontalOrigin.CENTER // cluster.label.verticalOrigin = Cesium.verticalOrigin.CENTER; cluster.label.pixelOffset = new Cesium.Cartesian2(0, 5) cluster.label.eyeOffset = new Cesium.Cartesian3(0, 0,-30) // cluster.point = { // show: true, // pixelSize: 30, // outlineColor: Cesium.Color.YELLOW, // outlineWidth: 10, // // scaleByDistance: new Cesium.NearFarScalar(1500, 1, 20000, 0.3), // // translucencyByDistance: new Cesium.NearFarScalar(1500, 1, 20000, 0.2), // distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 20000) // } // cluster.billboard.image = pinBuilder.fromText(clusteredEntities.length + '', Cesium.Color.fromCssColorString(featureKey.clusters_color), 48).toDataURL(); if (clusteredEntities.length >= 100) { // cluster.billboard.image = pin200; // cluster.point.color = Cesium.Color.YELLOW cluster.label.text = '100+' //文本 } else if (clusteredEntities.length >= 50) { // cluster.billboard.image = pin50; // cluster.point.color = Cesium.Color.YELLOW cluster.label.text = '50+' //文本 } else if (clusteredEntities.length >= 40) { // cluster.billboard.image = pin40; // cluster.point.color = Cesium.Color.YELLOW cluster.label.text = '40+' //文本 } else if (clusteredEntities.length >= 30) { // cluster.billboard.image = pin30; // cluster.point.color = Cesium.Color.YELLOW cluster.label.text = '30+' //文本 } else if (clusteredEntities.length >= 20) { // cluster.billboard.image = pin20; // cluster.point.color = Cesium.Color.YELLOW cluster.label.text = '20+' //文本 } else if (clusteredEntities.length >= 10) { // cluster.billboard.image = pin10; // cluster.point.color = Cesium.Color.YELLOW cluster.label.text = '10+' //文本 } else { // cluster.label.text = '3+' //文本 // lboard.image = singleDigitPins[clusteredEntities.length - 2]; } }) } // force a re-cluster with the new styling var pixelRange = dataSource.clustering.pixelRange dataSource.clustering.pixelRange = 0 dataSource.clustering.pixelRange = pixelRange } // start with custom style customStyle() }) } export function addPointFN(_Entities, _set = {}, _viewer,markersLayer) { let _featureKey = { layer_name: 'append-layer', type: '', //类型 titleKey: '', //标题 strokeWidth: 2, strokeColor: '[255, 0, 0, 255]', fillColor: '[0, 0, 255, 255]', clusters_enabled: '', //聚合显示 clusters_color: '#45deb2' //聚合颜色 } for (let k in _featureKey) { if (_set[k]) { _featureKey[k] = _set[k] } } addPoint(_Entities, _featureKey, _viewer,markersLayer) }
- 创建数据图层
- markersLayer = new Cesium.CustomDataSource('marker-layer')
- viewer.dataSources.add(markersLayer)
- 创建地图底图图层
viewer.imageryLayers.addImageryProvider(new Cesium.SingleTileImageryProvider({
url: '/static/map/worldimage.jpg'
}));
- 加载gif动态图片,需要引入SuperGif插件进行gif转换,再通过Cesium.CallbackProperty一帧帧获取,需要注意得加上dom元素
- <img src="/biz/alarm.gif" width="20px" height="20px" ref="gifRef" rel:auto_play="1" rel:rubbable="1"
style="position: absolute;z-index: -1;" />
_self.superGif = new SuperGif({
gif: this.$refs.gifRef
});
_self.superGif.load(function () {
layer && layer.entities.add({
id: item.id,
name: item.name,
type: "marker",
featureType: type,
feature: item.feature,
lon: item.lon,
lat: item.lat,
mapTools: tools,//地图右边按钮
position: Cesium.Cartesian3.fromDegrees(parseFloat(lon), parseFloat(lat), height),
billboard: {
image: new Cesium.CallbackProperty(() => {
return _self.superGif.get_canvas().toDataURL("image/png");
}, false),
scale: 1,
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
width: 60,
height: imageheight
},
label: {
text: type == "wrj" ? `${item.name}` : "",
font: '14pt 微软雅黑',
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
// backgroundColor: Cesium.Color.YELLOW,
// showBackground: true,
outlineColor: new Cesium.Color.fromCssColorString("tranparent"),
fillColor: new Cesium.Color.fromCssColorString("#fff"),
outlineWidth: 5,
verticalOrigin: Cesium.VerticalOrigin.CENTER,
pixelOffset: new Cesium.Cartesian2(-110, -25)
},
_lng: lon,
_lat: lat,
_obj: item
})
});
}
- 相机视角(有entity则用viewer,坐标用camera)
let heading = viewer.camera.heading, pitch = viewer.camera.pitch, roll = viewer.camera.roll;
viewer.flyTo(_self.pickValue, {
offset: {
heading: 2.990358455542995, // 方向
pitch: -0.5403975721607086,// 倾斜角度
range: 11100
}
//定位
let lon = list[0].lon || list[0].longitude, lat = list[0].lat || list[0].latitude;
viewer.camera.flyTo(this.mapCenter, 5000);
2、加载图层、绘制点、线、面,调节情景参数
加载图层
天地图超图方式对接
let IMG_C = viewer.imageryLayers.addImageryProvider(new Cesium.TiandituImageryProvider({
mapStyle: Cesium.TiandituMapsStyle.IMG_C,
token: 'xx'
}))
IMG_C.show = true;
// let IMG_C = viewer.imageryLayers.addImageryProvider(new Cesium.TiandituImageryProvider({
// mapStyle: Cesium.TiandituMapsStyle.TER_C,
// token: 'xx'
// }))
// IMG_C.show = true;
viewer.imageryLayers.addImageryProvider(new Cesium.TiandituImageryProvider({
mapStyle: Cesium.TiandituMapsStyle.CIA_C,//天地图全球中文注记服务(经纬度)
token: 'xxx' //由天地图官网申请的密钥
}))
- 原生对接
// 叠加影像服务
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: 22
});
viewer.imageryLayers.addImageryProvider(imgMap);
- 绘制面
ttMaplayer.entities.add({
position: Cesium.Cartesian3.fromDegrees(lon, lat, height),
ellipse: {
heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
disableDepthTestDistance: 99000000,
outlineColor: Cesium.Color.YELLOW.withAlpha(0.5),
outline: true,
outlineWidth: 2,
semiMinorAxis: 5000.0,
semiMajorAxis: 5000.0,
fill: false,
}
});
- 绘制矩形
let east = points[0].split(','),west = points[1].split(',');
layer.entities.add({
type:"marker",
name: item.name,
_obj:item,
position: Cesium.Cartesian3.fromDegrees(parseFloat((+east[0]+(+west[0]))/2), parseFloat((+west[1]+(+east[1]))/2)),
rectangle: {
coordinates: Cesium.Rectangle.fromDegrees(+east[0], +east[1],+west[0], +west[1]),
outlineColor:Cesium.Color.RED,
outlineWidth:24,
fill:true,
material: Cesium.Color.BLUE.withAlpha(0.6),
outline:true
}
})
- 绘制线段(可以设置线段宽度和材质)
_t.appendLayer.entities.add({
polyline: {
positions: new Cesium.CallbackProperty(function() {
return _t.routeList
}, false),
width: 5,
material: Cesium.Color.RED,
depthFailMaterial: Cesium.Color.RED,
clampToGround: true
}
})
- 参数调节
let Options = function () {
this.contrast = 128;
this.brightness = -0.3;
this.delta = 1;
this.gamma = 3.5;
this.enabled = false;
this.highDynamicRange = true;
this.shadows = false;
}
let option = new Options();
let gui = new dat.GUI();
gui.__closeButton.innerHTML = "收缩面板";
let bloom = viewer.scene.postProcessStages.bloom;
gui.add(option, 'highDynamicRange').name("高动态范围").onChange(function (value) {
viewer.scene.highDynamicRange = value;
})
gui.add(option, 'gamma', 0, 5).name("伽马亮度").onChange(function (value) {
viewer.scene.gamma = value;
})
gui.add(option, 'enabled').name("启用模糊").onChange(function (value) {
bloom.enabled = value;
})
gui.add(option, 'contrast', -128, 128).name("对比度").onChange(function (value) {
bloom.uniforms.contrast = value;
})
gui.add(option, 'brightness', -2, 2).name("光泽亮度").onChange(function (value) {
bloom.uniforms.brightness = value;
})
gui.add(option, 'delta', -5, 5).name("因子(delta)").onChange(function (value) {
bloom.uniforms.delta = value;
})
gui.add(option, 'shadows').name("启用阴影").onChange(function (value) {
viewer.shadows = value;
})
$('.dg.ac').css('top', '10%');
事件
鼠标左键点击事件
let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas), _self = this; let ellipsoid = viewer.scene.globe.ellipsoid; //点击地图视频标志窗口弹窗 handler.setInputAction(async e => { let lng, lat, height var cartesian = viewer.scene.pickPosition(e.position); //地图点位查询 let pick = viewer.scene.pick(e.position); if (Cesium.defined(pick) && pick.id && pick.id.type === "marker") { }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
- 鼠标移入事件
- //鼠标移入事件
handler.setInputAction(async movement => {
let lng, lat, height;
if (viewer.scene.mode !== Cesium.SceneMode.MORPHING) {
let pick = viewer.scene.pick(movement.endPosition);
if (Cesium.defined(pick) && pick.id)
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
鼠标移除事件
rectHandler && rectHandler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);
rectHandler && rectHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOWN);
rectHandler && rectHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_UP);
弹框(生成弹框和弹框移动)
生成:
dom节点
<poiDetail ref="poiRef"></poiDetail>
positionPopUp(c) {
this.tempPostion = c;
var x = c.x - 290;
var y = c.y - 250
this.boxStyle = `left:${x}px;top:${y}px`
},
destroy() {
this.options = {};
this.hide();
},
hide() {
this.getActionFlg = false;
this.visible = false;
this.showPlayer = false;
this.tempPostion = null;
}
- js方式控制dom节点
_self.$refs.poiRef.open({
position: changedC,
item: _self.pickValue,
removeHandler: () => {
_self.removeHandler()
}
})
- 移动:postRender监听位置移动改变坐标
viewer.scene.postRender.addEventListener(function () {
})
轨迹
(需要事先规划哈轨迹路线,然后再根据cesium时间滚轮进行播放)
var viewer = null,
entifyMap = {
car: {
entityFly: null,
primiayLayer: null
},
wrj: {
entityFly: null,
primiayLayer: null
}
}
import { carList, DroneList } from './routerJson.js'
var routeList = null
export default {
data() {
return {}
},
mounted() {
},
methods: {
collectPoint(position) {
var cartesian = viewer.scene.globe.pick(viewer.camera.getPickRay(position), viewer.scene)
routeList.push(cartesian) // 存储每次踩点的位置
viewer.entities.add({
polyline: {
positions: new Cesium.CallbackProperty(function() {
return routeList
}, false),
width: 5,
material: Cesium.Color.RED,
depthFailMaterial: Cesium.Color.RED,
clampToGround: true
}
})
},
defineRoute(viewerInstance, type) {
let _t = this
viewer = viewerInstance
// this.drawLine();
// return
// this.changeView();
this.type = type
this.clearRoute()
routeList = this.type=='car'?carList:DroneList;
if (entifyMap[type].entityFly) return
this.addRouterLine()
this.rollbackRoute()
this.addMouseMove()
},
addMouseMove() {
var handler = new Cesium.ScreenSpaceEventHandler(viewer.canvas)
handler.setInputAction(function(movement) {
viewer.trackedEntity = null
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
},
rollbackRoute() {
var start = Cesium.JulianDate.fromDate(new Date(), new Cesium.JulianDate()) // 开始时间
var stop = Cesium.JulianDate.addSeconds(start, 100, new Cesium.JulianDate()) // 结束时间
viewer.clock.startTime = start.clone()
viewer.clock.stopTime = stop.clone()
viewer.clock.currentTime = start.clone()
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;
viewer.clock.multiplier = 1
// viewer.timeline.zoomTo(start, stop)
function computeCircularTrack() {
var property = new Cesium.SampledPositionProperty()
for (var i = 0; i < routeList.length; i++) {
var time = Cesium.JulianDate.addSeconds(start, (i * 100) / (routeList.length - 1), new Cesium.JulianDate())
var position = routeList[i]
property.addSample(time, position)
}
return property
}
var position = computeCircularTrack()
entifyMap[this.type].entityFly = viewer.entities.add({
availability: new Cesium.TimeIntervalCollection([
new Cesium.TimeInterval({
start: start,
stop: stop
})
]),
position: position,
orientation: new Cesium.VelocityOrientationProperty(position),
// model: {
// uri: this.type == 'car' ? '/biz/car.gltf' : '/biz/Drone.gltf', // 加载模型
// minimumPixelSize: 64 // 指定模型大小
// },
billboard: {
image: this.type == 'car' ? '/biz/type/ydxlc.png' : '/biz/type/wrj.png',
scale: 1,
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
width: 47,
height: 59
},
path: {
show: false, // 显示轨迹
resolution: 1,
material: new Cesium.PolylineOutlineMaterialProperty({
color: Cesium.Color.fromAlpha(Cesium.Color.LIGHTSKYBLUE, 0.5),
outlineWidth: 1,
outlineColor: Cesium.Color.red
}),
width: 5
}
})
// 指定轨迹插值算法
entifyMap[this.type].entityFly.position.setInterpolationOptions({
interpolationDegree: 1,
interpolationAlgorithm: Cesium.LinearApproximation
})
viewer.trackedEntity = entifyMap[this.type].entityFly
},
track() {
var center = entityFly.position.getValue(viewer.clock.currentTime)
var orientation = entityFly.orientation.getValue(viewer.clock.currentTime)
var transform = Cesium.Transforms.eastNorthUpToFixedFrame(center)
transform = Cesium.Matrix4.fromRotationTranslation(Cesium.Matrix3.fromQuaternion(orientation), center)
viewer.camera.lookAtTransform(transform, new Cesium.Cartesian3(-100.0, 0, 50))
},
//切换视角
changeView(flag) {
if (flag) {
viewer.clock.onTick.removeEventListener(this.track)
viewer.trackedEntity = entityFly
} else {
viewer.clock.onTick.addEventListener(this.track)
viewer.trackedEntity = null
}
},
//清除路线
clearRoute(typ) {
var type = typ || this.type,entityFly = entifyMap[type].entityFly,primiayLayer = entifyMap[type].primiayLayer
entityFly && viewer.entities.remove(entityFly)
primiayLayer && viewer.scene.primitives.remove(primiayLayer)
entifyMap[type].entityFly = null
entifyMap[type].primiayLayer = null
// this.changeView();
},
//添加轨迹
addRouterLine() {
var instance = new Cesium.GeometryInstance({
geometry: new Cesium.GroundPolylineGeometry({
width: 5,
positions: routeList
}),
attributes: {}
})
const materialOpts = {
fabric: {
type: 'PolylineDash',
uniforms: {
color: {
red: 1,
green: 1,
blue: 0,
alpha: 1
},
gapColor: {
red: 1,
green: 1,
blue: 1,
alpha: 1
},
dashLength: 50
}
}
}
entifyMap[this.type].primiayLayer = new Cesium.GroundPolylinePrimitive({
asynchronous: false,
geometryInstances: instance,
appearance: new Cesium.PolylineMaterialAppearance({
material: new Cesium.Material(materialOpts)
})
})
viewer.scene.primitives.add(entifyMap[this.type].primiayLayer)
},
//绘制轨迹线
drawLine() {
let _t = this
viewer.screenSpaceEventHandler.setInputAction(function(clickEvent) {
_t.collectPoint(clickEvent.position)
}, Cesium.ScreenSpaceEventType.LEFT_CLICK)
viewer.screenSpaceEventHandler.setInputAction(function(moveEvent) {
if (routeList.length >= 2) {
routeList.pop()
_t.collectPoint(moveEvent.endPosition)
} else if (routeList.length == 1) {
_t.collectPoint(moveEvent.endPosition)
}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
viewer.screenSpaceEventHandler.setInputAction(function(clickEvent) {
routeList.pop()
_t.collectPoint(clickEvent.position)
viewer.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
viewer.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE)
viewer.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK)
}, Cesium.ScreenSpaceEventType.RIGHT_CLICK)
}
}
}
### 流线图
主要是定义材质和数学抛物线位置计算
/**
* 飞机纹理流动图
*
* @author zhangti
* @version v1
*
*/
var cesiumFlyPath = null
var originHeight = 0
export const CesiumFlyPath = function() {
cesiumFlyPath = this
this._PolylineTrailLinkMaterialProperty = null
}
CesiumFlyPath.prototype.init = function(param) {
if (null === param || undefined === param) return
var t = this
for (var key in param) {
t[key] = param[key]
}
this.config()
}
CesiumFlyPath.prototype.config = function() {
var cesiumFlyPath = this
//绘制位置在地形上
cesiumFlyPath.viewer.scene.globe.depthTestAgainstTerrain = false
//取消双击事件
cesiumFlyPath.viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(
Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
)
//定义流动纹理对象
Cesium.PolylineTrailLinkMaterialProperty = PolylineTrailLinkMaterialProperty
Cesium.Material.PolylineTrailLinkType = 'PolylineTrailLink'
Cesium.Material.PolylineTrailLinkImage = '/biz/fly.png'
//着色器
Cesium.Material.PolylineTrailLinkSource =
'czm_material czm_getMaterial(czm_materialInput materialInput)\n\
{\n\
czm_material material = czm_getDefaultMaterial(materialInput);\n\
vec2 st = materialInput.st;\n\
vec4 colorImage = texture2D(image, vec2(fract(st.s - time), st.t));\n\
material.alpha = colorImage.a * color.a;\n\
material.diffuse = (colorImage.rgb+color.rgb)/2.0;\n\
return material;\n\
}'
//实例化流动纹理
cesiumFlyPath._PolylineTrailLinkMaterialProperty = new Cesium.PolylineTrailLinkMaterialProperty(
cesiumFlyPath.color,
cesiumFlyPath.duration
)
Cesium.Material._materialCache.addMaterial(Cesium.Material.PolylineTrailLinkType, {
fabric: {
type: Cesium.Material.PolylineTrailLinkType,
uniforms: {
color: new Cesium.Color(1.0, 0.0, 0.0, 0.5),
image: Cesium.Material.PolylineTrailLinkImage,
time: 0
},
source: Cesium.Material.PolylineTrailLinkSource
},
translucent: function(material) {
return true
}
})
}
CesiumFlyPath.prototype.parabolaEquation = function(options, resultOut) {
var _cesiumFlyPath = this
//方程 y=-(4h/L^2)*x^2+h h:顶点高度 L:横纵间距较大者
var h = options.height && options.height > 5000 ? options.height : 5000
var L =
Math.abs(options.pt1.lon - options.pt2.lon) > Math.abs(options.pt1.lat - options.pt2.lat)
? Math.abs(options.pt1.lon - options.pt2.lon)
: Math.abs(options.pt1.lat - options.pt2.lat)
var num = options.num && options.num > 50 ? options.num : 50
var result = []
var dlt = L / num
if (Math.abs(options.pt1.lon - options.pt2.lon) > Math.abs(options.pt1.lat - options.pt2.lat)) {
//以lon为基准
var delLat = (options.pt2.lat - options.pt1.lat) / num
if (options.pt1.lon - options.pt2.lon > 0) {
dlt = -dlt
}
for (var i = 0; i < num; i++) {
var tempH = h - (Math.pow(-0.5 * L + Math.abs(dlt) * i, 2) * 4 * h) / Math.pow(L, 2)
var lon = options.pt1.lon + dlt * i
var lat = options.pt1.lat + delLat * i
result.push([lon, lat, tempH + originHeight + 1000])
}
} else {
//以lat为基准
var delLon = (options.pt2.lon - options.pt1.lon) / num
if (options.pt1.lat - options.pt2.lat > 0) {
dlt = -dlt
}
for (var i = 0; i < num; i++) {
var tempH = h - (Math.pow(-0.5 * L + Math.abs(dlt) * i, 2) * 4 * h) / Math.pow(L, 2)
var lon = options.pt1.lon + delLon * i
var lat = options.pt1.lat + dlt * i
result.push([lon, lat, tempH + originHeight + 1000])
}
}
// let cartographic = Cesium.Cartographic.fromDegrees(options.pt2.lon, options.pt2.lat);
// let distHeight = _cesiumFlyPath.viewer.scene.globe.getHeight(cartographic)
result.push([options.pt2.lon, options.pt2.lat, 1000])
if (resultOut != undefined) {
resultOut = result
}
return result
}
//默认
CesiumFlyPath.prototype.drawDefault = function(data) {
var _cesiumFlyPath = this,
center = data.center,
// lon = center.lon,
// lat = center.lat,
// zoom = data.zoom,
cities = data.cities
// v = data.v
//设置homebutton的位置
// Cesium.Camera.DEFAULT_VIEW_RECTANGLE = Cesium.Rectangle.fromDegrees(lon - 1, lat - 1, lon + 1, lat + 1)
//设置初始位置
// _cesiumFlyPath.viewer.camera.setView({
// destination: Cesium.Cartesian3.fromDegrees(lon, lat, zoom)
// })
//生成流动纹理
let cartographic = Cesium.Cartographic.fromDegrees(center.lon, center.lat)
originHeight = _cesiumFlyPath.viewer.scene.globe.getHeight(cartographic)
for (var j = 0; j < cities.length; j++) {
var points = cesiumFlyPath.parabolaEquation({
pt1: center,
pt2: cities[j],
height: _cesiumFlyPath.height,
num: cities.length
})
var pointArr = []
for (var i = 0; i < points.length; i++) {
pointArr.push(points[i][0], points[i][1], points[i][2])
}
_cesiumFlyPath.viewer.entities.add({
name: 'PolylineTrailLink' + j,
polyline: {
positions: Cesium.Cartesian3.fromDegreesArrayHeights(pointArr),
width: 2,
//流动纹理
material: cesiumFlyPath._PolylineTrailLinkMaterialProperty
}
})
}
// //原点
// let cartographic = Cesium.Cartographic.fromDegrees(lon, lat);
// let height = _cesiumFlyPath.viewer.scene.globe.getHeight(cartographic);
// _cesiumFlyPath.viewer.entities.add({
// position: Cesium.Cartesian3.fromDegrees(lon, lat, height),
// point: {
// pixelSize: 1,
// color: v.c
// }
// })
//目标点
// for (var i = 0; i < cities.length; i++) {
// let cartographic = Cesium.Cartographic.fromDegrees(cities[i].lon, cities[i].lat);
// let height = _cesiumFlyPath.viewer.scene.globe.getHeight(cartographic);
// _cesiumFlyPath.viewer.entities.add({
// position: Cesium.Cartesian3.fromDegrees(cities[i].lon, cities[i].lat, height),
// billboard: {
// image: !this.showDestPic?"/biz/type/point.png":"",
// scale: 0.5,
// horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
// verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
// width: 47,
// height: 59
// },
// // point: {
// // pixelSize: 1,
// // color: v.c2
// // }
// })
// }
}
CesiumFlyPath.prototype.build = function(param) {
var t = this
switch (param.handleType) {
case 'default': {
t.drawDefault(param)
break
}
}
}
CesiumFlyPath.prototype.clear = function() {
try {
this.viewer && this.viewer.entities && this.viewer.entities.removeAll()
} catch (error) {}
}
/*
流纹纹理线
color 颜色
duration 持续时间 毫秒
*/
var PolylineTrailLinkMaterialProperty = null
PolylineTrailLinkMaterialProperty = function(color, duration) {
this._definitionChanged = new Cesium.Event()
this._color = undefined
this._colorSubscription = undefined
this.color = color
this.duration = duration
this._time = new Date().getTime()
}
//在cesium中 定义 PolylineTrailLinkMaterialProperty
Cesium.defineProperties(PolylineTrailLinkMaterialProperty.prototype, {
isConstant: {
get: function() {
return false
}
},
definitionChanged: {
get: function() {
return this._definitionChanged
}
},
color: Cesium.createPropertyDescriptor('color')
})
PolylineTrailLinkMaterialProperty.prototype.getType = function(time) {
return 'PolylineTrailLink'
}
PolylineTrailLinkMaterialProperty.prototype.getValue = function(time, result) {
if (!Cesium.defined(result)) {
result = {}
}
result.color = Cesium.Property.getValueOrClonedDefault(this._color, time, Cesium.Color.WHITE, result.color)
result.image = Cesium.Material.PolylineTrailLinkImage
result.time = ((new Date().getTime() - this._time) % this.duration) / this.duration
return result
}
PolylineTrailLinkMaterialProperty.prototype.equals = function(other) {
return (
this === other || (other instanceof PolylineTrailLinkMaterialProperty && Property.equals(this._color, other._color))
)
}
下雪
export default class Snow{
constructor(v){
this.collection = v.scene.postProcessStages;
this._snow = new Cesium.PostProcessStage({
name: 'czm_snow',
fragmentShader: this.getFS()
});
this.collection.add(this._snow);
v.scene.skyAtmosphere.hueShift = -0.8;
v.scene.skyAtmosphere.saturationShift = -0.7;
v.scene.skyAtmosphere.brightnessShift = -0.33;
v.scene.fog.density = 0.001;
v.scene.fog.minimumBrightness = 0.8;
}
getFS(){
return "uniform sampler2D colorTexture;\n\
varying vec2 v_textureCoordinates;\n\
\n\
float snow(vec2 uv,float scale)\n\
{\n\
float time = czm_frameNumber / 60.0;\n\
float w=smoothstep(1.,0.,-uv.y*(scale/10.));if(w<.1)return 0.;\n\
uv+=time/scale;uv.y+=time*2./scale;uv.x+=sin(uv.y+time*.5)/scale;\n\
uv*=scale;vec2 s=floor(uv),f=fract(uv),p;float k=3.,d;\n\
p=.5+.35*sin(11.*fract(sin((s+p+scale)*mat2(7,3,6,5))*5.))-f;d=length(p);k=min(d,k);\n\
k=smoothstep(0.,k,sin(f.x+f.y)*0.01);\n\
return k*w;\n\
}\n\
\n\
void main(void){\n\
vec2 resolution = czm_viewport.zw;\n\
vec2 uv=(gl_FragCoord.xy*2.-resolution.xy)/min(resolution.x,resolution.y);\n\
vec3 finalColor=vec3(0);\n\
float c = 0.0;\n\
c+=snow(uv,30.)*.0;\n\
c+=snow(uv,20.)*.0;\n\
c+=snow(uv,15.)*.0;\n\
c+=snow(uv,10.);\n\
c+=snow(uv,8.);\n\
c+=snow(uv,6.);\n\
c+=snow(uv,5.);\n\
finalColor=(vec3(c)); \n\
gl_FragColor = mix(texture2D(colorTexture, v_textureCoordinates), vec4(finalColor,1), 0.5); \n\
\n\
}\n\
";
}
remove(){
this._snow.destroy();
}
}
基本工具箱:放大、缩小,定位、画线、全屏
resetMap() {
let { x, y, z } = window.globalConfig.map.center;
this.mapCenter = {
destination: {
x: x,
y: y,
z: z,
},
};
this.viewer.camera.flyTo(this.mapCenter, 5000);
},
zoomIn() {
var viewer = this.viewer;
let cameraPos = viewer.camera.position;
// 获取当前坐标系标准
let ellipsoid = viewer.scene.globe.ellipsoid;
// 根据坐标系标准,将笛卡尔坐标转换为地理坐标
let cartographic = ellipsoid.cartesianToCartographic(cameraPos);
// 获取镜头的高度
let height = cartographic.height;
viewer.camera.zoomIn(height / 3);
},
zoomOut() {
var viewer = this.viewer;
let cameraPos = viewer.camera.position;
// 获取当前坐标系标准
let ellipsoid = viewer.scene.globe.ellipsoid;
// 根据坐标系标准,将笛卡尔坐标转换为地理坐标
let cartographic = ellipsoid.cartesianToCartographic(cameraPos);
// 获取镜头的高度
let height = cartographic.height;
viewer.camera.zoomOut(height * 1.2);
},
screenSet() {
this.screen = !this.screen;
if (this.screen) {
Cesium.Fullscreen.requestFullscreen(document.getElementById("maps"))
} else {
Cesium.Fullscreen.exitFullscreen()
}
},
#### 相关链接:
bigMap kml和geojson转换
在线图层处理
常用的地图json下载和svg下载
[Ceisum文档比官网快](http://cesium.xin/cesium/cn/Documentation1.62/Viewer.html?classFilter=viewer)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。