gisthreemap
Version:
基于webGL的三维api
1,797 lines • 60.9 kB
JavaScript
// import * as Cesium from 'cesium'
// import 'cesium/Widgets/widgets.css'
import CustomTilingScheme from './SubClass/CustomTilingScheme'
import MapEvent from './SubClass/MapEvent'
import Popup from './SubClass/Popup'
import Entitys from './SubClass/Entitys'
import EntitysEffect from './SubClass/EntitysEffect'
import CustomMaterial from './extendMaterial/CustomMaterial'
import CircleDiffusion from './SubClass/CircleDiffusion'
import HexagonSpread from './SubClass/HexagonSpread'
import Scanline from './SubClass/Scanline'
import CircleScan from './SubClass/CircleScan'
import Measure from './SubClass/Measure'
import draw from './SubClass/draw'
import DrawDynamicTool from './SubClass/DrawDynamicTool'
import Mentitys from './SubClass/Mentitys'
import commonTools from './SubClass/CommonTools'
import Handler from './SubClass/Handler'
import MouseManager from './SubClass/MouseManager'
import EntityFactory from './SubClass/EntityFactory'
import TrackedAnimate from './SubClass/TrackedAnimate'
import Criska_Plugin from './SubClass/Criska_Plugin'
//导入mars3d主库
import "mars3d/dist/mars3d.css";
import "../assets/css/camera.css";
import "../assets/css/divGraphic.css";
import * as mars3d from "mars3d";
//导入mars3d插件(按需使用,需要先npm install)
// import "mars3d-space";
// import XbsjEarth from 'XbsjEarth/dist/XbsjEarth/XbsjEarth.js'
// import MVTImageryProvider from 'mvt-imagery-provider';
import mapboxstyle from "./mapVecstyles/mapboxstyle";
// 引入 turf
import * as turf from "@turf/turf";
// 引入 axios
import axios from 'axios'
class Criska_Cesium {
constructor(options) {
this.options = options
this.Events = [] //存储地图点击事件,绘制时,清空存储事件
this.pointEntitiesLine = [] // 存放高度线的数组
this.mars3d = mars3d
this.mgraphicLayer = new mars3d.layer.GraphicLayer({ id: 'simplelayer' })
this.heatMap = null
}
init(callback) {
// 配置 cesium token
Cesium.Ion.defaultAccessToken = this.options.CesiumToken
const defaultOptions = {
selectionIndicator: false, // 去掉点击的选中框
baseLayerPicker: false, // 如果设置为false,将不会创建右上角图层按钮。
imageryProvider: false, //必须为false
geocoder: false, // 如果设置为false,将不会创建右上角查询(放大镜)按钮。
navigationHelpButton: false, // 如果设置为false,则不会创建右上角帮助(问号)按钮。
homeButton: false, // 如果设置为false,将不会创建右上角主页(房子)按钮。
sceneModePicker: false, // 如果设置为false,将不会创建右上角投影方式控件(显示二三维切换按钮)。
animation: false, // 如果设置为false,将不会创建左下角动画小部件。
timeline: false, // 如果设置为false,则不会创建正下方时间轴小部件。
fullscreenButton: false, // 如果设置为false,将不会创建右下角全屏按钮。
scene3DOnly: true, // 为 true 时,每个几何实例将仅以3D渲染以节省GPU内存。
shouldAnimate: true, // 默认true ,否则为 false 。此选项优先于设置 Viewer#clockViewModel 。
// ps. Viewer#clockViewModel 是用于控制当前时间的时钟视图模型。我们这里用不到时钟,就把shouldAnimate设为false
infoBox: false, // 是否显示点击要素之后显示的信息
sceneMode: 3, // 初始场景模式 1 2D模式 2 2D循环模式 3 3D模式 Cesium.SceneMode
requestRenderMode: false, // 启用请求渲染模式,不需要渲染,节约资源吧
fullscreenElement: document.body, // 全屏时渲染的HTML元素 暂时没发现用处,虽然我关闭了全屏按钮,但是键盘按F11 浏览器也还是会进入全屏
contextOptions: {
requestWebgl2: true,
msaa: true,
multisampleNum: 8,
}
}
const initOptions = this.options.initOptions || defaultOptions
this.ThreeViewer = new Cesium.Viewer(this.options.el, initOptions)
const canvas = document.querySelector('.cesium-widget canvas')
let ctx = canvas.getContext("2d");
console.log(ctx,'ctx')
//this.earth = new XE.Earth(this.options.el);
//this.ThreeViewer = this.earth.czm.viewer;
this.marsmap = new mars3d.Map(this.ThreeViewer, {
control: {
contextmenu: { hasDefault: true } // 右键菜单
}
})
// 挂载3D热力图
this.heatMap = new HeatMap3D(this.ThreeViewer);
let dom1 = document.querySelector('#Threemapview .mars3d-contextmenu')
dom1.remove();
let dom2 = document.querySelector('#Threemapview .mars3d-smallTooltip')
dom2.remove();
this.marsmap.addLayer(this.mgraphicLayer)
const NODE_ENV = process.env.NODE_ENV;
console.log(NODE_ENV);
// 开发环境
if (NODE_ENV === 'development') {
// console.clear()
// 清除版权信息
// let clearIntervalTime = setInterval(() => {
// console.clear()
// }, 100)
// let clearSetTime = setTimeout(() => {
// clearInterval(clearIntervalTime)
// clearTimeout(clearSetTime)
// }, 10000)
// window.requestAnimationFrame(animationVersion);
} else {
// 清除版权信息
window.requestAnimationFrame(animationVersion);
}
// 回调
if (callback) {
callback(this.ThreeViewer)
}
// this.marsmap.unbindContextMenu()
// this.earth.sceneTree.root = {
// "title": "当前场景",
// "isSelected": true,
// "children": [
// ]
// };
// 隐藏版权
this.ThreeViewer._cesiumWidget._creditContainer.style.display = 'none'
this.ThreeViewer.scene.light = new Cesium.DirectionalLight({ //去除时间原因影响模型颜色
direction: new Cesium.Cartesian3(0.35492591601301104, -0.8909182691839401, -0.2833588392420772)
})
const criskapl = Criska_Plugin()
// 挂载第三方插件
this.criskaplugin = new criskapl(this.ThreeViewer)
// console.log(mapboxgl, 'mapboxgl')
// let terrainProvider = new Cesium.CesiumTerrainProvider({
// url : Cesium.IonResource.fromAssetId(3956),
// requestWaterMask: true, // 请求水体效果所需要的海岸线数据
// requestVertexNormals: true, // 请求地形照明数据
// });
// this.ThreeViewer.terrainProvider = terrainProvider;
// 打开抗锯齿
this.ThreeViewer.scene.fxaa = true
this.ThreeViewer.scene.postProcessStages.fxaa.enabled = true;
// 自动调整分辨率
this.adjustmentPixel()
// Primitive 管理
this.Primitivemanager = new Cesium.PrimitiveCollection();
this.Primitivemanager.destroyPrimitives = false;
this.ThreeViewer.scene.primitives.add(this.Primitivemanager);
// let supportsImageRenderingPixelated = this.ThreeViewer.cesiumWidget._supportsImageRenderingPixelated;
// if (supportsImageRenderingPixelated) {
// let vtxf_dpr = window.devicePixelRatio;
// while (vtxf_dpr >= 2.0) { vtxf_dpr /= 2.0; }
// this.ThreeViewer.resolutionScale = vtxf_dpr;
// }
// 隐藏默认切片
// imageryLayers.get(0).show = false;
// 时间设置,调整光照
let utc = Cesium.JulianDate.fromDate(new Date(this.options.currentTime)) // UTC
this.ThreeViewer.clock.currentTime = Cesium.JulianDate.addHours(utc, 8, new Cesium.JulianDate()) // 北京时间=UTC+8=GMT+8
// 点击事件监听
// 获取BoundingSphere
this.originboundingSphere = this.getBoundingSphere({
r: this.options.mapOption.radius,
...this.options.mapOption.center
})
const { x: originx, y: originy, z: originz } = this.options.mapOption.center
const { heading, pitch, roll, radius } = this.options.mapOption
// camera视野的默认偏转角度
// let heading = Cesium.Math.toRadians(360.0)
// let pitch = Cesium.Math.toRadians(-45.0)
// // 镜头距点位距离
// let range = 500
// 创建中心点
this.centerEntity = new Cesium.Entity({
eid: 'centerpoint',
position: Cesium.Cartesian3.fromDegrees(originx, originy),
point: {
pixelSize: 0,
color: Cesium.Color.WHITE.withAlpha(0),
outlineColor: Cesium.Color.WHITE.withAlpha(0),
outlineWidth: 0
}
});
this.ThreeViewer.entities.add(this.centerEntity);
// 加载底图
this.initBaseLayers(this.options.baseLayer.Cesium)
// 加载arcgis管线
// this.ThreeViewer.imageryLayers.addImageryProvider(
// new Cesium.ArcGisMapServerImageryProvider({
// url : 'http://192.168.88.205:6080/arcgis/rest/services/jy/JYGS_pipe_BS/MapServer'
// })
// )
// 加载设备
this.initBaseEquments(this.options.EqumentPoints)
// 是否光照
this.sunshine(this.options.senceOption.sunshine)
// 是否自传
if (this.options.senceOption.autoRotation) {
// 自转动
this.autoRotation(() => {
if (this.options.Tile3DModels.length > 0) {
// 遍历Tile3DModels,看是否有飞向模型,没有的话,飞向自定的范围
let models = this.options.Tile3DModels.filter(item => item.gotomodel)
if (!models.length) {
this.CommonflyTo(this.centerEntity, { offset: new Cesium.HeadingPitchRange(heading, pitch, originz), duration: 5 })
}
setTimeout(() => {
this.initBaseModels(this.options.Tile3DModels)
// 加载水系
this.initWaterLayers(this.options.waterpolygons)
// 加载管线
this.initBaseLayers(this.options.featureLayers)
}, 5100)
} else {
this.CommonflyTo(this.centerEntity, { offset: new Cesium.HeadingPitchRange(heading, pitch, originz), duration: 5 })
setTimeout(() => {
// 加载水系
this.initWaterLayers(this.options.waterpolygons)
// 加载管线
this.initBaseLayers(this.options.featureLayers)
}, 5200)
}
})
} else {
if (this.options.Tile3DModels.length > 0) {
this.initBaseModels(this.options.Tile3DModels)
// 遍历Tile3DModels,看是否有飞向模型,没有的话,飞向自定的范围
let models = this.options.Tile3DModels.filter(item => item.gotomodel)
if (!models.length) {
this.CommonflyTo(this.centerEntity, { offset: new Cesium.HeadingPitchRange(heading, pitch, originz), duration: 5 })
}
setTimeout(() => {
// 加载水系
this.initWaterLayers(this.options.waterpolygons)
// 加载管线
this.initBaseLayers(this.options.featureLayers)
}, 5200)
} else {
this.CommonflyTo(this.centerEntity, { offset: new Cesium.HeadingPitchRange(heading, pitch, originz), duration: 5 })
setTimeout(() => {
// 加载水系
this.initWaterLayers(this.options.waterpolygons)
// 加载管线
this.initBaseLayers(this.options.featureLayers)
}, 5200)
}
}
// 挂载子class
this.bindSubClass()
// 设置初始动画速度
this.originspeed = this.ThreeViewer.clockViewModel.multiplier
// // 清除版权信息
// setTimeout(() => {
// console.clear()
// }, 8000)
}
/**
* 挂载子类
*/
bindSubClass() {
// 挂载自定义材质纹理
this.CustomMaterial = new CustomMaterial()
// 事件类
this.mapevent = new MapEvent(this.ThreeViewer, this.options.mapEventOption)
// 量测类
this.measure = new Measure(this.ThreeViewer)
// 动态绘制类
this.drawDynamicTool = new DrawDynamicTool(this.ThreeViewer)
// 绘制类
this.draw = new draw(this.ThreeViewer)
// 鼠标事件
this.handlerAction = new Handler(this.ThreeViewer)
// 基础实体事件
this.mentitys = new Mentitys(this.ThreeViewer)
// 鼠标管理
this.mouseManager = new MouseManager(this.ThreeViewer)
// 动态实体
this.entityFactory = new EntityFactory(this.ThreeViewer)
// 通用工具
this.commonTools = new commonTools()
// 弹窗类
this.popup = new Popup(this.ThreeViewer)
// 实体类自动初始化的
this.defaultEntitys = new Entitys(this.ThreeViewer)
// 自定义的Entitys
this.CustomEntitys = Entitys
// 特效实体类自动初始化
this.defaultEntitysEffect = new EntitysEffect(this.ThreeViewer)
// 自定义的EntitysEffect
this.CustomEntitysEffect = EntitysEffect
// 挂载扩散圆
this.circleDiffusion = new CircleDiffusion(this.ThreeViewer)
// 挂载六角星
this.hexagonSpread = new HexagonSpread(this.ThreeViewer, 'hexagonSpread')
// 挂载线圈发光
this.scanline = new Scanline(this.ThreeViewer, 'scanlineSpread')
// 挂载雷达平扫
this.circleScan = new CircleScan(this.ThreeViewer)
// 轨迹动画类
this.trackEntity = new TrackedAnimate(this.ThreeViewer, 'trace_animate', () => {
})
// this.criska_base = new Criska_Base(this.ThreeViewer)
}
// 分辨率调整函数
adjustmentPixel() {
// 判断是否支持图像渲染像素化处理
let supportsImageRenderingPixelated = this.ThreeViewer.cesiumWidget._supportsImageRenderingPixelated;
if (supportsImageRenderingPixelated) {
// 直接拿到设备的像素比例因子 - 如我设置的1.25
let vtxf_dpr = window.devicePixelRatio;
// 这个while我们在后面会做一个说明,但不是解决问题的说明
while (vtxf_dpr >= 2.0) { vtxf_dpr /= 2.0; }
// 设置渲染分辨率的比例因子
this.ThreeViewer.resolutionScale = vtxf_dpr;
}
}
initBaseLayers(layers) {
if (!layers || !layers.length) return []
layers.forEach(item => {
switch (item.layerType) {
case 'WebTileLayer':
this.addWebTileLayer(item)
break;
case 'WMTS':
this.addWmtsLayer(item)
break;
case 'ArcGIS':
this.addArcgisLayer(item)
break;
case 'MapBox_Raster':
this.addMapBoxRasterLayer(item)
break;
case 'WMS':
this.addWMSLayer(item)
break;
default:
break;
}
// 显隐控制
this.setLayerVisable({ layerid: item.id }, item.visable)
})
}
initBaseModels(models) {
if (!models || !models.length) return []
models.forEach(item => {
if (item.add) {
this.add3DTileModels(item)
}
})
}
initBaseEquments(points) {
if (!points || !points.length) return []
points.forEach(item => {
this.addMakers(item.points, item.sourcename, item.visable)
})
}
initWaterLayers(layers) {
// jsp.features[0].geometry.coordinates.reduce(function (a, b) { return a.concat(b) });
if (!layers || !layers.length) return []
layers.forEach(item => {
this.TestloadGeojson(item.url, '水体面')
})
}
initWaterLayersWMS(layers) {
// jsp.features[0].geometry.coordinates.reduce(function (a, b) { return a.concat(b) });
if (!layers || !layers.length) return []
layers.forEach(item => {
axios.post(item.url, null, {
params: {
...item.params
}
})
.then((res) => {
console.log(res, 'res')
//
let features = res.data.features;
features.forEach((sitem) => {
let coordinates = sitem.geometry.coordinates
coordinates.forEach((gitem) => {
console.log(gitem, 'gitem')
let c3polygon = gitem.reduce(function (a, b) { return a.concat(b) });
// console.log(c3polygon, 'c3polygonc3polygon')
// 生成水系
this.setWaterEarth(c3polygon, {
id: `water_${Math.random()}`,
baseWaterColor: [207, 53, 46, 1], // 水面基本颜色
blendColor: [127, 127, 127, 0.7], // 水面融合颜色
height: 0.24, // 水面高度
ground: false, // 是否贴底
frequency: 5000, // 水面频率
amplitude: 2, // 水面振幅
animationSpeed: 0.05, // 水面速度
specularIntensity: 0.5, // 水面强度
horizontalSpeed: 10, // 水平方向速度
verticalSpeed: 10, // 水平方向速度
outline: false
})
})
})
})
.catch(err => console.warn(err));
})
}
TestloadGeojson(data, name, color) {
// '@public/json/给水管-绿色.json'
Cesium.GeoJsonDataSource.load(data, {
fill: new Cesium.Color(0, 0.49, 1.0, 0.5), stroke: new Cesium.Color(0, 0.49, 1.0, 0.5),
}).then((dataSource) => {
dataSource.name = name
this.ThreeViewer.dataSources.add(dataSource)
console.log(dataSource, 'dataSource')
const entities = dataSource.entities.values
entities.forEach((item) => {
console.log(item, 'item')
})
})
}
setWaterEarth(degrees, options = {
id: `water_${Math.random()}`,
baseWaterColor: [0, 127, 255, 1], // 水面基本颜色
blendColor: [127, 127, 127, 0.7], // 水面融合颜色
height: 0.24, // 水面高度
ground: false, // 是否贴底
frequency: 5000, // 水面频率
amplitude: 2, // 水面振幅
animationSpeed: 0.005, // 水面速度
specularIntensity: 0.5, // 水面强度
horizontalSpeed: 10, // 水平方向速度
verticalSpeed: 10, // 水平方向速度
outline: false
}) {
// const criskaplugin = this.earth
// 处理坐标 转为弧度
let positions = degrees.map((item) => {
return Cesium.Math.toRadians(item)
})
// 处理颜色,归到0-1
let baseColor = options.baseWaterColor.map((item) => {
return item / 255
})
baseColor[3] = options.baseWaterColor[3];
let blendColor = options.blendColor.map((item) => {
return item / 255
})
blendColor[3] = options.blendColor[3];
let wateroptions = {
...options,
baseWaterColor: baseColor,
blendColor: blendColor
}
// const objConfig = {
// "ref": options.id,
// "czmObject": {
// "xbsjType": "Water",
// "positions": positions,
// ...wateroptions
// }
// };
// const Water = new XE.Obj.Water(criskaplugin);
// Water.xbsjFromJSON(objConfig);
this.earth.sceneTree.root.children.push({
"ref": options.id,
"czmObject": {
"xbsjType": "Water",
"positions": positions,
...wateroptions
}
});
// criskaplugin.sceneTree.root.children.push()
console.log(this.earth.sceneTree.root, '水系已添加')
// let water1 = criskaplugin.sceneTree.$refs.water1.czmObject;
}
/**
* 添加geoserver wmts 图层
* @param {Object} option
*/
addWmtsLayer(option) {
let CreateOption = null
const matrixIds = ['EPSG:4326:0', 'EPSG:4326:1', 'EPSG:4326:2', 'EPSG:4326:3', 'EPSG:4326:4', 'EPSG:4326:5', 'EPSG:4326:6', 'EPSG:4326:7', 'EPSG:4326:8', 'EPSG:4326:9', 'EPSG:4326:10',
'EPSG:4326:11', 'EPSG:4326:12', 'EPSG:4326:13', 'EPSG:4326:14', 'EPSG:4326:15', 'EPSG:4326:16', 'EPSG:4326:17', 'EPSG:4326:18', 'EPSG:4326:19', 'EPSG:4326:20', 'EPSG:4326:21']
// const m = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21']
// 仅支持3857和4326的数据
if (option.SR === 'EPSG:4326') {
CreateOption = {
url: option.url,
tileMatrixSetID: option.SR,
tileMatrixLabels: matrixIds,
style: option.style || '',
tilingScheme: new Cesium.GeographicTilingScheme({
// 此处很重要,很重要。。。
numberOfLevelZeroTilesX: 2,
numberOfLevelZeroTilesY: 1
})
}
} else if (option.SR === 'EPSG:3857') {
CreateOption = {
style: option.style || '',
url: `${option.url}/rest/${option.layername}/{style}/{TileMatrixSet}/{TileMatrixSet}:{TileMatrixSet}:{TileMatrix}/{TileRow}/{TileCol}?format=image/png`,
tileMatrixSetID: 'EPSG:900913'
}
}
const wmtsImageryProvider = new Cesium.WebMapTileServiceImageryProvider({
format: 'image/png',
layer: option.layername,
...CreateOption
})
wmtsImageryProvider._layerid = option.id || `layer_${Math.random()}`
if (option.addViewer) {
this.ThreeViewer.imageryLayers.addImageryProvider(wmtsImageryProvider)
}
return wmtsImageryProvider
}
addArcgisLayer(option) {
const arcGisMapServerImageryProvider = new Cesium.ArcGisMapServerImageryProvider({
url: option.url,
show: option.visable
//token: 'jrafdgyUFOu1YlyT90MAJ2WnsYFnR46esei0NIRbRPMoEDref4FEBIqdk2Pl1MZUAvpgmfbqO1Knfg1MRbXTiA..'
})
arcGisMapServerImageryProvider._layerid = option.id || `layer_${Math.random()}`
if (option.addViewer) {
this.ThreeViewer.imageryLayers.addImageryProvider(arcGisMapServerImageryProvider)
}
return arcGisMapServerImageryProvider
}
/**
* 添加网络切片
* @param {Object} option
* @returns
*/
addWebTileLayer(option) {
let CreateOption = {
url: option.url
}
// 是否纠偏
if (option.Rectification) {
CreateOption.tilingScheme = new CustomTilingScheme({
fromSR: 'GCJ02',
toSR: 'EPSG:4326'
}) // 自定义切片片方案,用于纠偏
}
// 是否设置获取可以请求的最大详细级别,可实现无限缩放
if (option.maximumLevel) CreateOption.maximumLevel = option.maximumLevel
const WebTileProvider = new Cesium.UrlTemplateImageryProvider(CreateOption)
WebTileProvider._layerid = option.id || `layer_${Math.random()}`
if (option.addViewer) {
let imga = this.ThreeViewer.imageryLayers.addImageryProvider(WebTileProvider)
// console.log(imga, 'imga')
if (imga._imageryProvider._layerid === 'baselayer_arcgis_blue') {
console.log(imga, 'imga')
// contrast 对比度
//
imga.brightness = 2.0
imga.gamma = 1.1
imga.contrast = 1.1
imga.hue = 0.050
imga.saturation = 1.5
// imga.gamma = 1
}
// imga.brightness = 3.0
// imga.contrast =
}
return WebTileProvider
}
// 加载mapbox栅格瓦片
addMapBoxRasterLayer(option) {
let CreateOption = {
// url: option.url
}
// 是否纠偏
if (option.Rectification) {
CreateOption.tilingScheme = new CustomTilingScheme({
fromSR: 'GCJ02',
toSR: 'EPSG:4326'
}) // 自定义切片片方案,用于纠偏
}
// // const GridProvider = new Cesium.GridImageryProvider(CreateOption)
// // GridProvider._layerid = option.id || `layer_${Math.random()}`
// // 添加mapbox自定义地图
let MapboxRasterLayer = new Cesium.MapboxStyleImageryProvider({
username: "wals001",
styleId: option.styleId,
scaleFactor: true,
accessToken: 'pk.eyJ1Ijoid2FsczAwMSIsImEiOiJjbGE2N2M1Ym0wMDBlM3dvMmU0MmJpazZ3In0.eFa_DgNJBal3KUH5yvlZAg',
...CreateOption
});
// mapbox://styles/criska/cl9sfslxy002z15smj457t4jn
this.ThreeViewer.imageryLayers.addImageryProvider(MapboxRasterLayer);
return MapboxRasterLayer
}
// 加载wms服务
addWMSLayer(option) {
let wmsImageryProvider = new Cesium.WebMapServiceImageryProvider({
parameters: {
transparent: true,
format: 'image/png',
srs: option.SR,
styles: ''
},
...option
});
wmsImageryProvider._layerid = option.id || `layer_${Math.random()}`
this.ThreeViewer.imageryLayers.addImageryProvider(wmsImageryProvider); //加载
}
// 添加3Dtile模型
add3DTileModels(option) {
const ModelsTileset = new Cesium.Cesium3DTileset({
url: option.url,
skipLevelOfDetail: true,
baseScreenSpaceError: 1024,
maximumScreenSpaceError: 160, // 数值加大,能让最终成像变模糊
skipScreenSpaceErrorFactor: 16,
skipLevels: 1,
immediatelyLoadDesiredLevelOfDetail: false,
loadSiblings: true, // 如果为true则不会在已加载完概况房屋后,自动从中心开始超清化房屋
cullWithChildrenBounds: true,
cullRequestsWhileMoving: true,
cullRequestsWhileMovingMultiplier: 10, // 值越小能够更快的剔除
preloadWhenHidden: true,
preferLeaves: true,
maximumMemoryUsage: 256, // 内存分配变小有利于倾斜摄影数据回收,提升性能体验
progressiveResolutionHeightFraction: 0.5, // 数值偏于0能够让初始加载变得模糊
// dynamicScreenSpaceErrorDensity: 0.1, // 数值加大,能让周边加载变快
dynamicScreenSpaceErrorDensity: 1, // 数值加大,能让周边加载变快
dynamicScreenSpaceErrorFactor: 1, // 不知道起了什么作用没,反正放着吧先
dynamicScreenSpaceError: true // 根据测试,有了这个后,会在真正的全屏加载完之后才清晰化房屋
})
// Cesium.ExperimentalFeatures.enableModelExperimental = true
if (option.rgba) {
ModelsTileset.readyPromise.then(function (tileset) {
tileset.style = new Cesium.Cesium3DTileStyle({
color: {
conditions: [
// #9faabd // 'rgb(51, 153, 255)'
// "color('rgb(150, 179, 189)',1)"
["true", option.rgba]
]
}
});
// viewer.flyTo(tileset)
})
}
// 判断是否使用自定义片元着色器
if (option.customShader) {
let customShader = new Cesium.CustomShader({
lightingModel: Cesium.LightingModel[option.customShader.lightingModel],
fragmentShaderText: option.customShader.fragmentShaderText
})
ModelsTileset.enableModelExperimental = true;
ModelsTileset.customShader = customShader;
} else {
ModelsTileset.enableModelExperimental = false;
}
ModelsTileset._modelid = option.id || `model_${Math.random()}`
// this.ThreeViewer.scene.primitives.add(ModelsTileset)
this.primitiveadd(ModelsTileset)
// 是否要调整模型位置
if (option.isreset) {
ModelsTileset.readyPromise.then((newtileset) => {
// this.tileSet(newtileset, 104.635759, 30.132481, 9)
this.tileSetAll(newtileset,...option.isresetoption)
});
}
// 是否定位到模型位置
if (option.gotomodel) {
this.ThreeViewer.flyTo(ModelsTileset)
}
return ModelsTileset
}
// 修改模型颜色
change3DTileModelsColor(modelid, rgba) {
const model = this.getModel(modelid)
model.style = new Cesium.Cesium3DTileStyle({
color: {
conditions: [
["true", rgba]
]
}
})
}
primitiveadd(primitive) {
this.Primitivemanager.add(primitive);
if (this.ThreeViewer.scene.primitives.length <= 1) {
this.ThreeViewer.scene.primitives.add(this.Primitivemanager);
}
}
// 利用translation对模型的经度、纬度、高度进行修改
tileSet(tileset, longitude, latitude, height = 0) {
//3dtile模型的边界球体
var boundingSphere = tileset.boundingSphere;
//迪卡尔空间直角坐标=>地理坐标(弧度制)
var cartographic_original = Cesium.Cartographic.fromCartesian(boundingSphere.center);
//设置新的经度、纬度、高度
var cartographic_offset = Cesium.Cartographic.fromDegrees(longitude, latitude, height)
//地理坐标(弧度制)=>迪卡尔空间直角坐标
var Cartesian3_original = Cesium.Cartesian3.fromRadians(cartographic_original.longitude, cartographic_original.latitude, cartographic_original.height);
var Cartesian3_offset = Cesium.Cartesian3.fromRadians(cartographic_offset.longitude, cartographic_offset.latitude, cartographic_offset.height);
//获得地面和offset的转换
var translation = Cesium.Cartesian3.subtract(Cartesian3_offset, Cartesian3_original, new Cesium.Cartesian3());
//修改模型矩阵
tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation);
}
// 利用transform对模型的所有参数进行修改
tileSetAll(tileset, longitude, latitude, height, rotateX, rotateY, rotateZ, scale) {
//平移 修改经纬度
// const cartographic = Cesium.Cartographic.fromCartesian(tileset.boundingSphere.center);
// var position = Cesium.Cartesian3.fromDegrees(cartographic.longitude, cartographic.latitude, cartographic.height);
var position = Cesium.Cartesian3.fromDegrees(longitude, latitude, height);
var transform = Cesium.Transforms.eastNorthUpToFixedFrame(position);
//旋转角度设置
if (rotateX) {
var mx = Cesium.Matrix3.fromRotationX(Cesium.Math.toRadians(rotateX));
var rotationX = Cesium.Matrix4.fromRotationTranslation(mx);
//旋转、平移矩阵相乘
Cesium.Matrix4.multiply(transform, rotationX, transform);
}
if (rotateY) {
var my = Cesium.Matrix3.fromRotationY(Cesium.Math.toRadians(rotateY));
var rotationY = Cesium.Matrix4.fromRotationTranslation(my);
//旋转、平移矩阵相乘
Cesium.Matrix4.multiply(transform, rotationY, transform);
}
if (rotateZ) {
var mz = Cesium.Matrix3.fromRotationZ(Cesium.Math.toRadians(rotateZ));
var rotationZ = Cesium.Matrix4.fromRotationTranslation(mz);
//旋转、平移矩阵相乘
Cesium.Matrix4.multiply(transform, rotationZ, transform);
}
//缩放 修改缩放比例
if (scale) {
var scale1 = Cesium.Matrix4.fromUniformScale(scale);
Cesium.Matrix4.multiply(transform, scale1, transform);
}
//赋值给tileset
tileset._root.transform = transform;
}
primitivedeletes(primitive) {
this.Primitivemanager.remove(primitive);
}
primitiveRemoveall() {
if (this.ThreeViewer.scene.primitives.length <= 1) {
this.ThreeViewer.scene.primitives.removeAll()
} else {
this.Primitivemanager.removeAll()
}
}
// 添加点位
addMakers(points, sourcetype = `source_${Math.random()}`, visable = true) {
let dataSource = null
// 获取dataSource 存在的状态
const indataSource = this.getDataSourceByName(sourcetype)
// 如果存在 先清除所有实体
if (indataSource) {
indataSource.entities.removeAll()
dataSource = indataSource
} else {
// 生成新的dataSource
dataSource = new Cesium.CustomDataSource(sourcetype)
// dataSource添加到viewer
this.ThreeViewer.dataSources.add(dataSource)
}
// 默认显示或隐藏
dataSource.show = visable
// 自定义label颜色
const textColor = 'rgb(11, 255, 244)'
// 清除上一次加载的点位
// this.ThreeViewer.entities.removeAll()
// 添加点位
points.forEach((pointObj) => {
// 循环添加点位引线方法
const labelEntityLine = this.addFloatPoint(pointObj, pointObj.longitude, pointObj.latitude, pointObj.height, dataSource)
this.pointEntitiesLine.push(labelEntityLine)
let pointentities = {
name: pointObj.name || '',
id: pointObj.id,
eid: pointObj.id,
content: pointObj.content || '',
position: Cesium.Cartesian3.fromDegrees(
pointObj.longitude,
pointObj.latitude,
pointObj.height || 0
),
// 文字标签
label: pointObj.orilabel || {
show: pointObj.label.show || false,
text: pointObj.label.text || '',
font: pointObj.label.fontsize ? `${pointObj.label.fontsize} monospace` : `14px monospace`,
style: pointObj.label.style ? Cesium['LabelStyle'][pointObj.label.style] : Cesium['LabelStyle']['FILL_AND_OUTLINE'],
fillColor: pointObj.label.color ? Cesium.Color.fromCssColorString(pointObj.label.color) : Cesium.Color.fromCssColorString(textColor),
outlineWidth: pointObj.label.outlineWidth || 4,
verticalOrigin: pointObj.label.verticalOrigin ? Cesium['VerticalOrigin'][pointObj.label.verticalOrigin] : Cesium.VerticalOrigin.BOTTOM, // 垂直方向以底部来计算标签的位置
pixelOffset: pointObj.label.offsetx && pointObj.label.offsety ? new Cesium.Cartesian2(pointObj.label.offsetx, pointObj.label.offsety) : new Cesium.Cartesian2(0, -60) // 偏移量
},
// 图标
billboard: {
image: pointObj.billboard.image || 'https://p26-passport.byteacctimg.com/img/user-avatar/a7ab372b32558ab9c8e130194a1a78d8~300x300.image',
width: pointObj.billboard.width || 48,
height: pointObj.billboard.height || 75,
pixelOffset: pointObj.billboard.offsetx && pointObj.billboard.offsety ? new Cesium.Cartesian2(pointObj.billboard.offsetx, pointObj.billboard.offsety) : new Cesium.Cartesian2(0, 0), // 偏移量
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM
}
}
if (pointObj.hasOwnProperty('selfsymbol')) {
pointentities = {
name: pointObj.name,
id: pointObj.id,
eid: pointObj.id,
position: Cesium.Cartesian3.fromDegrees(
pointObj.longitude,
pointObj.latitude,
pointObj.height || 0
),
...pointObj.selfsymbol
}
}
// 实体添加到dataSource
dataSource.entities.add(pointentities)
})
return dataSource
}
// 加载高度线
addFloatPoint(pointObj, long, lat, height, dataSource) {
const lineColor = '#108de7'
let floatlinesymbol = {
positions: Cesium.Cartesian3.fromDegreesArrayHeights([
long, lat, 0,
long, lat, height
]),
width: 1,
// 材质设置
// material: Cesium.Color.DODGERBLUE,
// material: Cesium.Color.fromCssColorString(lineColor)
material: new Cesium.PolylineGlowMaterialProperty({ //发光线
glowPower: pointObj.floatline.glowPower || 0.25,
color: pointObj.floatline.color ? Cesium.Color.fromCssColorString(pointObj.floatline.color) : Cesium.Color.DODGERBLUE
})
}
if (pointObj.floatline.hasOwnProperty('selfsymbol')) {
floatlinesymbol = {
positions: Cesium.Cartesian3.fromDegreesArrayHeights([
long, lat, 0,
long, lat, height
]),
...pointObj.floatline.selfsymbol
}
}
// 如果传了dataSource 加载到dataSource
if (dataSource) {
dataSource.entities.add({
name: 'line_' + pointObj.pointName,
code: 'line_' + pointObj.id,
id: 'line_' + pointObj.id,
eid: 'line_' + pointObj.id,
// 经度维度必须是数字
// position: Cesium.Cartesian3.fromDegrees(120.42602, 31.92423),
polyline: floatlinesymbol
})
return dataSource.entities
} else {
// 否则加载到viewer的entities里
const entityLine = this.ThreeViewer.entities.add({
name: 'line_' + pointObj.pointName,
code: 'line_' + pointObj.id,
id: 'line_' + pointObj.id,
eid: 'line_' + pointObj.id,
// 经度维度必须是数字
// position: Cesium.Cartesian3.fromDegrees(120.42602, 31.92423),
polyline: floatlinesymbol
})
return entityLine
}
}
// 加载信息框
addPopPoint(pointObj, long, lat, height, dataSource) {
}
// 添加点位模型
addGlbModels(points, sourcetype = `source_${Math.random()}`, visable = true) {
let dataSource = null
// 获取dataSource 存在的状态
const indataSource = this.getDataSourceByName(sourcetype)
// 如果存在 先清除所有实体
if (indataSource) {
indataSource.entities.removeAll()
dataSource = indataSource
} else {
// 生成新的dataSource
dataSource = new Cesium.CustomDataSource(sourcetype)
// dataSource添加到viewer
this.ThreeViewer.dataSources.add(dataSource)
}
// 默认显示或隐藏
dataSource.show = visable
// 自定义label颜色
const textColor = 'rgb(11, 255, 244)'
// 清除上一次加载的点位
// this.ThreeViewer.entities.removeAll()
// 添加点位
points.forEach((pointObj) => {
// 循环添加点位引线方法
// const labelEntityLine = this.addFloatPoint(pointObj, pointObj.longitude, pointObj.latitude, 1000, dataSource)
// this.pointEntitiesLine.push(labelEntityLine)
let modelentities = {
name: pointObj.name || '',
id: pointObj.id,
eid: pointObj.id,
content: pointObj.content || '',
position: Cesium.Cartesian3.fromDegrees(
pointObj.longitude,
pointObj.latitude,
pointObj.height || 0
),
orientation: Cesium.Transforms.headingPitchRollQuaternion(
Cesium.Cartesian3.fromDegrees(
pointObj.longitude,
pointObj.latitude,
pointObj.height || 0
),
new Cesium.HeadingPitchRoll(
Cesium.Math.toRadians(pointObj.head || 50), // 设置这个属性即可(顺时针旋转的角度值)
Cesium.Math.toRadians(pointObj.roll || 0),
Cesium.Math.toRadians(pointObj.patch || 0)
)
),
// orientation: new Cesium.CallbackProperty(diaoyong, false),
model: {
show: true,
uri: pointObj.modeluri,
scale: pointObj.modelscale,
color: pointObj.color ? Cesium.Color.fromCssColorString(pointObj.color) : null,
minimumPixelSize: 60,
maximumScale: 50000,
},
...pointObj
}
// 实体添加到dataSource
dataSource.entities.add(modelentities)
})
return dataSource
}
/**
* 创建缓冲区
* @param {*} lon
* @param {*} lat
* @param {*} radius
* @param {*} units
*/
createBuffer(lon, lat, radius, units = 'kilometer') {
const point = turf.point([lon, lat])
const buffered = turf.buffer(point, radius / 1000, { units })
let coordinates = buffered.geometry.coordinates
let points = coordinates[0]
let degreesArray = this.pointsToDegreesArray(points)
// this.ThreeViewer.entities.add({
// polygon: {
// hierarchy: new Cesium.PolygonHierarchy(Cesium.Cartesian3.fromDegreesArray(degreesArray)),
// material: Cesium.Color.RED.withAlpha(0.6),
// classificationType: Cesium.ClassificationType.BOTH
// },
// })
return {
geojson: buffered,
degreesArray
}
}
// 点数组转为cesium格式
pointsToDegreesArray(points, height) {
let degreesArray = []
points.map(item => {
degreesArray.push(item[0])
degreesArray.push(item[1])
if (height) {
degreesArray.push(height)
}
});
return degreesArray
}
/**
* 删除图层
* @param {*} layer
* @param {*} hasDestroy 是否释放对象
*/
removeLayer(layer, hasDestroy) {
this.marsmap.removeLayer(layer, hasDestroy)
}
getLayerById() {
}
removeAllEntity(sourcetype) {
// 清除dataSource的实体
if (sourcetype) {
const DataSource = this.getDataSourceByName(sourcetype)
DataSource.entities.removeAll()
} else {
const DataSources = this.getDataSources()
DataSources._dataSources.forEach((item) => {
if (item.name) {
if (!(item.name.includes('Equpoint'))) {
item.entities.removeAll()
}
}
})
this.ThreeViewer.entities.removeAll()
}
}
// 清除所有实体,关闭点选事件,关闭量测
clearEntandCloseMe() {
// 删除实体
this.removeAllEntity()
// 清除点选
this.options.mapEventOption.openEntityEventMap = false
this.options.mapEventOption.pipeEventMap = false
// 关闭量测
this.measure.remove()
}
/**
* 清除实体通过Eid
* @param {} eid
* @param {*} sourcetype
* @returns
*/
removeEntityByEid(eid, sourcetype) {
const { entities, Entity } = this.getEntityByEid(eid, sourcetype)
entities.remove(Entity)
return entities
}
/**
* 清除实体通过id
* @param {} id
* @param {*} sourcetype
* @returns
*/
removeEntityById(id, sourcetype) {
const { entities, Entity } = this.getEntityById(id, sourcetype)
entities.remove(Entity)
return entities
}
removeDataSource(name, destroy = true) {
const dataSource = this.getDataSourceByName(name)
// 获取单一设备
this.ThreeViewer.dataSources.remove(dataSource, destroy)
}
getViewer() {
return this.ThreeViewer
}
/**
* 获取具有中心和半径的包围球。
* @param {Object} option
*/
getBoundingSphere(option) {
// Cartesian3.fromDegrees 从以度为单位的经度和纬度值返回笛卡尔坐标位置。
return new Cesium.BoundingSphere(
Cesium.Cartesian3.fromDegrees(option.x, option.y, option.z),
option.r
)
}
/**
* 从以度为单位的经度和纬度值返回Cartesian3位置。
* @returns
*/
getCartesian3fromDegrees(longitude, latitude, height = 0) {
return Cesium.Cartesian3.fromDegrees(Number(longitude), Number(latitude), Number(height))
}
/**
* 笛卡尔坐标转换为画布坐标
* @param {} Cartesian3
*/
getCanvasCoordfromcartesian(Cartesian3) {
return this.ThreeViewer.scene.cartesianToCanvasCoordinates(Cartesian3, new Cesium.Cartesian2())
}
// 笛卡尔转为经纬度
getWGS84FromCartesian3(coor) {
let cartographic = Cesium.Cartographic.fromCartesian(coor);
let x = Cesium.Math.toDegrees(cartographic.longitude);
let y = Cesium.Math.toDegrees(cartographic.latitude);
let wgs84 = {
x: x,
y: y,
};
return wgs84;
}
/**
*
* @returns 获取当前范围
*/
getCurrentExtent() {
// 范围对象
let extent = {}
// 得到当前三维场景
let scene = this.ThreeViewer.scene
// 得到当前三维场景的椭球体
let ellipsoid = scene.globe.ellipsoid
let canvas = scene.canvas;
// canvas左上角
let car3_lt = this.ThreeViewer.camera.pickEllipsoid(new Cesium.Cartesian2(0, 0), ellipsoid)
// canvas右下角
let car3_rb = this.ThreeViewer.camera.pickEllipsoid(new Cesium.Cartesian2(canvas.width, canvas.height), ellipsoid)
// 当canvas左上角和右下角全部在椭球体上
if (car3_lt && car3_rb) {
let carto_lt = ellipsoid.cartesianToCartographic(car3_lt)
let carto_rb = ellipsoid.cartesianToCartographic(car3_rb)
extent.xmin = Cesium.Math.toDegrees(carto_lt.longitude)
extent.ymax = Cesium.Math.toDegrees(carto_lt.latitude)
extent.xmax = Cesium.Math.toDegrees(carto_rb.longitude)
extent.ymin = Cesium.Math.toDegrees(carto_rb.latitude)
}
// 当canvas左上角不在但右下角在椭球体上
else if (!car3_lt && car3_rb) {
let car3_lt2 = null;
let yIndex = 0
do {
// 这里每次10像素递加,一是10像素相差不大,二是为了提高程序运行效率
yIndex <= canvas.height ? yIndex += 10 : canvas.height
car3_lt2 = this.ThreeViewer.camera.pickEllipsoid(new Cesium.Cartesian2(0, yIndex), ellipsoid)
} while (!car3_lt2);
let carto_lt2 = ellipsoid.cartesianToCartographic(car3_lt2)
let carto_rb2 = ellipsoid.cartesianToCartographic(car3_rb)
extent.xmin = Cesium.Math.toDegrees(carto_lt2.longitude)
extent.ymax = Cesium.Math.toDegrees(carto_lt2.latitude)
extent.xmax = Cesium.Math.toDegrees(carto_rb2.longitude)
extent.ymin = Cesium.Math.toDegrees(carto_rb2.latitude)
}
// 获取高度
extent.height = Math.ceil(this.ThreeViewer.camera.positionCartographic.height)
return extent
}
getScale() {
// 监听场景渲染事件
}
/**
* 获取dataSources数据集
* @returns
*/
getDataSources() {
return this.ThreeViewer.dataSources
}
/**
* 根据name从DataSources 中 获取dataSource
* @param {*} name
* @returns
*/
getDataSourceByName(name) {
return this.ThreeViewer.dataSources.getByName(name)[0]
}
/**
* 根据Eid获取实体
* @param {*} eid
* @param {*} sourcetype
* @returns
*/
getEntityByEid(eid, sourcetype) {
// 根据sourcetype 查询到Source
let entities = null
if (sourcetype) {
const DatsSource = this.getDataSourceByName(sourcetype)
entities = DatsSource.entities
} else {
entities = this.ThreeViewer.entities
}
//根据Eid在dataSource中查找中Entity
const ent = entities.values.filter((item) => {
if (item.eid === eid) {
return item
}
})
return {
entities,
Entity: ent[0]
}
}
/**
* 获取实体通过ID
* @param {} id
* @param {*} sourcetype
* @returns
*/
getEntityById(id, sourcetype) {
// 根据sourcetype 查询到Source
let entities = null
if (sourcetype) {
const DatsSource = this.getDataSourceByName(sourcetype)
entities = DatsSource.entities
} else {
entities = this.ThreeViewer.entities
}
//根据Eid在dataSource中查找中Entity
const ent = entities.getById(id)
return {
entities,
Entity: ent
}
}
getModel(modelid) {
const model = this.Primitivemanager._primitives.filter((item) => {
if (item._modelid === modelid) {
return item
}
})
return model[0]
}
/* 获取camera高度 */
getHeight() {
if (this.ThreeViewer) {
let height = this.ThreeViewer.camera.positionCartographic.height
return height
}
}
/* 获取camera中心点坐标 */
getCenterPosition() {
const result = this.ThreeViewer.camera.pickEllipsoid(new Cesium.Cartesian2(this.ThreeViewer.canvas.clientWidth / 2, this.ThreeViewer.canvas
.clientHeight / 2))
const curPosition = Cesium.Ellipsoid.WGS84.cartesianToCartographic(result)
const lon = curPosition.longitude * 180 / Math.PI
const lat = curPosition.latitude * 180 / Math.PI
const height = this.getHeight()
return {
lon: lon,
lat: lat,
height: height
}
}
/**
* 获取相机姿态位置
* @returns
*/
getcameraPosInfo() {
// 获取 相机姿态信息
let head = this.ThreeViewer.scene.camera.heading
let pitch = this.ThreeViewer.scene.camera.pitch
let roll = this.ThreeViewer.scene.camera.roll
let info = { 'head': head, 'pitch': pitch, 'roll': roll };
// 获取位置 wgs84的地心坐标系,x,y坐标值以弧度来表示
let position = this.ThreeViewer.scene.camera.positionCartographic //with longitude and latitude expressed in radians and height in meters.
//以下方式也可以获取相机位置只是返回的坐标系不一样
// let position = viewer.scene.camera.position //cartesian3 空间直角坐标系
// let ellipsoid = scene.globe.ellipsoid;
// let position =ellipsoid.cartesianToCartographic(viewer.scene.camera.position)//
// 弧度转经纬度
let longitude = Cesium.Math.toDegrees(position.longitude).toFixed(6)
let latitude = Cesium.Math.toDegrees(position.latitude).toFixed(6)
let height = position.height
return { lng: longitude, lat: latitude, h: height, mat: info }
}
/* 地图放大 */
setMapbig() {
// 镜头拉进
this.ThreeViewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(this.getCenterPosition().lon, this.getCenterPosition().lat, this.getCenterPosition().height / 1.8),
duration: 1.0,
// orientation : {
// direction: this.ThreeViewer.camera.direction,
// right: this.ThreeViewer.camera.right,
// up: this.ThreeViewer.camera.up,
// }
})
}
/* 地图缩小 */
setMapsmall() {
// 镜头远离
this.ThreeViewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(this.getCenterPosition().lon, this.getCenterPosition().lat, this.getCenterPosition().height * 1.2),
duration: 1.0
})
}
/**
* 设置图层显示和隐藏
* @param {*} layerid
* @param {*} layer
* @param {*} layer
*/
setLayerVisable({ layerid, layer = null }, visable) {
if (layer) {
console.log('我选择了layer,可直接隐藏')
} else {
// 从所有图层中进行遍历查询
if (this.ThreeViewer.imageryLayers.length > 0) {
this.ThreeViewer.imageryLayers._layers.forEach((item) => {
if (item.imageryProvider._layerid === layerid) {
item.show = visable
}
})
}
}
}
CreateDataSource(sourcetype) {
return new Cesium.CustomDataSource(sourcetype)
}
switchBaseLayer(layerid) {
// 高德影像
if (layerid.includes('amap_img')) {
this.options.baseLayer.Cesium.forEach((item) => {
if (item.id === layerid || item.id.includes('amap_label')) {
// 设置为显示
this.setLayerVisable({ layerid: item.id }, true)
} else {
// 其他的设置为隐藏
this.setLayerVisable({ layerid: item.id }, false)
}
})
}
// 高德普通 和 深色
else {
this.options.baseLayer.Cesium.forEach((item) => {
if (item.id === layerid) {
// 设置为显示
this.setLayerVisable({ layerid: item.id }, true)
} else {
// 其他的设置为隐藏
this.setLayerVisable({ layerid: item.id }, false)
}
})
}
}
/**
*
* @param {*} boundingSphere
* @param {*} option 包含callback
*/
flyToBoundingSphere(boundingSphere, option = {
duration: 1
}) {
this.ThreeViewer.camera.flyToBoundingSphere(boundingSphere, option)
}
/**
* 相机视角移动
* @param {*} lon
* @param {*} lat
* @param {*} height
* @param {*} additional
*/
flyTo(lon, lat, height = 1500, additional = {
orientation: {
heading: 0,
pitch: -45,
roll: 0
}
}) {
let SetOption = additional
if (additional.hasOwnProperty('orientation')) {
SetOption.orientation.heading = Cesium.Math.toRadians(additional.orientation.heading)
SetOption.orientation.pitch = Cesium.Math.toRadians(additional.orientation.pitch)
SetOption.orientation.roll = Cesium.Math.toRadians(additional.orientation.roll)
}
this.ThreeViewer.camera.flyTo({
destination: this.getCartesian3fromDegrees(lon, lat, height),
...SetOption
})
}
/**
*
* @param {*} target
* @param {*} options
* @returns 飞行成功返回一个为true的promise
*/
CommonflyTo(target, options) {
return this.ThreeViewer.flyTo(target, options)
}
/**
* 相机恢复初始状态
*/
gotoOriginBoundingSphere() {
let centerpoint = this.getEntityByEid('centerpoint');
if (!centerpoint.Entity) {
this.ThreeViewer.entities.add(this.centerEntity);
}
const { z: originz } = this.options.mapOption.center
const { heading, pitch } = this.options.mapOption
this.CommonflyTo(this.centerEntity, { offset: new Cesium.HeadingPitchRange(heading, pitch, originz), duration: 5 })
}
// 地球自转
autoRotation(callback) {
let i = Date.now()
let rotate = () => {
const a = 0.8;
const t = Date.now();
const n = (t - i) / 1e3
i = t;
this.ThreeViewer.scene.camera.rotate(Cesium.Cartesian3.UNIT_Z, -a * n)
}
// 只要时间变化就执行
this.ThreeViewer.clock.onTick.addEventListener(rotate);
// 4.2s后 北美洲转动至亚洲,停止转动,进入回调
setTimeout(() => {
this.ThreeViewer.clock.onTick.removeEventListener(rotate)
callback()
}, 4200);
}
// 日照管理
sunshine(sun) {
this.ThreeViewer.scene.globe.enableLighting = sun
this.ThreeViewer.shadows = sun
}
changeEarthColor(color) {
this.ThreeViewer.scene.globe.baseColor = new Cesium.Color.fromCssColorString(color)
}
/**
* 时间轴操作
*/
// 动画暂停
clockPause() {
this.ThreeViewer.clock.shouldAnimate = false
}
// 动画开始
clockRestar() {
this.ThreeViewer.clock.shouldAnimate = true
}
// 动画倍速
clockhastenMultiplier(v) {
this.ThreeViewer.clockViewModel.multiplier = this.originspeed * v
}
// 动画减倍速
clockdecelerateMultiplier(v) {
this.ThreeViewer.clockViewModel.multiplier = this.originspeed / v
}
// 重置时间轴
clockReset() {
this.ThreeViewer.clock.currentTime = this.ThreeViewer.clock.startTime;
}
// 循环/不循环
// 时间轴执行完后停止(LOOP_STOP为循环,UNBOUNDED为继续读秒)
clockClockRange(type = 'CLAMPED') {
this.ThreeViewer.clock.clockRange = Cesium.ClockRange[type];
}
// 水面流动特效
/**
* 绘制水面
* @param boundary 边界点位 [112.23, 22.25, 112.24, 22.24]
* @param waterImg 水面贴图
* @param extrudedHeight 水面高度
* @returns 水面实例
*/
useDrawRiver(
boundary,
waterImg,
extrudedHeight = 0
) {
const _this = this
let riverHeight = extrudedHeight
console.log(this.useCreatePolygonGeometry, 'this.useCreatePolygonGeometry')
const polygon = this.useCreatePolygonGeometry(boundary, riverHeight)
let river = null
river = new Cesium.Primitive({
geometryInstances: new Cesium.GeometryInstance({
geometry: polygon,
}),
appearance: new Cesium.EllipsoidSurfaceAppearance({
aboveGround: true,
}),
show: true,
asynchronous: false,
releaseGeometryInstances: false,
})
const riverMaterial = new Cesium.Material({
fabric: {
type: 'Water',
uniforms: {
baseWaterColor: new Cesium.Color(64 / 255.0, 157 / 255.0, 253 / 255.0, 0.5), // 水的基本颜色
normalMap: waterImg, // 水的法线贴图
frequency: 5000.0, // 水波纹的数量
animationSpeed: 0.005, // 水的流速
amplitude: 2, // 水波纹振幅
specularIntensity: 1, // 镜面反射强度
},
},
})
const scene = this.ThreeViewer.scene
river.appearance.material = riverMaterial
scene.primitives.add(river) //添加到场景
river.appearance.material = riverMaterial
Object.defineProperty(river, 'extrudedHeight', {
get() {
return riverHeight
},
set(newVal) {
if (typeof newVal !== 'number') {
return
}
riverHeight = newVal
river._state = 3 // 重置primitive状态触发cesium update方法
river._appearance = undefined
river.geometryInstances.geometry = _this.useCreatePolygonGeometry(boundary, riverHeight)
},
})
return river
}
useCreatePolygonGeometry(boundary, extrudedHeight) {
const polygon = new Cesium.PolygonGeometry({
polygonHierarchy: new Cesium.PolygonHierarchy(Cesium.Cartesian3.fromDegreesArray(boundary)),
extrudedHeight,
vertexFormat: Cesium.EllipsoidSurfaceAppearance.VERTEX_FORMAT,
})
return polygon
}
// 生成光锥体点位
/**
* 光锥体点位
* @param points 点位数据 [{longitude: 120, latitude: 38, height: 100}]
* @param options 光锥体颜色,底部半径及高度
* @param popupHtml 光锥体弹窗(html格式,不传则无点击弹窗功能) <table></table>
* @param leftFnc 函数,图层左键点击事件回调(点击获取点位信息时使用)
* @param rightObj 右键点击事件对象{text: '标题', offsetY: -170}
*/
createLightCone(points, options = {
color: 'rgba(255,0,0,0.9)', // 椎体颜色
radius: 8000, // 底部半径
height: 150000 // 椎体高度
}, popupHtml, layername, leftFnc, rightObj) {
let graphicLayer = null
if (layername) {
// 创建矢量数据图层
let cusgraphicLayer = new mars3d.layer.GraphicLayer({ id: layername })
graphicLayer = cusgraphicLayer
this.marsmap.addLayer(graphicLayer)
} else {
graphicLayer = this.mgraphicLayer
}
if (popupHtml) {
graphicLayer.bindPopup(popupHtml)
}
points.forEach(pointObj => {
if (pointObj.longitude && pointObj.latitude) {
const lightCone = new mars3d.graphic.LightCone({
position: Cesium.Cartesian3.fromDegrees(pointObj.longitude, pointObj.latitude, (pointObj.height || 20)),
style: {
color: options.color,
radius: options.radius,
height: options.height
},
show: true
})
graphicLayer.addGraphic(lightCone)
}
})
// if (leftFnc) {
// graphicLayer.on(mars3d.EventType.click, leftFnc)
// }
// if (rightObj) {
// // 在layer上绑定右键菜单
// graphicLayer.bindContextMenu(
// [
// {
// text: rightObj.text,
// icon: "fa fa-trash-o",
// callback: (e) => {
// const graphic = e.graphic
// console.log(graphic)
// }
// }
// ],
// { offsetY: rightObj.offsetY } // 右键菜单偏移量
// )
// }
}
// 生成视频点位
/**
* 视频点位
* @param points 点位数据 [{longitude: 120, latitude: 38, height: 100, videoUrl: 'http://data.mars3d.cn/file/video/lukou.mp4'}]
*/
createVideoPoint(points) {
// 创建矢量数据图层
let graphicLayer = new mars3d.layer.GraphicLayer()
this.marsmap.addLayer(graphicLayer)
points.forEach(pointObj => {
const graphicImg = new mars3d.graphic.DivGraphic({
position: [pointObj.longitude, pointObj.latitude, (pointObj.height || 20)],
style: {
html: `<div class="mars3d-camera-content">
<img class="mars3d-camera-img" src="${require("../assets/img/icon/camera.svg").default}" >
</div>
<div class="mars3d-camera-line" ></div>
<div class="mars3d-camera-point"></div>`,
offsetX: -16,
distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 100000)
},
// popup: `<video src='http://data.mars3d.cn/file/video/lukou.mp4' controls autoplay style="width: 300px;" ></video>`,
popup: `<video src='${pointObj.videoUrl}' controls autoplay style="width: 300px;" ></video>`,
popupOptions: {
offsetY: -170, // 显示Popup的偏移值,是DivGraphic本身的像素高度值
template: `<div class="marsBlackPanel animation-spaceInDown">
<div class="marsBlackPanel-text">{content}</div>
<span style="color: white;" class="mars3d-popup-close-button closeButton" >×</span>
</div>`,
horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
verticalOrigin: Cesium.VerticalOrigin.CENTER
}
})
graphicLayer.addGraphic(graphicImg)
})
}
}
function animationVersion() {
console.clear()
console.log('\n'.repeat('1000'));
window.requestAnimationFrame(animationVersion);
}
export { Criska_Cesium }