赞
踩
图中效果源代码在下面的封装栏中
- viewer = new Cesium.Viewer('cesiumContainer',{
- // terrainProvider: Cesium.createWorldTerrain(),
- // animation: false, // 控制场景动画的播放速度控件
- // baseLayerPicker: true, // 底图切换控件
- // baselLayerPicker:false,// 将图层选择的控件关掉,才能添加其他影像数据
- // // fullscreenButton: false, // 全屏控件
- // geocoder: false, // 地理位置查询定位控件
- // homeButton: true, // 默认相机位置控件
- // timeline: false, // 时间滚动条控件
- // infoBox: false, //是否显示信息框
- // sceneModePicker: false, //是否显示3D/2D选择器
- // selectionIndicator: false, // 点击点绿色弹出 是否显示选取指示器组件
- // sceneMode: Cesium.SceneMode.SCENE3D, //设定3维地图的默认场景模式:Cesium.SceneMode.SCENE2D、Cesium.SceneMode.SCENE3D、Cesium.SceneMode.MORPHING
- // navigationHelpButton: false, // 默认的相机控制提示控件
- // scene3DOnly: true, // 每个几何实例仅以3D渲染以节省GPU内存
- // navigationInstructionsInitiallyVisible: false,
- // showRenderLoopErrors: false, //是否显示渲染错误
- // orderIndependentTranslucency:false,//设置背景透明
-
- });
添加点位的数据格式
- poin : [{id:'12321321' , name: "北京西路测试点", type: "固定枪机", state: "在线", position: { x: 116.4568, y: 39.8926} ,text:'X'},
- {id:'43244324' , name: "阿乐修理厂门口", type: "固定枪机", state: "在线", position: { x: 116.4568, y: 39.8944 } ,text:'+'},
- {id:'43764324', name: "裕华路加油站", type: "固定枪机", state: "在线", position: { x: 116.4566, y: 39.8923 } ,text:'?'},
- {id:'437543345', name: "康佳大药房", type: "固定枪机", state: "在线", position: { x: 116.4513, y: 39.8923 } ,text:'!'},],
-
添加点位先上代码(class封装)
- //加载点
- dragEntity(){
- let drag = new DragEntity({
- viewer:this.$store.state.viewer,
- })
- let _this = this
- // this.poin = [{id:234,position:[122.8,39.9],text:"L"},{id:432,position:[122,39],text:"C"}]
- this.poin.forEach(item => {
- let entity = drag.addEntity(item);
- _this.poinEntity[item.id] = entity;
- })
- },
-
- /**
- * @param {Viewer} viewer
- *
- */
- export default class DragEntity{
- constructor(val){
- this.viewer = val.viewer,
- }
- addEntity(value){
- //数据格式{id:543595234324_432423,position:[122.8,39.9],text:"L"}
- let pinBuilder = new Cesium.PinBuilder();
- let poin = this.viewer.entities.add({
- id:value.id,
- name: value.name,
- position: Cesium.Cartesian3.fromDegrees(value.position.x, value.position.y),
- billboard: {
- image: pinBuilder.fromText(value.text,Cesium.Color.ROYALBLUE, 48).toDataURL(),
- verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
- },
- monitoItems:{
- data:value
- },
- });
- return poin
- }
-
- }
解读一下,我们封装了一个class类,将添加点的方法封装到类中方便调用,我们用“billboard”方法与cesium中PinBuilder来进行添加目标点,"PinBuilder"不会的可以看一下官网https://sandcastle.cesium.com/?src=Map%20Pins.html&label=All,然后我们将创建好的实体,return出来,用一个对象来进行接收,用对象的目的就是为了以后方便查找。来看一眼效果
- leftDownAction(){
- let viewer = this.$store.state.viewer
- this.handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
- let _this = this
- let id
- _this.handler.setInputAction(function (movement) {
- let pick = viewer.scene.pick(movement.position);
- if (Cesium.defined(pick) && (pick.id.id) ) {
- // _this.leftDownFlag = true;
- id= pick.id.id;
- console.log(id)
- }
-
- }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
-
- },
代码解读,我们先创建一个LEFT_CLICK 事件,返回值为经纬度,运用 viewer.scene.pick判断拿到实体,打印到控制台;
- export default class Bubble {
- constructor(val){
- this.viewer = val.viewer
- this.div=document.createElement("div");
- // this.addDynamicLabel({id:1,position:val.position,title:"cl弹窗"});
- }
- addDynamicLabel(data){
- let div = this.div
- div.id = data.id;
- // div.style.display="inline"
- div.style.position = "absolute";
- div.style.width = "300px";
- div.style.height = "30px";
- let HTMLTable = `
- <div style="background:#00ffef66;height:200px;border:"1px soild #08f8a7">${data.text}
- <div style="">
- </div>
- `;
- div.innerHTML = HTMLTable;
- this.viewer.cesiumWidget.container.appendChild(div);
- let gisPosition = data.position._value
- this.viewer.scene.postRender.addEventListener(() => {
- const canvasHeight = this.viewer.scene.canvas.height;
- const windowPosition = new Cesium.Cartesian2();
- Cesium.SceneTransforms.wgs84ToWindowCoordinates(
- this.viewer.scene,
- gisPosition,
- windowPosition
- );
- div.style.bottom = canvasHeight - windowPosition.y +220 + "px";
- const elWidth = div.offsetWidth;
- div.style.left = windowPosition.x - elWidth / 2 + "px";
- }, this);
- }
- clearDiv(id){
- if(this.div){
- var parent = this.div.parentElement;
- parent.removeChild(this.div);
- // this.div.removeNode(true);
- this.viewer.scene.postRender.removeEventListener(this.addDynamicLabel,this)
- }
-
- }
- }
修改点击事件代码
- import Bubble from './bubble/index.js'
- leftDownAction(){
- let viewer = this.$store.state.viewer
- let bubble = new Bubble({
- viewer:viewer
- })
- this.handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
- let _this = this
- let id
- _this.handler.setInputAction(function (movement) {
- let pick = viewer.scene.pick(movement.position);
- if (Cesium.defined(pick) && (pick.id.id) ) {
- // _this.leftDownFlag = true;
- id= pick.id.id;
- let entiy = this.poinEntity[id];
- bubble.addDynamicLabel(entiy);
- }else{
- bubble.clearDiv();
- }
-
- }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
-
- },
第四步的完整解读在cesium 自定义动态标记_cesium 标记特效_GIS-CL的博客-CSDN博客 cesium自定义标记中,本文不做多讲解。当点击时显示弹窗,当点击空白初,删除弹窗。
- import Bubble from './bubble/index.js'
- import DragEntity from './dragentity.js'
- data(){
- return{
- fullSizenum:'fullSize',
- poinEntity:{},
- poin : [{id:'12321321' , name: "北京西路测试点", type: "固定枪机", state: "在线", position: { x: 116.4568, y: 39.8926} ,text:'X'},
- {id:'43244324' , name: "阿乐修理厂门口", type: "固定枪机", state: "在线", position: { x: 116.4568, y: 39.8944 } ,text:'+'},
- {id:'43764324', name: "裕华路加油站", type: "固定枪机", state: "在线", position: { x: 116.4566, y: 39.8923 } ,text:'?'},
- {id:'437543345', name: "康佳大药房", type: "固定枪机", state: "在线", position: { x: 116.4513, y: 39.8923 } ,text:'!'},],
- }
- },
- mounted(){
- this.dragEntity()
- this.leftDownAction()
- },
- methods:{
- leftDownAction(){
- let viewer = this.$store.state.viewer
- this.handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
- let _this = this
- let id
- _this.handler.setInputAction(function (movement) {
- let pick = viewer.scene.pick(movement.position);
- if (Cesium.defined(pick) && (pick.id.id) ) {
- // _this.leftDownFlag = true;
- id= pick.id.id;
- _this.bubble(id)
- }else{
- // console.log(_this.bubbles)
- if(_this.bubbles){
- _this.bubbles.windowClose()
- }
-
- }
-
- }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
-
- },
- bubble(id){
- if(this.bubbles){
- this.bubbles.windowClose()
- }
- console.log(this.poinEntity[id])
- this.bubbles = new Bubble(Object.assign(this.poinEntity[id],{
- viewer:this.$store.state.viewer
- }))
-
- },
- //加载点
- dragEntity(){
- let drag = new DragEntity({
- viewer:this.$store.state.viewer,
- })
- let _this = this
- // this.poin = [{id:234,position:[122.8,39.9],text:"L"},{id:432,position:[122,39],text:"C"}]
- this.poin.forEach(item => {
- let entity = drag.addEntity(item);
- _this.poinEntity[item.id] = entity;
- })
- },
- }
-
- /**
- * @param {Viewer} viewer
- *
- */
- export default class DragEntity{
- constructor(val){
- this.viewer = val.viewer,
- }
- addEntity(value){
- let pinBuilder = new Cesium.PinBuilder();
- let poin = this.viewer.entities.add({
- id:value.id,
- name: value.name,
- position: Cesium.Cartesian3.fromDegrees(value.position.x, value.position.y),
- billboard: {
- image: pinBuilder.fromText(value.text,Cesium.Color.ROYALBLUE, 48).toDataURL(),
- verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
- },
- monitoItems:{
- data:value
- },
- });
- return poin
- }
-
- }
- /**
- * @descripion:
- * @param {Viewer} viewer
- * @param {Cartesian2} position
- * @param {String} title
- * @param {String} id
- * @return {*}
- */
-
- import Vue from "vue";
- import Label from "./index.vue";
- let WindowVm = Vue.extend(Label);
- export default class Bubble {
-
- constructor(val) {
- console.log(val.monitoItems.data.name)
- this.viewer = val.viewer;
- // this.height = val.height;
- this.position = val.position._value;
- let title = val.monitoItems.data.name;
- let state = val.monitoItems.data.state;
- let id = val.id
- this.vmInstance = new WindowVm({
- propsData: {
- title,
- state,
- id
- }
- }).$mount(); //根据模板创建一个面板
-
- this.vmInstance.closeEvent = e => {
- this.windowClose();
- }
-
- val.viewer.cesiumWidget.container.appendChild(this.vmInstance.$el); //将字符串模板生成的内容添加到DOM上
-
- this.addPostRender();
- }
-
- //添加场景事件
- addPostRender() {
- this.viewer.scene.postRender.addEventListener(this.postRender, this);
- }
-
- //场景渲染事件 实时更新窗口的位置 使其与笛卡尔坐标一致
- postRender() {
- if (!this.vmInstance.$el || !this.vmInstance.$el.style) return;
- const canvasHeight = this.viewer.scene.canvas.height;
- const windowPosition = new Cesium.Cartesian2();
- Cesium.SceneTransforms.wgs84ToWindowCoordinates(
- this.viewer.scene,
- this.position,
- windowPosition
- );
- this.vmInstance.$el.style.bottom =
- canvasHeight - windowPosition.y +260+ "px";
- const elWidth = this.vmInstance.$el.offsetWidth;
- this.vmInstance.$el.style.left = windowPosition.x - elWidth / 2 +110 + "px";
-
- const camerPosition = this.viewer.camera.position;
- let height = this.viewer.scene.globe.ellipsoid.cartesianToCartographic(camerPosition).height;
- height += this.viewer.scene.globe.ellipsoid.maximumRadius;
- if((!(Cesium.Cartesian3.distance(camerPosition,this.position) > height))&&this.viewer.camera.positionCartographic.height<50000000){
- this.vmInstance.$el.style.display = "block";
- }else{
- this.vmInstance.$el.style.display = "none";
- }
- }
- //关闭
- windowClose() {
- if(this.vmInstance){
- this.vmInstance.$el.remove();
- this.vmInstance.$destroy();
- }
- //this.vmInstance.$el.style.display = "none"; //删除dom
- this.viewer.scene.postRender.removeEventListener(this.postRender, this); //移除事件监听
- }
- }
index.vue
- <template>
- <div :id="id" class="box">
- <div class="pine"></div>
- <div class="box-wrap">
- <div class="close" @click="closeClick">X</div>
- <div class="area">
- <div class="area-title fontColor">{{ title }}</div>
-
- </div>
- <div class="content">
- <div class="data-li">
- <div class="data-label textColor">状态:</div>
- <div class="data-value">
- <span class="label-num yellowColor">{{state}}</span>
- </div>
- </div>
- <div class="data-li">
- <div class="data-label textColor">实时水位:</div>
- <div class="data-value">
- <span class="label-num yellowColor">100</span>
- <span class="label-unit textColor">m³/s</span>
- </div>
- </div>
- </div>
- </div>
-
- <!-- <img src="./layer_border.png" alt="Norway"> -->
- </div>
- </template>
-
- <script>
- export default {
- name: "DynamicLabel",
- data() {
- return {
- show: true,
- };
- },
- props: {
- title: {
- type: String,
- default: "标题",
- },
- id: {
- type: String,
- default: "001",
- },
- state:{
- type: String,
- default: "001",
- }
- },
- methods:{
- closeClick(){
- if(this.closeEvent){
- this.closeEvent();
- }
- }
- }
- };
- </script>
-
-
- <style lang="scss">
- .box {
- width: 200px;
- position: relative;
- bottom: 0;
- left: 0;
- }
- .close{
- position: absolute;
- color: #fff;
- top: 1px;
- right: 10px;
- text-shadow: 2px 2px 2px #022122;
- cursor: pointer;
- animation: fontColor 1s;
- }
- .box-wrap {
- position: absolute;
- left: 21%;
- top: 0;
- width: 100%;
- height: 163px;
- border-radius: 50px 0px 50px 0px;
- border: 1px solid #38e1ff;
- background-color: #38e1ff4a;
- box-shadow: 0 0 10px 2px #29baf1;
- animation: slide 2s;
- }
- .box-wrap .area {
- position: absolute;
- top: 20px;
- right: 0;
- width: 95%;
- height: 30px;
- background-image: linear-gradient(to left, #4cdef9, #4cdef96b);
- border-radius: 30px 0px 0px 0px;
- animation: area 1s;
- }
- .pine {
- position: absolute;
- // left: 0;
- // bottom: -83px;
- width: 100px;
- height: 100px;
- box-sizing: border-box;
- line-height: 120px;
- text-indent: 5px;
- }
-
- .pine::before {
- content: "";
- position: absolute;
- left: 0;
- bottom: -83px;
- width: 40%;
- height: 60px;
- box-sizing: border-box;
- border-bottom: 1px solid #38e1ff;
- transform-origin: bottom center;
- transform: rotateZ(135deg) scale(1.5);
- animation: slash 0.5s;
- filter: drop-shadow(1px 0px 2px #03abb4);
- /* transition: slash 2s; */
- }
-
- .area .area-title {
- text-align: center;
- line-height: 30px;
- }
- .textColor {
- font-size: 14px;
- font-weight: 600;
- color: #ffffff;
- text-shadow: 1px 1px 5px #002520d2;
- animation: fontColor 1s;
- }
- .yellowColor {
- font-size: 14px;
- font-weight: 600;
- color: #f09e28;
- text-shadow: 1px 1px 5px #002520d2;
- animation: fontColor 1s;
- }
-
- .fontColor {
- font-size: 16px;
- font-weight: 800;
- color: #ffffff;
- text-shadow: 1px 1px 5px #002520d2;
- animation: fontColor 1s;
- }
- .content {
- padding: 55px 10px 10px 10px;
- }
- .content .data-li {
- display: flex;
- }
-
- @keyframes fontColor {
- 0% {
- color: #ffffff00;
- text-shadow: 1px 1px 5px #00252000;
- }
- 40% {
- color: #ffffff00;
- text-shadow: 1px 1px 5px #00252000;
- }
- 100% {
- color: #ffffff;
- text-shadow: 1px 1px 5px #002520d2;
- }
- }
-
- @keyframes slide {
- 0% {
- border: 1px solid #38e1ff00;
- background-color: #38e1ff00;
- box-shadow: 0 0 10px 2px #29baf100;
- }
-
- 100% {
- border: 1px solid #38e1ff;
- background-color: #38e1ff4a;
- box-shadow: 0 0 10px 2px #29baf1;
- }
- }
- @keyframes area {
- 0% {
- width: 0%;
- }
- 25% {
- width: 0%;
- }
-
- 100% {
- width: 95%;
- }
- }
-
- /* img{
- position:absolute;
- left:30%;
- top:0;
- width: 100%;
- box-shadow: 0 0 10px 2px #29baf1;
- } */
-
- @keyframes slash {
- 0% {
- transform: rotateZ(135deg) scale(0);
- }
-
- 100% {
- transform: rotateZ(135deg) scale(1.5);
- }
- }
- </style>
然后在封装栏中第一步调用即可,最终效果与展示效果一样。
————————————————
原文链接:https://blog.csdn.net/weixin_46730573/article/details/119852888
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。