cesium canvas广告牌
在有些业务中,对场景中的广告牌样式要求比较高,需要动态显示一些数据,这个时候,我们可以通过将复杂背景样式制作成图片,通过canvas绘制图片和动态数据,从而达到比较好的显示效果。
1 CanvasMarker 类封装
CanvasMarker.js
/** @Description:* @Author: maizi* @Date: 2022-05-27 11:36:22* @LastEditTime: 2024-07-23 15:34:06* @LastEditors: maizi*/
const merge = require('deepmerge')const defaultStyle = {scale: 0.2,text: '0.0'
}
const monitorPanel = require('@/assets/img/monitorPanel.png')class CanvasMarker {constructor(viewer, coords, options = {}) {this.viewer = viewer;this.coords = coords;this.options = options;this.props = this.options.props;this.baseHeight = this.coords[2] || 10;this.style = merge(defaultStyle, this.options.style || {});this.entity = null;this.canvas = nullthis.init();}init() {let img = new Image();img.src = monitorPanel;img.onload = ()=> {this.picture = img;this.canvas = this.createCanvas()}this.entity = new Cesium.Entity({type: "canvas_point",props: this.props,position:Cesium.Cartesian3.fromDegrees(this.coords[0], this.coords[1], this.baseHeight),billboard: {image: new Cesium.CallbackProperty(() => {return this.canvas.toDataURL("image/png");}),scale:new Cesium.CallbackProperty(() => {return this.style.scale}),color: new Cesium.Color(1, 1, 1),disableDepthTestDistance: Number.POSITIVE_INFINITY,},});}createCanvas() {let canvas = null;if (this.canvas) {canvas = this.canvas} else {canvas = document.createElement("canvas");canvas.width = 512;canvas.height = 329;}let ctx = canvas.getContext("2d");ctx.clearRect(0, 0, canvas.width, canvas.height);ctx.drawImage(this.picture, 0, 0);ctx.fillStyle = "rgb(255, 255, 255)",ctx.font = "80px sans-serif",ctx.textBaseline = "middle",ctx.fillText("温度:", 50, canvas.height / 2);ctx.fillText(this.style.text, 270, canvas.height / 2);ctx.fillText("℃", 380, canvas.height / 2);// // 导出canvas为图片// var dataURL = canvas.toDataURL("image/png");// var link = document.createElement('a');// link.download = 'canvas-image.png';// link.href = dataURL;// link.click();return canvas;}setSelect(enabled) {if (enabled) {this.addPoint()} else {this.removePoint()}}addPoint() {this.point = new Cesium.Entity({position: Cesium.Cartesian3.fromDegrees(this.coords[0], this.coords[1], this.baseHeight),point: {color: Cesium.Color.DARKBLUE.withAlpha(.4),pixelSize: 6,outlineColor: Cesium.Color.YELLOW.withAlpha(.8),outlineWidth: 4,disableDepthTestDistance: Number.POSITIVE_INFINITY} }); this.viewer.entities.add(this.point)}removePoint() {if (this.point) {this.viewer.entities.remove(this.point)this.point = null}}updateStyle(style) {this.style = merge(this.style, style || {});this.createCanvas()}
}export {CanvasMarker
}
2 完整示例代码
MapWorks.js
import GUI from 'lil-gui';
// 初始视图定位在中国
import { CanvasMarker } from './CanvasMarker'Cesium.Camera.DEFAULT_VIEW_RECTANGLE = Cesium.Rectangle.fromDegrees(90, -20, 110, 90);
//天地图key
const key = '39673271636382067f0b0937ab9a9677'let viewer = null;
let eventHandler = null;
let canvasLayer = null
let canvasList = []
let selectGraphic = null
let gui = nullfunction initMap(container) {viewer = new Cesium.Viewer(container, {animation: false,baseLayerPicker: false,fullscreenButton: false,geocoder: false,homeButton: false,infoBox: false,sceneModePicker: false,selectionIndicator: false,timeline: false,navigationHelpButton: false, scene3DOnly: true,orderIndependentTranslucency: false,contextOptions: {webgl: {alpha: true}}})viewer._cesiumWidget._creditContainer.style.display = 'none'viewer.scene.fxaa = trueviewer.scene.postProcessStages.fxaa.enabled = trueif (Cesium.FeatureDetection.supportsImageRenderingPixelated()) {// 判断是否支持图像渲染像素化处理viewer.resolutionScale = window.devicePixelRatio}// 移除默认影像removeAll()// 地形深度测试viewer.scene.globe.depthTestAgainstTerrain = true// 背景色viewer.scene.globe.baseColor = new Cesium.Color(0.0, 0.0, 0.0, 0)// 太阳光照viewer.scene.globe.enableLighting = true;// 初始化图层initLayer()// 鼠标事件initClickEvent()//调试window.viewer = viewer
}function initClickEvent() {eventHandler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);initLeftClickEvent()initMouseMoveEvent()
}function initLeftClickEvent() {eventHandler.setInputAction((e) => {if (selectGraphic) {selectGraphic.setSelect(false)selectGraphic = null}if (gui) {gui.destroy()}let pickedObj = viewer.scene.pick(e.position);if (pickedObj && pickedObj.id) {if (pickedObj.id.type === 'canvas_point') {selectGraphic = getGraphicById(pickedObj.id.id)if (selectGraphic) {selectGraphic.setSelect(true)initGui()}}}},Cesium.ScreenSpaceEventType.LEFT_CLICK)
}function initMouseMoveEvent() {eventHandler.setInputAction((e) => {const pickedObj = viewer.scene.pick(e.endPosition);if (pickedObj && pickedObj.id) {if (pickedObj.id.type === 'canvas_point') {// 改变鼠标状态viewer._element.style.cursor = "";document.body.style.cursor = "pointer";} else {viewer._element.style.cursor = "";document.body.style.cursor = "default";}} else {viewer._element.style.cursor = "";document.body.style.cursor = "default";}},Cesium.ScreenSpaceEventType.MOUSE_MOVE)
}function getGraphicById(id) {let graphic = nullfor (let i = 0; i < canvasList.length; i++) {if (canvasList[i].entity.id === id) {graphic = canvasList[i]break} }return graphic
}
function initGui() {let params = {...selectGraphic.style}gui = new GUI()let layerFolder = gui.title('参数设置')layerFolder.add(params, 'scale', 0.1, 2).step(0.1).onChange(function (value) {selectGraphic.updateStyle(params)})
}function addTdtLayer(options) {let url = `https://t{s}.tianditu.gov.cn/DataServer?T=${options.type}&x={x}&y={y}&l={z}&tk=${key}`const layerProvider = new Cesium.UrlTemplateImageryProvider({url: url,subdomains: ['0','1','2','3','4','5','6','7'],tilingScheme: new Cesium.WebMercatorTilingScheme(),maximumLevel: 18});viewer.imageryLayers.addImageryProvider(layerProvider);
}function initLayer() {addTdtLayer({type: 'img_w'})addTdtLayer({type: 'cia_w'})canvasLayer = new Cesium.CustomDataSource('canvasMarker')viewer.dataSources.add(canvasLayer)}function loadCanvasMarker(points) {points.forEach(item => {const canvasMarker = new CanvasMarker(viewer, item)canvasList.push(canvasMarker)canvasLayer.entities.add(canvasMarker.entity)});viewer.flyTo(canvasLayer)updateText()
}function updateText() {setInterval(()=>{canvasList.forEach((item) => {const text = Math.floor(30 * Math.random())item.updateStyle({text: text})})}, 2000)
}function removeAll() {viewer.imageryLayers.removeAll();
}function destroy() {viewer.entities.removeAll();viewer.imageryLayers.removeAll();viewer.destroy();
}export {initMap,loadCanvasMarker,destroy
}
CanvasMarker.vue
<!--* @Description: * @Author: maizi* @Date: 2023-04-07 17:03:50* @LastEditTime: 2023-04-11 18:07:29* @LastEditors: maizi
--><template><div id="container"></div>
</template><script>
import * as MapWorks from './js/MapWorks'
export default {name: 'CanvasMarker',mounted() {this.init();},methods:{init(){let container = document.getElementById("container");MapWorks.initMap(container)//创建告警点let points = [[104.074822, 30.659807, 60],[104.076822, 30.653807, 60],[104.075822, 30.652807, 60],[104.072822, 30.654807, 60]];MapWorks.loadCanvasMarker(points)}},beforeDestroy(){//实例被销毁前调用,页面关闭、路由跳转、v-if和改变key值MapWorks.destroy();}
}
</script><style lang="scss" scoped>
#container{width: 100%;height: 100%;background: rgba(7, 12, 19, 1);overflow: hidden;background-size: 40px 40px, 40px 40px;background-image: linear-gradient(hsla(0, 0%, 100%, 0.05) 1px, transparent 0), linear-gradient(90deg, hsla(0, 0%, 100%, 0.05) 1px, transparent 0);
}</style>
3 运行效果

相关文章:
cesium canvas广告牌
在有些业务中,对场景中的广告牌样式要求比较高,需要动态显示一些数据,这个时候,我们可以通过将复杂背景样式制作成图片,通过canvas绘制图片和动态数据,从而达到比较好的显示效果。 1 CanvasMarker 类封装 …...
使用Floyd算法求解两点间最短距离
Floyd算法 Floyd算法又称为Floyd-Warshell算法,其实Warshell算法是离散数学中求传递闭包的算法,两者的思想是一致的。Floyd算法是求解多源最短路时通常选用的算法,经过一次算法即可求出任意两点之间的最短距离,并且可以处理有负权…...
linux“how_paras.sh“ E212: 无法打开并写入文件
经过一番测试和查找, [6localhost bin]$ find / -name "hello.sh" 2>/dev/null /home/6/bin/hello.sh [6localhost bin]$ ls hello.sh ls: 无法访问hello.sh: 没有那个文件或目录,为什么在/bin文件下却不能打开, [6localhost …...
CSS mask-image 实现边缘淡出过渡效果
使用场景 在生产环境中,遇到一个需求,需要在一个深色风格的大屏页面中,嵌入 Google Maps。为了减少违和感,希望地图四边能够淡出过渡。 这里的“淡出过渡”,关键是淡出,而非降低透明度。 基于 Google Ma…...
电子元器件—电容和电感(一篇文章搞懂电路中的电容和电感)(笔记)(面试考试必备知识点)电容和电感作用、用途、使用、注意事项、特点等(面试必备)-笔记(详解)
作者:Whappy 座右铭:不曾拥有,何来失去! 时间:2024年8月2日08:40:04 一、电容的作用 储能: 电容器通过充电储存电荷在电容板上,形成电场储存电能。当需要释放储存的电能时,电荷…...
2024HDU Contest 5 Problem 5
题目链接 从大到小枚举gcd的值 d d d,以及编号为 d d d的倍数的点, [ d , 2 d , 3 d , … ] [d,2d,3d,\dots] [d,2d,3d,…]。 然后对于任何一条边 ( x , y ) (x,y) (x,y),如果 x x x的子树和 y y y的子树里都有编号为 d d d倍数的点…...
nGQL入门
引言 nGQL(NebulaGraph Query Language)是用于操作 NebulaGraph 的查询语言。它的语法类似于 Cypher,但有自己独特的特性。以下是一些 nGQL 的基本语法和操作示例,以帮助你入门。 基本概念 节点(Vertex)…...
[CP_AUTOSAR]_系统服务_DEM模块(二)功能规范介绍
目录 1、DEM 功能规范描述1.1、Startup behavior1.2、Monitor re-initialization 在前面 《[CP_AUTOSAR]_系统服务_DEM模块(一)》文中,简要介绍了 DEM 模块的功能、与其它模块之间的功能交互,本文将接着介绍 DEM 模块的功能规范。…...
Linux中yum、rpm、apt-get、wget的区别,yum、rpm、apt-get常用命令,CentOS、Ubuntu中安装wget
文章目录 一、常见Linux发行版本二、Linux中yum、rpm、apt-get、wget的区别2.1 yum2.2 rpm2.3 apt-get2.4 wget2.5 总结 三、CentOS中yum的作用3.1 yum清空缓存列表3.2 yum显示信息3.3 yum搜索、查看3.4 yum安装3.5 yum删除、卸载程序3.6 yum包的升级、降级 四、Ubuntu中apt-ge…...
IPython的使用技巧2
关注我,持续分享逻辑思维&管理思维&面试题; 可提供大厂面试辅导、及定制化求职/在职/管理/架构辅导; 推荐专栏《10天学会使用asp.net编程AI大模型》,目前已完成所有内容。一顿烧烤不到的费用,让人能紧跟时代的…...
win10打开程序闪退的解决方法,亲测好用
当我们在使用win10系统的时候,可能会遇到安装某些程序后无法正常使用,一打开就闪退,或者点击右下角图标就消失了,而其他程序却可以正常打开使用。下面小编就来和大家分享亲测好用的win10打开程序闪退的解决办法。 问题原因分析&a…...
木舟0基础学习Java的第二十一天(数据库,MySQL,SQLyog)
数据库 数据库:按照数据结构来组织 存储数据的厂库 数据管理系统(Database Management System,DBMS):一套操作和管理数据库的软件 用于简历 使用 维护数据库 关系型数据库:采用关系模型作为数据组织方式 逻辑结构是一张二维表 由行和列组成…...
python-鼠标绘画线条程序
闲来无聊简单编写了一个绘图小程序。 主要思路 主要是基于Python中的内置模块turtle编写的,简单扩展了一下,通过绑定事件能够达到鼠标绘制、删除、存储已经绘制图案的线条这几个功能。 路径结构 -draw- define.py- main.py- myturtle.py使用 点住鼠…...
【Python实战】如何优雅地实现 PDF 去水印?
话接上篇,自动化处理 PDF 文档,完美实现 WPS 会员功能 小伙伴们更关心的是如何去除 PDF 中的水印~ 今天,就来分享一个超简单的 PDF 去水印方法~ 1. 原理介绍 在上一篇中,我们介绍了如何将 PDF 文档转换成图片,图片…...
Keysight(原Agilent) E4980AL 精密 LCR 表特性与技术指标
Keysight(原Agilent) E4980AL 精密 LCR 表为基础 LCR 表树立了行业标准,可在多个频率范围内提供更佳的精度、速度和通用性。E4980AL 结合了种类繁多的附件,适用于一般研发和生产环境中的各种元件和材料测量。也可通过频率升级而提升投资回报率。 Keysig…...
【运维】Redis主从复制 配置
【运维】Redis主从复制 配置 主库配置Master # 默认情况下,是 启用保护模式的,其他主机的客户端无法连接到 Redis 。当想要其他主机的客户端连接到 Redis 时,需要修改为 no 。protected-mode no 从库配置Slave # replicaof [master主机ip] …...
C++ 微积分 - 求导 - 自动微分(Automatic Differentiation)
C 微积分 - 求导 - 自动微分(Automatic Differentiation) flyfish 自动微分(Automatic Differentiation,简称 AD)是一种用于精确计算函数导数的技术。它结合了符号微分的准确性和数值微分的效率。自动微分的核心思想…...
面试题-每日5道
26.在 Queue 中 poll()和 remove()有什么区别? 相同点:都是删除第一个元素并返回。 不同点:如果没有元素poll()会返回null,而remove()会抛出NoSuchElementException异常 27.哪些集合类是线程安全的? Vector,Stock,Hashtable都是线程安全的&a…...
STM32卡死、跑飞如何调试确定问题
目录 前言 一、程序跑飞原因 二、调试工具 2.1Registers工具 2.2 Memory工具 2.3 Disassembly工具 2.4 Call Stack工具 三、找到程序跑飞位置 方式一、 方式二、 前言 我们初学STM32的时候代码难免会出现疏忽,导致程序跑飞,不再正常运行&#…...
代理模式和Spring MVC
Spring是一个分层的轻量级的开源Java框架。核心是IOC(Inverse of Control 控制反转)和AOP(Aspect Oriented Programming 面向切面编程) AOP 面向切面 AOP (Aspect Orient Programming),直译过来就是 面向切面编程,AOP 是一种编程思想&#x…...
GLIGEN图像空间控制:用边界框实现像素级精准生成
1. GLIGEN:不是又一个“AI画图玩具”,而是图像生成控制权的真正移交你有没有试过对着 Stable Diffusion 的提示词框反复修改半小时,就为了把一只猫准确地放在沙发左边、让咖啡杯稳稳立在桌面上、让窗外的梧桐树只出现在画面右上角——结果生成…...
YOLOv11室内展台飞机模型目标检测数据集-182张-Airplane-1_4_2
YOLOv11室内展台飞机模型目标检测数据集 📊 数据集基本信息 目标类别: [‘airplane’] 中文类别:[‘飞机’] 训练集:159 张 验证集:23 张 测试集:0 张 总计:182 张 📄 data.yaml 配置信息 该数据集提供了data.yaml文件,内容如下: train: ../train/images val: .…...
Java十道高频面试题(一)
Java基础与集合1. HashMap的底层数据结构是什么?(JDK 1.7 vs 1.8)考察点:数据结构演进、哈希冲突解决、扩容死循环问题。参考答案:HashMap在JDK 1.7和1.8中有着本质的区别,主要体现在底层结构和扩容机制上&…...
HoRain云--PHP日期格式化函数date()详解与最佳实践
🎬 HoRain 云小助手:个人主页 ⛺️生活的理想,就是为了理想的生活! ⛳️ 推荐 前些天发现了一个超棒的服务器购买网站,性价比超高,大内存超划算!忍不住分享一下给大家。点击跳转到网站。 目录 ⛳️ 推荐 …...
2026年度能耗监测系统的深度分析与展望
在当前全球可持续发展的大背景下,能耗监测系统的重要性愈发凸显。随着技术的进步和社会对节能减排的需求,2026年度的能耗监测系统将迎来一场技术革命和应用升级。本文将从市场需求、技术现状、未来发展方向及实施策略等多个方面,对2026能耗监…...
芯片巨头并购软件公司:从硬件竞赛到软硬协同的产业变革
1. 行业现象背后的深层逻辑最近和几个在芯片设计公司和EDA软件公司工作的老朋友聊天,大家不约而同地提到了一个趋势:芯片巨头们的手,伸得越来越长了。以前是买IP核、买制造厂,现在则是频频出手,将一家家软件公司收入囊…...
自建链接管理服务OtterLink:从部署到实战的完整指南
1. 项目概述:一个链接管理的“瑞士军刀” 最近在折腾个人知识库和内容分发,发现一个痛点:手头攒了太多链接。技术文章、工具网站、项目仓库、临时笔记链接……散落在浏览器书签、聊天记录、备忘录里,时间一长要么找不到ÿ…...
CV论文工业落地避坑指南:从复现到部署的四大过滤维度
1. 这不是论文清单,而是一份“CV研究者晨间速读指南” 如果你每天打开arXiv、CVPR官网或Twitter刷到一堆标题带“Vision Transformer”“Diffusion”“Multimodal Alignment”的新论文,却总在摘要第一句就卡住——“We propose a novel hierarchical tok…...
别再只用if-else了!用Simulink Relay模块给你的控制逻辑加个‘缓冲带’(附C代码生成分析)
别再只用if-else了!用Simulink Relay模块给你的控制逻辑加个‘缓冲带’(附C代码生成分析) 在嵌入式控制系统的开发中,我们常常需要处理各种阈值判断和状态切换。传统的if-else结构虽然简单直接,但在实际应用中往往会导…...
告别英文界面:RedHat 6.3 桌面环境汉化原理与手动配置详解
从底层机制到实战:RedHat 6.3 桌面环境深度汉化指南 第一次在终端里看到满屏英文报错时,我盯着那个"Permission denied"愣了半天——明明昨天刚装好的系统,怎么连个中文提示都没有?这种经历恐怕是很多国内Linux用户的共…...
