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…...
工程地质软件市场:发展现状、趋势与策略建议
一、引言 在工程建设领域,准确把握地质条件是确保项目顺利推进和安全运营的关键。工程地质软件作为处理、分析、模拟和展示工程地质数据的重要工具,正发挥着日益重要的作用。它凭借强大的数据处理能力、三维建模功能、空间分析工具和可视化展示手段&…...
Neo4j 集群管理:原理、技术与最佳实践深度解析
Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

VM虚拟机网络配置(ubuntu24桥接模式):配置静态IP
编辑-虚拟网络编辑器-更改设置 选择桥接模式,然后找到相应的网卡(可以查看自己本机的网络连接) windows连接的网络点击查看属性 编辑虚拟机设置更改网络配置,选择刚才配置的桥接模式 静态ip设置: 我用的ubuntu24桌…...
Python Einops库:深度学习中的张量操作革命
Einops(爱因斯坦操作库)就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库,用类似自然语言的表达式替代了晦涩的API调用,彻底改变了深度学习工程…...

R 语言科研绘图第 55 期 --- 网络图-聚类
在发表科研论文的过程中,科研绘图是必不可少的,一张好看的图形会是文章很大的加分项。 为了便于使用,本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中,获取方式: R 语言科研绘图模板 --- sciRplothttps://mp.…...
离线语音识别方案分析
随着人工智能技术的不断发展,语音识别技术也得到了广泛的应用,从智能家居到车载系统,语音识别正在改变我们与设备的交互方式。尤其是离线语音识别,由于其在没有网络连接的情况下仍然能提供稳定、准确的语音处理能力,广…...
基于鸿蒙(HarmonyOS5)的打车小程序
1. 开发环境准备 安装DevEco Studio (鸿蒙官方IDE)配置HarmonyOS SDK申请开发者账号和必要的API密钥 2. 项目结构设计 ├── entry │ ├── src │ │ ├── main │ │ │ ├── ets │ │ │ │ ├── pages │ │ │ │ │ ├── H…...
TCP/IP 网络编程 | 服务端 客户端的封装
设计模式 文章目录 设计模式一、socket.h 接口(interface)二、socket.cpp 实现(implementation)三、server.cpp 使用封装(main 函数)四、client.cpp 使用封装(main 函数)五、退出方法…...

深入解析光敏传感技术:嵌入式仿真平台如何重塑电子工程教学
一、光敏传感技术的物理本质与系统级实现挑战 光敏电阻作为经典的光电传感器件,其工作原理根植于半导体材料的光电导效应。当入射光子能量超过材料带隙宽度时,价带电子受激发跃迁至导带,形成电子-空穴对,导致材料电导率显著提升。…...
JavaScript 标签加载
目录 JavaScript 标签加载script 标签的 async 和 defer 属性,分别代表什么,有什么区别1. 普通 script 标签2. async 属性3. defer 属性4. type"module"5. 各种加载方式的对比6. 使用建议 JavaScript 标签加载 script 标签的 async 和 defer …...