动画设计就业方向和发展前景,企业网站模板优化,个人网站设计界面,网站维护提示怎么做前言#xff1a;今天总结关于point、label、billboard海量数据加载。后续会研究下大量model加载以及大bim(几百G上T)模型记载
海量点加载 弹窗 加载点位时#xff0c;不加载弹窗。点击点位时在加载弹窗#xff0c;及有效的减少加载量#xff0c;优化性能。 const handler …前言今天总结关于point、label、billboard海量数据加载。后续会研究下大量model加载以及大bim(几百G上T)模型记载
海量点加载 弹窗 加载点位时不加载弹窗。点击点位时在加载弹窗及有效的减少加载量优化性能。 const handler new Cesium.ScreenSpaceEventHandler();
handler.setInputAction(function (movement: any) {const pickedLabel viewer.scene.pick(movement.position);if (Cesium.defined(pickedLabel)) {console.log(pickedLabel)staticPoins.some(i {if (i.id pickedLabel.id.id || i.id pickedLabel.id) {changePopWins(i)return true}})}}, Cesium.ScreenSpaceEventType.LEFT_CLICK);function changePopWins(item: Point) {let flag popWins.value.some(i {if (i.id item.id) {i.visible !i.visiblereturn true}})if (!flag) {popWins.value.push({ ...item, visible: true })}
}dom-tag组件
templatediv classcesium-domPoint refelementslot :dataprops.data/slot/div
/template
script langts setup
import * as Cesium from cesium;
import { onMounted, onUnmounted, ref, PropType } from vue;
import type { EalignX, EalignY } from ../typing;
const props defineProps({eventClick: Function,data: Object,trackPos: {type: Object as PropTypeCesium.Cartesian3,},trackEntity: {type: Object as PropTypeCesium.Entity,},alignX: {type: String as PropTypeEalignX,},alignY: {type: String as PropTypeEalignY,},trackCursor: Boolean,
});
const { Viewer } window;
let element refHTMLDivElement | null(null),mousePos: Cesium.Cartesian2,trackCursor props.trackCursor;
const handler new Cesium.ScreenSpaceEventHandler();
const onUpdate () {if (element null) return;let screenPos;if (trackCursor) {screenPos mousePos;} else if (props.trackEntity) {let pos (props.trackEntity.position props.trackEntity.position.getValue(Cesium.JulianDate.now())) ||Cesium.Cartesian3.ZERO;screenPos Cesium.SceneTransforms.wgs84ToWindowCoordinates(Viewer.scene,pos);} else if (props.trackPos) {screenPos Cesium.SceneTransforms.wgs84ToWindowCoordinates(Viewer.scene,props.trackPos);}if (screenPos) {if (element.value) {switch (props.alignX) {case left:element.value.style.left screenPos.x px;break;case center:element.value.style.left screenPos.x element.value.clientWidth * 0.5 px;break;case right:default:element.value.style.left screenPos.x - element.value.clientWidth * 0.5 px;}switch (props.alignY) {case top:element.value.style.top screenPos.y - element.value.clientHeight px;break;case bottom:element.value.style.top screenPos.y px;break;case center:default:element.value.style.top screenPos.y - element.value.clientHeight * 0.5 px;}if (parseFloat(element.value.style.top) (-element.value.clientWidth) || parseFloat(element.value.style.left) (-element.value.clientHeight) || parseFloat(element.value.style.left) (document.body.clientWidth element.value.clientWidth) || parseFloat(element.value.style.top) (document.body.clientHeight element.value.clientHeight)) {element.value.style.display none;}else {element.value.style.display ;}}} else {if (element.value) element.value.style.display none;}
};
onMounted(() {if (trackCursor) {handler.setInputAction((event: any) {let offsetToLeftTop Viewer.container.getBoundingClientRect();mousePos Cesium.Cartesian2.subtract(event.endPosition,new Cesium.Cartesian2(offsetToLeftTop.left, offsetToLeftTop.top),new Cesium.Cartesian2());}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);}Viewer.scene.preUpdate.addEventListener(onUpdate);
});
onUnmounted(() {if (Viewer !Viewer.isDestroyed()) {Viewer.scene.preUpdate.removeEventListener(onUpdate);}handler handler.destroy()
});
/script
style langless scoped
.cesium-domPoint {position: absolute;z-index: 0;
}
/styletemplate v-foritem in popWins :keyitem.idDomTag :trackPositem.pos v-ifitem.visiblePopWin :pointitem tooglePopWintooglePopWin1 //DomTag/template最常用的就是entity 不加载图片以及文字的时候20W的点都没问题虽然帧数就10左右但是流畅度还行 for (let i 0; i 500; i) {for (let j 0; j 400; j) {viewer.entities.add({point: {pixelSize: 5,color: Cesium.Color.BEIGE},position: Cesium.Cartesian3.fromDegrees(103 i * 0.1, 30 j * 0.1)}) }}添加文字后(20K)虽然也是10侦左右但是会感到明显的卡顿 for (let i 0; i 50; i) {for (let j 0; j 400; j) {viewer.entities.add({point: {pixelSize: 5,color: Cesium.Color.BEIGE},label: {text: i},position: Cesium.Cartesian3.fromDegrees(103 i * 0.1, 30 j * 0.1)}) }
}添加图片 图片较小只有179个字节。20k的数据流畅度可以图片越大流畅度越低 viewer.entities.add({point: {pixelSize: 5,color: Cesium.Color.BEIGE},billboard: {image: icons/facility.gif},// label: {// text: i// },position: Cesium.Cartesian3.fromDegrees(103 i * 0.1, 30 j * 0.1)}) 总结entity加载图片越大流畅度越低点越密集流畅度越低。层级越高流畅度越高密度下降。
entity聚合 添加10k聚合功能首次加载时间延长但是加载成功后流畅度显著提高并且entity可以同时添加文字和图片 /* 本质上还是利用的是entity加载还是慢加载时间长 加载完成后性能提升 */ let staticPoins: Point[] []for (let i 0; i 500; i) {for (let j 0; j 200; j) {let obj {visible: false,id: i _ j,onlinetime: 2023-02-21 11:32:22,accountname: ${i}_${j},differentialstate: 7,curH: 474.59999999999997,curB: 30 i * 0.1,curL: 104 0.1 * j,satellitenumber: 50,dopvalue: 0.6000000238418579,delay: 0,reserver1: 153403.172851563,reserver2: NTRIP GNSSInternetRadio/1.4.5,pos: Cesium.Cartesian3.fromDegrees(104.06657490833334, 30.63132543),}obj.pos Cesium.Cartesian3.fromDegrees(obj.curL, obj.curB)staticPoins.push(obj)}}staticPoins.forEach((i, j) {if (j 10000)dataSource.entities.add({id: i.id,point: {pixelSize: 0},label: {text: i.accountname,font: 20px sans-serif,showBackground: true,// verticalOrigin: Cesium.VerticalOrigin.TOP,pixelOffset: new Cesium.Cartesian2(0, -65),distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 10e5),//根据Label与相机的距离来获取或设置Label的近和远像素偏移缩放比例属性// eyeOffset: new Cesium.Cartesian3(0, 7.2, 0)heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND},billboard: {image: icons/facility.gif,scaleByDistance: new Cesium.NearFarScalar(1.5e2, 1, 1.5e7, 0),//根据相机距离缩放下限、下限的值、上限、上限的值width: 16,height: 16,heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,horizontalOrigin: Cesium.HorizontalOrigin.CENTER, // //相对于对象的原点注意是原点的位置的水平位置verticalOrigin: Cesium.VerticalOrigin.BOTTOM,},position: i.pos})})const dataSourcePromise viewer.dataSources.add(dataSource);dataSourcePromise.then(function (dataSource) {const pixelRange 15;const minimumClusterSize 3;const enabled true;dataSource.clustering.enabled enabled; //是否聚合dataSource.clustering.pixelRange pixelRange;dataSource.clustering.minimumClusterSize minimumClusterSize;const pinBuilder new Cesium.PinBuilder();const pin1000 pinBuilder.fromText(1000, Cesium.Color.RED, 48).toDataURL();const pin500 pinBuilder.fromText(100, Cesium.Color.RED, 48).toDataURL();const pin100 pinBuilder.fromText(100, Cesium.Color.RED, 48).toDataURL();const pin50 pinBuilder.fromText(50, Cesium.Color.RED, 48).toDataURL();const pin40 pinBuilder.fromText(40, Cesium.Color.ORANGE, 48).toDataURL();const pin30 pinBuilder.fromText(30, Cesium.Color.YELLOW, 48).toDataURL();const pin20 pinBuilder.fromText(20, Cesium.Color.GREEN, 48).toDataURL();const pin10 pinBuilder.fromText(10, Cesium.Color.BLUE, 48).toDataURL();const singleDigitPins new Array(8);for (let i 0; i singleDigitPins.length; i) {singleDigitPins[i] pinBuilder.fromText(${i 2}, Cesium.Color.VIOLET, 48).toDataURL();}function customStyle() {if (Cesium.defined(removeListener)) {removeListener removeListener();removeListener undefined;} else {removeListener dataSource.clustering.clusterEvent.addEventListener(function (clusteredEntities, cluster) {cluster.label.show false;cluster.billboard.show true;cluster.billboard.id cluster.label.id;cluster.billboard.verticalOrigin Cesium.VerticalOrigin.BOTTOM;if (clusteredEntities.length 1000) {cluster.billboard.image pin1000;} else if (clusteredEntities.length 500) {cluster.billboard.image pin500;} else if (clusteredEntities.length 100) {cluster.billboard.image pin100;} else if (clusteredEntities.length 50) {cluster.billboard.image pin50;} else if (clusteredEntities.length 40) {cluster.billboard.image pin40;} else if (clusteredEntities.length 30) {cluster.billboard.image pin30;} else if (clusteredEntities.length 20) {cluster.billboard.image pin20;} else if (clusteredEntities.length 10) {cluster.billboard.image pin10;} else {cluster.billboard.image singleDigitPins[clusteredEntities.length - 2];}});}const pixelRange dataSource.clustering.pixelRange;dataSource.clustering.pixelRange 0;dataSource.clustering.pixelRange pixelRange;}customStyle();})dom加载 利用坐标点的变化时候改变dom元素的位置 优点自由度高 缺点适合几百以内的数据。 template v-foritem in points :keyitem.idDomTag :trackPositem.posDev :pointitem tooglePopWintooglePopWin //DomTag
/templatePointPrimitiveCollection 加载PointPrimitiveCollection点集合速度快且流畅也是推荐的方式。 缺点只能加载点 let pointPrimitives: Cesium.PointPrimitiveCollection;
pointPrimitives scene.primitives.add(new Cesium.PointPrimitiveCollection()
);
for(let i 0; i 100000; i) {
pointPrimitives.add({id: i.id,pixelSize: 10,color: color,outlineColor: outlineColor,outlineWidth: 0,label: {text: 222},distanceDisplayCondition: new Cesium.DistanceDisplayCondition(5.5e3),position: i.pos,
});
}点位移动 这个方法移动十万个点位很流畅 viewer.scene.preUpdate.addEventListener(animateBillboards);
function animateBillboards() {const moveAmount new Cesium.Cartesian3(100, 0.0, 0.0);const positionScratch new Cesium.Cartesian3();// ts-ignoreconst billboards pointPrimitives._pointPrimitives;const length billboards.length;for (let i 0; i length; i) {const billboard billboards[i];Cesium.Cartesian3.clone(billboard.position, positionScratch);Cesium.Cartesian3.add(positionScratch, moveAmount, positionScratch);billboard.position positionScratch;}
}billoardPrimitives 同上只能加载图片。 let billoardPrimitives: Cesium.BillboardCollection
billoardPrimitives viewer.scene.primitives.add(new Cesium.BillboardCollection({scene: scene,}));
for(let i 0; i 100000; i) {
billoardPrimitives.add({id: i.id,image: icons/facility.gif,width: 10,height: 10,position: i.pos
});
}Primitive和聚合搭配着使用 cesium官方未能提供primitive的聚合方法但是可以用entity的聚合搭配着使用。 CommomSiteTookit
import * as Cesium from cesium;
import { defaultValue } from cesiumtype Option {delay?:number;enabled?: boolean;pixelRange?:number;minimumClusterSize?:number;
}
/*** _v 引入外部创建的Viewer实例(new Cesium.Viewer(...))* myPrimitives 原语集合可以包含页面显示的pointPrimitiveCollection、billboardCollection、labelCollection、primitiveCollection、primitiveCluster* myPrimitiveCluster 自定义原语集群* myBillboardCollection 广告牌集合(站点显示的内容数据)** desc 使用primitiveCollection原语集合与primitiveCluster原语集群处理地图界面显示广告牌billboard数量 10w 级时界面卡顿浏览器崩溃等问题*/
class CommomSiteTookit {static _v: Cesium.Viewer;myPrimitives: Cesium.PrimitiveCollection | null nullmyPrimitiveCluster:any null;myBillboardCollection:Cesium.BillboardCollection|null null;constructor() {}/*** desc 使用commomSiteTookit实例前必须先初始化该实例的_v对象*/init(viewer: Cesium.Viewer) {CommomSiteTookit._v viewer;}/*** param [options] 具有以下属性的对象* param [options.delay800] 防抖处理定时器的time* param [options.enabledtrue] 是否启用集群* param [options.pixelRange15] 用于扩展屏幕空间包围框的像素范围* param [options.minimumClusterSize2] 可集群的屏幕空间对象的最小数量** desc 处理原语集合并实现聚合集群功能方法* return billboardCollection集合可直接往集合里添加广告牌billboard呈现在页面上*/load(options:Option {}) {let billboardCollection new Cesium.BillboardCollection();let labelboardCollection new Cesium.LabelCollection();if (Cesium.defined(this.myPrimitives)) {CommomSiteTookit._v.scene.primitives.remove(this.myPrimitives);}this.myPrimitives CommomSiteTookit._v.scene.primitives.add(new Cesium.PrimitiveCollection());//ts-ignoreconst primitiveCluster new Cesium.PrimitiveCluster();this.myPrimitives this.myPrimitives.add(primitiveCluster);primitiveCluster.delay defaultValue(options.delay, 800);primitiveCluster.enabled defaultValue(options.enabled, true);primitiveCluster.pixelRange defaultValue(options.pixelRange, 15);primitiveCluster.minimumClusterSize defaultValue(options.minimumClusterSize,2);primitiveCluster._billboardCollection billboardCollection;primitiveCluster._initialize(CommomSiteTookit._v.scene);let removeListener:any;let pinBuilder new Cesium.PinBuilder();/* 定义广告牌 fromText显示文字颜色大小 */const pin1000 pinBuilder.fromText(1000, Cesium.Color.RED, 48).toDataURL();const pin500 pinBuilder.fromText(500, Cesium.Color.RED, 48).toDataURL();const pin100 pinBuilder.fromText(100, Cesium.Color.RED, 48).toDataURL();const pin50 pinBuilder.fromText(50, Cesium.Color.RED, 48).toDataURL();const pin40 pinBuilder.fromText(40, Cesium.Color.ORANGE, 48).toDataURL();const pin30 pinBuilder.fromText(30, Cesium.Color.YELLOW, 48).toDataURL();const pin20 pinBuilder.fromText(20, Cesium.Color.GREEN, 48).toDataURL();const pin10 pinBuilder.fromText(10, Cesium.Color.BLUE, 48).toDataURL();/* 数量小于十个的聚合广告牌 */let singleDigitPins new Array(8);for (let i 0; i singleDigitPins.length; i) {singleDigitPins[i] pinBuilder.fromText( (i 2), Cesium.Color.VIOLET, 40).toDataURL();}const _ this;function customStyle() {if (Cesium.defined(removeListener)) {removeListener();removeListener undefined;} else {removeListener primitiveCluster.clusterEvent.addEventListener(function(clusteredEntities:any, cluster:any) {cluster.label.show false;cluster.billboard.show true;cluster.billboard.id cluster.label.id;cluster.billboard.verticalOrigin Cesium.VerticalOrigin.BOTTOM;/* 根据站点(参数)的数量给予对应的广告牌 */if (clusteredEntities.length 1000) {cluster.billboard.image pin1000;} else if (clusteredEntities.length 500) {cluster.billboard.image pin500;} else if (clusteredEntities.length 100) {cluster.billboard.image pin100;} else if (clusteredEntities.length 50) {cluster.billboard.image pin50;} else if (clusteredEntities.length 40) {cluster.billboard.image pin40;} else if (clusteredEntities.length 30) {cluster.billboard.image pin30;} else if (clusteredEntities.length 20) {cluster.billboard.image pin20;} else if (clusteredEntities.length 10) {cluster.billboard.image pin10;} else {cluster.billboard.image singleDigitPins[clusteredEntities.length - 2];}});}// force a re-cluster with the new stylinglet pixelRange primitiveCluster.pixelRange;primitiveCluster.pixelRange 0;primitiveCluster.pixelRange pixelRange;_.myPrimitiveCluster primitiveCluster;}this.myBillboardCollection billboardCollection;// start with custom stylecustomStyle();return billboardCollection;}/*** params enable bool值控制开启或关闭集群* desc 控制集群生效与否*/enableCluster(enable:boolean) {if (Cesium.defined(this.myPrimitiveCluster)) {this.myPrimitiveCluster!.enabled enable;}}/*** params id 站点ID* return 返回可操作的广告牌[siteBillboard.image xxxx]* desc 根据id在集合中获取指定站点广告牌*/getSiteBillboardById(id: string) {if (!Cesium.defined(this.myBillboardCollection)) return undefined;const _b this.myBillboardCollection!;const l _b.length;let siteBillboard undefined;for (let i 0; i l; i) {if (id _b.get(i).id) {siteBillboard _b.get(i);break;}}return siteBillboard;}/*** desc 删除所有站点广告牌*/removeAll() {if (Cesium.defined(this.myPrimitives)) {CommomSiteTookit._v.scene.primitives.remove(this.myPrimitives);}}/*** params show bool值 控制显示或隐藏* desc 隐藏或显示所有站点广告牌*/showStatus(show true) {this.myPrimitives!.show show;}/*** desc 根据id删除指定站点广告牌*/remove(id:string) {const billboard this.getSiteBillboardById(id);billboard this.myBillboardCollection!.remove(billboard);}/*** desc 销毁(目前退出页面时直接viewer销毁)*/destroy() {this.myPrimitives null;this.myPrimitiveCluster null;this.myBillboardCollection null;// this._v.scene.primitives.destroy()}
}export default new CommomSiteTookit(); CommomSiteTookit.init(viewer)const data CommomSiteTookit.load({enabled: true,delay: 1200,pixelRange: 20});for(let i 0; i 100000; i) {data.add({image: icons/facility.gif,scaleByDistance: new Cesium.NearFarScalar(1.5e2, 1, 1.5e7, 0.2),width: 16,height: 16,position: i.pos,id: i.id});
}