import WKT from 'terraformer-wkt-parser'; import { nextTick } from 'vue'; import MVTImageryProvider from './mvtImageProvider.js'; export default class NewFiberMapUtils { //地图实例 map = null; features = []; removeHandler = null; colorOpacity = 1; constructor(pramas) { Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIwNGNmNWUwMi02NWEyLTQxNzItOTNhNC1mY2NiZTcxNDc2OWYiLCJpZCI6MTU5NDQsInNjb3BlcyI6WyJhc2wiLCJhc3IiLCJhc3ciLCJnYyJdLCJpYXQiOjE1NjkyMjk3MTN9.PYUfCHykW23NuwRzzz04yW7JyZ4vQlcb4kToZ44r42w'; let config = Object.assign(this.mapConfig(pramas)); config.container = pramas.container || config.container; config.featureCallBack = pramas.featureCallBack || config.featureCallBack; this.map = new Cesium.Viewer(config.container, config); this.map.imageryLayers.remove(this.map.imageryLayers.get(0)); this.map.scene.globe.maximumScreenSpaceError = 4 / 1; } mapConfig({ selectionIndicator = false, animation = false, baseLayerPicker = false, timeline = false, sceneModePicker = false, navigationHelpButton = false, useDefaultRenderLoop = true, showRenderLoopErrors = true, fullscreenButton = false, infoBox = false, vrButton = false, geocoder = false, homeButton = false, CreditsDisplay = false, contextOptions = { requestWebgl1: true, }, }) { return { contextOptions, selectionIndicator, baseLayerPicker, timeline, sceneModePicker, navigationHelpButton, useDefaultRenderLoop, showRenderLoopErrors, fullscreenButton, infoBox, animation, vrButton, geocoder, homeButton, CreditsDisplay, }; } //设置视角无动画 setView(fields = { lon: 0, lat: 0, zoom: 10000000, heading: 0, pitch: 0, roll: 0 }) { let self = this; self.map.camera.setView({ destination: Cesium.Cartesian3.fromDegrees(fields.lon, fields.lat, fields.zoom), //赤道上空1000km高度 orientation: { heading: Cesium.Math.toRadians(fields.heading), // 相机方向指向当地东向 pitch: Cesium.Math.toRadians(fields.pitch), // 再将相机方向转向地心,此时Up方向指向当地东向 roll: fields.roll, }, }); } //设置视角有动画 flyTo(fields = { lon: 0, lat: 0, zoom: 10000000, heading: 0, pitch: 0, roll: 0, duration: 1 }) { let self = this; self.map.camera.flyTo({ duration: fields.fields, //飞行时间 destination: Cesium.Cartesian3.fromDegrees(fields.lon, fields.lat, fields.zoom), //赤道上空1000km高度 orientation: { heading: Cesium.Math.toRadians(fields.heading), // 相机方向指向当地东向 pitch: Cesium.Math.toRadians(fields.pitch), // 再将相机方向转向地心,此时Up方向指向当地东向 roll: fields.roll, }, }); } //添加矢量切片 addMVTImageryProvider( options = { style: '', } ) { let mvtImageryProvider = new MVTImageryProvider({ style: options.style, tileSize: 1024, mapboxAccessToken: 'pk.eyJ1IjoibHVrYXNtYXJ0aW5lbGxpIiwiYSI6ImNpem85dmhwazAyajIyd284dGxhN2VxYnYifQ.HQCmyhEXZUTz3S98FMrVAQ', }); this.map.scene.globe.baseColor = Cesium.Color.fromCssColorString(options.style.layers[0]['paint']['background-color']); this.map.imageryLayers.addImageryProvider(mvtImageryProvider); } //添加3Dtiles async loadCesium3DTileSet(e = {}) { let { url: o, id: a = _.uniqueId(), style: l = {}, show: i = !0, customShader: s = void 0, callback } = e; // e = this.map.scene.primitives.add( // new Cesium.Cesium3DTileset({ // url: o, // show: i, // customShader: s, // shadows: !1, // skipLevelOfDetail: !0, // baseScreenSpaceError: 1024, // maximumScreenSpaceError: 64, // skipScreenSpaceErrorFactor: 16, // skipLevels: 1, // immediatelyLoadDesiredLevelOfDetail: !1, // loadSiblings: !1, // cullWithChildrenBounds: !0, // cullRequestsWhileMoving: !0, // cullRequestsWhileMovingMultiplier: 10, // preloadWhenHidden: !0, // preloadFlightDestinations: !0, // preferLeaves: !0, // maximumMemoryUsage: 1024, // progressiveResolutionHeightFraction: 0.5, // dynamicScreenSpaceErrorDensity: 1, // dynamicScreenSpaceErrorFactor: 4, // dynamicScreenSpaceErrorHeightFalloff: 0.25, // foveatedScreenSpaceError: !0, // foveatedConeSize: 0.1, // foveatedMinimumScreenSpaceErrorRelaxation: 0, // foveatedTimeDelay: 0, // luminanceAtZenith: 0, // backFaceCulling: !0, // debugFreezeFrame: !1, // debugColorizeTiles: !1, // debugWireframe: !1, // debugShowBoundingVolume: !1, // debugShowContentBoundingVolume: !1, // debugShowViewerRequestVolume: !1, // debugShowGeometricError: !1, // debugShowRenderingStatistics: !1, // debugShowMemoryUsage: !1, // debugShowUrl: !1, // dynamicScreenSpaceError: !0, // }) // ); const tileset = await Cesium.Cesium3DTileset.fromUrl(o); tileset.newFiberId = 'cesiumBuilding'; this.map.scene.primitives.add(tileset); var boundingSphere = tileset.boundingSphere; var cartographic = Cesium.Cartographic.fromCartesian(boundingSphere.center); var surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0); var offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0); var translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3()); tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation); var m = Cesium.Transforms.eastNorthUpToFixedFrame(surface); const _scale = Cesium.Matrix4.fromUniformScale(4); Cesium.Matrix4.multiply(tileset._root.transform, _scale, m); tileset._root.transform = m; if (callback) { callback(tileset, this.map); } //不能每个模型都跳一此,首次缩放改为所选的回调 // this.map.zoomTo(tileset) // return ( // (e.key = a), // e.readyPromise.then(function (e) { // var t = Cesium.Cartographic.fromCartesian(e.boundingSphere.center), // o = Cesium.Cartesian3.fromRadians(t.longitude, t.latitude, 0); // let a = Cesium.Cartesian3.fromRadians(t.longitude, t.latitude, 0); // t = Cesium.Cartesian3.subtract(a, o, new Cesium.Cartesian3()); // (e.modelMatrix = Cesium.Matrix4.fromTranslation(t)), // l.color && // (e.style = new Cesium.Cesium3DTileStyle({ // color: { // conditions: [['true', l.color]], // }, // })), // l.isEffects && e.tileVisible.addEventListener(r.modelEffect); // }), // a // ); } /**由经纬度拼接geojson * */ getgeojson(data) { let arr = []; if (data.length > 0) { for (var i = 0; i < data.length; i++) { if ( data[i].lon != null && data[i].lat != null && data[i].lon != '' && data[i].lat != '' && parseFloat(data[i].lon) > -180 && parseFloat(data[i].lon) < 180 && parseFloat(data[i].lat) > -90 && parseFloat(data[i].lat) < 90 ) { let point = { coordinates: [data[i].lon, data[i].lat], properties: data[i], }; arr.push(point); } } } return { type: 'FeatureCollection', features: arr.map((item) => { let geometry = { type: 'Point', coordinates: item.coordinates, }; return { type: 'Feature', geometry, properties: item.properties, }; }), }; } getWKTtoGeojson(arry) { return { type: 'FeatureCollection', features: arry.map((item) => { if (!!item.geometrys) { let geometry = WKT.parse(item.geometrys); return { type: 'Feature', geometry, properties: item }; } else { let geometry = WKT.parse(item.supplier); return { type: 'Feature', geometry, properties: item }; } }), }; } //添加geojson point addGeojsonPoint( option = { id: '', data: '', icon: '', text: '', fontSize: '', font: 'Source Han Sans CN', height: 25, width: 25, labelOffset: [0, 20], imgOffset: [0, 0], showBackground: false, backgroundColor: '#ff0000', fillColor: '#ffffff', outlineColor: '', outlineWidth: 1, show: false, style: Cesium.LabelStyle.FILL, //Cesium.LabelStyle.FILL_AND_OUTLINE Cesium.LabelStyle.OUTLINE distanceDisplayCondition: [0, 1000000], } ) { const promise = Cesium.GeoJsonDataSource.load(option.data); //读取geojson数据 promise.then((dataSource) => { dataSource.name = option.id; this.map.dataSources.add(dataSource); const entities = dataSource.entities.values; //获取dataSource中的entitis集合 for (const item in entities) { const entity = entities[item]; entity.newFiberId = option.id; if (option.text !== '') { let timer = setInterval(() => { if (!entity.properties) { return; } else { entity.name = entity.properties[option.text]._value; entity.label.text = entity.name; clearInterval(timer); } }); } entity.billboard = { image: option.icon, //修改图片样式 height: option.height, width: option.width, horizontalOrigin: Cesium.HorizontalOrigin.CENTER, // //相对于对象的原点(注意是原点的位置)的水平位置 verticalOrigin: Cesium.VerticalOrigin.BOTTOM, //相对于对象的原点的垂直位置,BOTTOM时锚点在下,对象在上 pixelOffset: new Cesium.Cartesian2(option.imgOffset[0], option.imgOffset[1]), show: option.show, position: entity.position, distanceDisplayCondition: new Cesium.DistanceDisplayCondition( option.distanceDisplayCondition ? option.distanceDisplayCondition[0] : 0, option.distanceDisplayCondition ? option.distanceDisplayCondition[1] : 1000000 ), }; entity.label = { text: entity.name, //文字描述 font: option.fontSize + ' ' + option.font, //字体样式 fillColor: Cesium.Color.fromCssColorString(option.fillColor), //字体颜色 backgroundColor: Cesium.Color.fromCssColorString(option.backgroundColor), //背景颜色 showBackground: option.showBackground, //是否显示背景颜色 style: option.style, //label样式 outlineColor: Cesium.Color.fromCssColorString(option.outlineColor), outlineWidth: option.outlineWidth, //外轮廓宽度 pixelOffset: new Cesium.Cartesian2(option.labelOffset[0], option.labelOffset[1]), //偏移 //eyeOffset: new Cesium.Cartesian3(0, 0, -10000), show: option.show, distanceDisplayCondition: new Cesium.DistanceDisplayCondition( option.distanceDisplayCondition ? option.distanceDisplayCondition[0] : 0, option.distanceDisplayCondition ? option.distanceDisplayCondition[1] : 1000000 ), // disableDepthTestDistance: Number.POSITIVE_INFINITY, //一个属性,指定从相机到该距离时禁用深度测试的距离 // heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, //贴地设置 }; this.map.entities.add(entity); } }); } //添加geojson polyLine addGeojsonLine( option = { id: '', data: '', text: '', fontSize: '', font: 'Source Han Sans CN', labelOffset: [0, 20], showBackground: false, backgroundColor: '#ff0000', fillColor: '#ffffff', outlineColor: '', outlineWidth: 1, style: Cesium.LabelStyle.FILL, //Cesium.LabelStyle.FILL_AND_OUTLINE Cesium.LabelStyle.OUTLINE material: null, width: 6, distanceDisplayCondition: [0, 1000000], } ) { const promise = Cesium.GeoJsonDataSource.load(option.data); //读取geojson数据 promise.then((dataSource) => { dataSource.name = option.id; this.map.dataSources.add(dataSource); const entities = dataSource.entities.values; //获取dataSource中的entitis集合 for (const item in entities) { const entity = entities[item]; entity.newFiberId = option.id; setTimeout(() => { if (typeof entity === 'function') return; entity.polyline.material = option.material ? option.material : !!entity.properties ? Cesium.Color.fromCssColorString(entity.properties.color._value).withAlpha(0.6) : ''; entity.polyline.width = option.width; entity.polyline.distanceDisplayCondition = new Cesium.DistanceDisplayCondition( option.distanceDisplayCondition ? option.distanceDisplayCondition[0] : 0, option.distanceDisplayCondition ? option.distanceDisplayCondition[1] : 1000000 ); entity.label = { text: option.text, //文字描述 font: option.fontSize + ' ' + option.font, //字体样式 fillColor: Cesium.Color.fromCssColorString(option.fillColor), //字体颜色 backgroundColor: Cesium.Color.fromCssColorString(option.backgroundColor), //背景颜色 showBackground: option.showBackground, //是否显示背景颜色 style: option.style, //label样式 outlineColor: Cesium.Color.fromCssColorString(option.outlineColor), outlineWidth: option.outlineWidth, //外轮廓宽度 verticalOrigin: Cesium.VerticalOrigin.CENTER, //垂直位置 horizontalOrigin: Cesium.HorizontalOrigin.LEFT, //水平位置 pixelOffset: new Cesium.Cartesian2(option.labelOffset[0], option.labelOffset[1]), //偏移 // distanceDisplayCondition: new Cesium.DistanceDisplayCondition(10.0, 20000000.0), scaleByDistance: new Cesium.NearFarScalar(1000, 1, 20000000, 1.5), // eyeOffset: new Cesium.Cartesian3(0, 0, -10000), disableDepthTestDistance: Number.POSITIVE_INFINITY, //一个属性,指定从相机到该距离时禁用深度测试的距离 heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, //贴地设置 }; this.map.entities.add(entity); }, 100); } }); } //添加geojson polygon addGeojsonPolygon( option = { id: '', data: '', text: '', fontSize: '', font: 'Source Han Sans CN', labelOffset: [0, 20], showBackground: false, backgroundColor: '#ff0000', fillColor: '#ffffff', outlineColor: '', outlineWidth: 1, style: Cesium.LabelStyle.FILL, //Cesium.LabelStyle.FILL_AND_OUTLINE Cesium.LabelStyle.OUTLINE material: null, width: 6, strokeColor: '#ffffff', groundHeight: 0, distanceDisplayCondition: [0, 1000000], } ) { const promise = Cesium.GeoJsonDataSource.load(option.data, {}); //读取geojson数据 promise.then((dataSource) => { dataSource.name = option.id; this.map.dataSources.add(dataSource); const entities = dataSource.entities.values; //获取dataSource中的entitis集合 for (const item in entities) { const entity = entities[item]; entity.newFiberId = option.id; setTimeout(() => { if (typeof entity === 'function') return; entity.polygon.material = option.material !== null ? option.material : !!entity.properties ? Cesium.Color.fromCssColorString(entity.properties.color._value).withAlpha(0.2) : ''; entity.polygon.outline = false; entity.polygon.outlineColor = Cesium.Color.fromCssColorString(entity.properties.color._value); entity.polygon.height = option.groundHeight; entity.polygon.distanceDisplayCondition = new Cesium.DistanceDisplayCondition( option.distanceDisplayCondition ? option.distanceDisplayCondition[0] : 0, option.distanceDisplayCondition ? option.distanceDisplayCondition[1] : 1000000 ); entity.label = { text: option.text, //文字描述 font: option.fontSize + ' ' + option.font, //字体样式 fillColor: Cesium.Color.fromCssColorString(option.fillColor), //字体颜色 backgroundColor: Cesium.Color.fromCssColorString(option.backgroundColor), //背景颜色 showBackground: option.showBackground, //是否显示背景颜色 style: option.style, //label样式 outlineColor: Cesium.Color.fromCssColorString(option.outlineColor), outlineWidth: option.outlineWidth, //外轮廓宽度 verticalOrigin: Cesium.VerticalOrigin.CENTER, //垂直位置 horizontalOrigin: Cesium.HorizontalOrigin.LEFT, //水平位置 pixelOffset: new Cesium.Cartesian2(option.labelOffset[0], option.labelOffset[1]), //偏移 // distanceDisplayCondition: new Cesium.DistanceDisplayCondition(10.0, 20000000.0), scaleByDistance: new Cesium.NearFarScalar(1000, 1, 20000000, 1.5), // eyeOffset: new Cesium.Cartesian3(0, 0, -10000), disableDepthTestDistance: Number.POSITIVE_INFINITY, //一个属性,指定从相机到该距离时禁用深度测试的距离 heightReference: Cesium.HeightReference.CLAMP_TO_GROUND, //贴地设置 }; this.map.entities.add(entity); }, 100); } }); } //添加动态水面 dynamicWaterToMap(geojson, waterImg) { geojson.features.forEach((feature) => { let coordinatesArry = feature.geometry.coordinates.flat().flat(); let instance = new Cesium.GeometryInstance({ id: 'dynamicWater', geometry: new Cesium.PolygonGeometry({ polygonHierarchy: new Cesium.PolygonHierarchy(Cesium.Cartesian3.fromDegreesArray(coordinatesArry)), }), }); let primitive = new Cesium.Primitive({ geometryInstances: instance, //可以是实例数组 appearance: new Cesium.EllipsoidSurfaceAppearance({ material: 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: 1000.0, animationSpeed: 0.1, amplitude: 20, specularIntensity: 10, }, }, }), }), }); // 将图元添加到集合 this.map.scene.primitives.add(primitive); }); } //添加geoserver wms addGeoserverWMS( option = { url: '', layerId: '', id: '', } ) { let provider = new Cesium.WebMapServiceImageryProvider({ url: option.url, layers: option.layerId, newFiberId: option.id, parameters: { service: 'WMS', format: 'image/png', transparent: true, }, }); this.map.imageryLayers.addImageryProvider(provider); } //构造抛物线 parabolaFlowInit(option = { id: '', startPosition: '', endPosition: '', height: '', color: '', width: '' }) { let _siglePositions = parabola(option.startPosition, option.endPosition, option.height); let polyline = { positions: _siglePositions, width: option.width, material: new Cesium.LineFlowMaterialProperty({ color: Cesium.Color.fromCssColorString(option.color), speed: 5, percent: 0.5, gradient: 0.01, }), }; // this.map.entities.add({ // polyline: { // width: option.width, // newFiberId: option.id, // positions: _siglePositions, // material: Cesium.Color.fromCssColorString(option.color1), // }, // }); this.map.entities.add({ polyline: polyline, newFiberId: option.id, }); function parabola(startPosition, endPosition, height = 0, count = 50) { //方程 y=-(4h/L^2)*x^2+h h:顶点高度 L:横纵间距较大者 let result = []; height = Math.max(+height, 100); count = Math.max(+count, 50); let diffLon = Math.abs(startPosition[0] - endPosition[0]); let diffLat = Math.abs(startPosition[1] - endPosition[1]); let L = Math.max(diffLon, diffLat); let dlt = L / count; if (diffLon > diffLat) { //base on lon let delLat = (endPosition[1] - startPosition[1]) / count; if (startPosition[0] - endPosition[0] > 0) { dlt = -dlt; } for (let i = 0; i < count; i++) { let h = height - (Math.pow(-0.5 * L + Math.abs(dlt) * i, 2) * 4 * height) / Math.pow(L, 2); let lon = startPosition[0] + dlt * i; let lat = startPosition[1] + delLat * i; let point = new Cesium.Cartesian3.fromDegrees(lon, lat, h); result.push(point); } } else { //base on lat let delLon = (endPosition[0] - startPosition[0]) / count; if (startPosition[1] - endPosition[1] > 0) { dlt = -dlt; } for (let i = 0; i < count; i++) { let h = height - (Math.pow(-0.5 * L + Math.abs(dlt) * i, 2) * 4 * height) / Math.pow(L, 2); let lon = startPosition[0] + delLon * i; let lat = startPosition[1] + dlt * i; let point = new Cesium.Cartesian3.fromDegrees(lon, lat, h); result.push(point); } } return result; } } //点击事件 mapClickEvent(callback) { //点击地图事件 let handler = new Cesium.ScreenSpaceEventHandler(this.map.scene.canvas); handler.setInputAction((click) => { // 屏幕坐标转世界坐标——关键点 let ellipsoid = this.map.scene.globe.ellipsoid; let cartesian = this.map.camera.pickEllipsoid(click.position, ellipsoid); if (cartesian) { //判断点击的是否是地球 //将笛卡尔坐标转换为地理坐标 let cartographic = Cesium.Cartographic.fromCartesian(cartesian); //将弧度转为度的十进制度表示 let lon = Cesium.Math.toDegrees(cartographic.longitude); let lat = Cesium.Math.toDegrees(cartographic.latitude); let pick = this.map.scene.pick(click.position); if (Cesium.defined(pick) && pick.id.id) { let position = cartesian; let point = [lon, lat]; let feature = pick.id; if (typeof callback === 'function') callback(position, point, feature); } } }, Cesium.ScreenSpaceEventType.LEFT_CLICK); } //创建弹窗 createPopup(option = { element: '', position: '' }) { let self = this; let position = Cesium.Cartesian3.fromDegrees(option.position[0], option.position[1], option.position[2]); let bubble = document.getElementById(option.element); let winpos = self.map.scene.cartesianToCanvasCoordinates(position); let poph = bubble.offsetHeight; bubble.style.left = winpos.x + 'px'; bubble.style.top = winpos.y - poph + 'px'; //self.map.scene.postRender.addEventListener(function (e) {}); //相机移动开始事件 // this.map.scene.camera.moveStart.addEventListener(() => { this.removeHandler = this.map.scene.postRender.addEventListener(() => { if (position) { winpos = self.map.scene.cartesianToCanvasCoordinates(position); bubble = document.getElementById(option.element); if (!bubble) return; poph = bubble.offsetHeight; bubble.style.left = winpos.x + 'px'; bubble.style.top = winpos.y - poph + 'px'; } }); //}); //相机移动结束事件 // this.map.scene.camera.moveEnd.addEventListener(() => { // console.log('end'); // this.removeHandler.call(); // }); } setVisibility(id, visible) { let selectedLayer = this.map.entities.values.filter((item) => item.newFiberId == id); if (!selectedLayer.length) return; selectedLayer.forEach((entity) => { entity.show = visible; if (entity.billboard) { entity.billboard.show._value = visible; } if (entity.label) { entity.label.show._value = visible; } }); } removeLayer(id) { let selectedLayer = this.map.entities.values.filter((item) => item.newFiberId == id); if (!selectedLayer.length) return; selectedLayer.forEach((entity) => { this.map.entities.remove(entity); }); let selectedSource = this.map.dataSources.getByName(id); if (!selectedSource.length) return; this.map.dataSources.remove(selectedSource[0]); } }