技术标签: cesium 图形图像 javascript
Cesium是国外一个基于javascript的地图引擎,支持3D、2D、2.5D形式的展示,可以自行绘制图形、高亮区域,并提供良好的触摸支持,并支持大多数的浏览器和移动端。
当前案例基于vue3+vite
构建
npm i cesium vite-plugin-cesium vite -D
# yarn add cesium vite-plugin-cesium vite -D
vite.config.js
配置:
import {
defineConfig } from 'vite';
import cesium from 'vite-plugin-cesium';
export default defineConfig({
plugins: [cesium()]
});
<template>
<div id="cesiumContainer"></div>
</template>
<script lang="ts" setup>
import {
onMounted } from "vue";
import {
Viewer } from 'cesium';
onMounted(() => {
const viewer = new Viewer('cesiumContainer');
})
</script>
<style lang="scss" scoped></style>
在我们使用Cesium的过程中,如果没有申请ion,同时没有自己的数据源用的cesium提供的数据源,viewer的底部常常会提示一行小的英文字母。大意就是需要申请access token
.
Access Tokens page
页面。Cesium Viewer
的时候,将access token
填为自己的access token即可。Cesium.Ion.defaultAccessToken = '<YOUR ACCESS TOKEN HERE>';
此时底部的小字就消失了!
以上就能畅快的访问Cesium ion提供的各种数据源了。
Cesium应用程序另一个关键元素是Imagery(图层)。瓦片图集合根据不同的投影方式映射到虚拟的三维数字地球表面。依赖于相机指向地表的方向和距离,Cesium会去请求和渲染不同层级的图层详细信息。
多种图层能够被添加、移除、排序和适应到Cesium中。
Cesium提供了一系列方法用于处理图层,比如颜色自适应,图层叠加融合。一些样例代码如下:
Cesium提供了各种 接口 支持各样的图层数据源。
支持的图层格式
注意:不同的数据源需要不同的认证 - 需要确保自己能够有权限访问到这些数据源,自然地需要注册特定的认证才可以
默认地,Cesium使用Bing Maps
作为默认的图层。这个图层被打包进Viewer中用于演示。Cesium需要您自己创建ion account然后生成一个access key用于访问图层数据。
去Cesium ion
页面,将Sentinel-2图层加入到自己的assets中。点击在导航栏中点击“Asset Depot
”
点击 Add to my assets。Sentinel-2将在你个人用户中的asset列表(My Assets)中出现,此时将在个人的app中图层数据源变得可用。
代码修改
我们创建一个IonImageryProvider
,将assetId传给对应的Sentinel-2
图层。然后我们将ImageryProvider
添加到viewer.imageryLayers
。
// Remove default base layer
viewer.imageryLayers.remove(viewer.imageryLayers.get(0));
// Add Sentinel-2 imagery
viewer.imageryLayers.addImageryProvider(new Cesium.IonImageryProvider({
assetId : 3954 }));
Sentinel-2:全世界的无云卫星图像,分辨率可降至10米
Cesium支持流式的、可视化的全球高程投影地形地势、水形数据,包括海洋、湖泊、河流、山峰、峡谷和其他能够被三维展示出来的且效果比二维好的地形数据。像图层数据一样,Cesium引擎会从一个服务器上请求流式地形数据,仅请求那些基于当前相机能看到的需要绘制的图层上的数据。
Cesium官方提供了一些地形数据集的例子,以及如何配置这些参数。
支持的地形数据格式:
为了添加地形数据,我们需要创建一个CesiumTerrainProvider
,提供一个url和一些配置项,然后将这个provider赋值给viewer.terrainProvider
。
此处,我们使用Cesium WorldTerrian
图层,该图层由Cesium ion
提供,在“My Assets”中是默认提供的。我们可以用createWorldTerrainhelper
函数创建一个由Cesium ion提供服务的Cesium WorldTerrian。
// Load Cesium World Terrain
viewer.terrainProvider = Cesium.createWorldTerrain({
requestWaterMask : true, // required for water effects
requestVertexNormals : true // required for terrain lighting
});
*requestWaterMask
和requestVertexNormals
是可选的配置项,告诉Cesium是否需要请求额外的水、光数据。这两个选项默认是设为false的。*
最终,既然我们有了地形数据,我们需要更多的线条来使得地形数据背后的objects能够正确地显示,只有最前面、最上面的objects才能是可见的。
// Enable depth testing so things behind the terrain disappear.
viewer.scene.globe.depthTestAgainstTerrain = true;
我们现在有地形数据和运动的水。纽约非常平坦,所以可以在上面的地形数据上自由的探索。举一个显而易见的例子,你可以跳转到更加崎岖的区域比如 Grand Canyon 或者 San Francisco。
接下来将添加一些更多的正确的时间和空间设置到Viewer中。涉及到与viewer.scene进行交互,该类控制了viewer中的所有图形元素。
// Enable lighting based on sun/moon positions
viewer.scene.globe.enableLighting = true;
按照以上配置,我们scene(场景)中的光照将会随着每天时间的变化而变化。如果你zoom out,你就会看到一部分数字地球位于黑暗之中,因为模拟真实的地球,太阳只能照射到地球的一部分。
这些是在场景中定位和定位Cesium objects所必需的基本类型,并且有许多有用的转换方法。请参阅每种类型的文档以了解更多信息。
现在让我们把相机定位在我们数据所在的NYC(纽约)的场景中。
相机是viewer.scene
中的属性,用来控制当前可见的域。我们可以通过直接设置它的位置和方向来控制相机,或者通过使用Cesium提供的API来控制相机,它被设计成指定相机的位置和方向随时间的变化。
一些最常用的方法如下:
Camera.setView(options): 在特定位置和方向立即设置相机。
Camera.zoomIn(amount): 沿着视角矢量移动摄像机。
Camera.zoomOut(amount): 沿视角矢量向后移动摄像机。
Camera.flyTo(options): 创建从当前相机位置到新位置的动画相机飞行。
Camera.lookAt(target, offset) : 定位并定位摄像机以给定偏移量瞄准目标点。
Camera.move(direction, amount) : 朝任何方向移动摄像机。
Camera.rotate(axis, angle) : 绕任意轴旋转相机。
进一步获得API功能,看看这些相机演示:
Camera API Demo
Custom Camera Controls Demo
让我们尝试一种方法将相机跳转到纽约。使用camera.setView()
初始化view,使用Cartesian3和HeadingpitchRoll指定相机的位置和方向:
// Create an initial camera view
var initialPosition = new Cesium.Cartesian3.fromDegrees(-73.998114468289017509, 40.674512895646692812, 2631.082799425431);
var initialOrientation = new Cesium.HeadingPitchRoll.fromDegrees(7.1077496389876024807, -31.987223091598949054, 0.025883251314954971306);
var homeCameraView = {
destination : initialPosition,
orientation : {
heading : initialOrientation.heading,
pitch : initialOrientation.pitch,
roll : initialOrientation.roll
}
};
// Set the initial view
viewer.scene.camera.setView(homeCameraView);
相机现在被定位和定向以俯瞰曼哈顿,并且我们的视图参数被保存在一个对象中,我们可以将其传递给其他相机方法。
效果如下:
实际上,我们可以使用这个相同的视角来更新按下home按钮的效果。我们不必让它从远处返回地球的默认视角,我们可以重写按钮,使我们看到曼哈顿的初始视角。我们可以通过添加几个选项来调整动画,然后添加一个取消默认航班的事件侦听器,并调用FlyTo()
我们的Home视角:
// Add some camera flight animation options
homeCameraView.duration = 2.0;
homeCameraView.maximumHeight = 2000;
homeCameraView.pitchAdjustHeight = 2000;
homeCameraView.endTransform = Cesium.Matrix4.IDENTITY;
// Override the default home button
viewer.homeButton.viewModel.command.beforeExecute.addEventListener(function (e) {
e.cancel = true;
viewer.scene.camera.flyTo(homeCameraView);
});
点击Home按钮后,视图会直接跳转到纽约上空
更多关于基本相机控制,请访问我们的Camera Tutorial。
接下来,我们配置viewer的Clock和Timline来控制scene的时间进度。
这里是clock的相关API
当使用特定时间时,Cesium使用JulandDATE类型,它存储了1月1日中午以来的天数-4712(公元前4713年)。为了提高精度,该类将日期和秒的全部部分存储在单独的组件中。为了计算安全和代表跳跃秒,日期总是存储在国际原子时间标准中。
下面是我们如何设置场景时间选项的例子:
// Set up clock and timeline.
viewer.clock.shouldAnimate = true; // make the animation play when the viewer starts
viewer.clock.startTime = Cesium.JulianDate.fromIso8601("2017-07-11T16:00:00Z");
viewer.clock.stopTime = Cesium.JulianDate.fromIso8601("2017-07-11T16:20:00Z");
viewer.clock.currentTime = Cesium.JulianDate.fromIso8601("2017-07-11T16:00:00Z");
viewer.clock.multiplier = 2; // sets a speedup
viewer.clock.clockStep = Cesium.ClockStep.SYSTEM_CLOCK_MULTIPLIER; // tick computation mode
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP; // loop at the end
viewer.timeline.zoomTo(viewer.clock.startTime, viewer.clock.stopTime); // set visible range
这设置场景动画的速率、开始和停止时间,并告诉时钟在到达停止时间时循环回到开始。它还将时间线控件设置为适当的时间范围。看看这个时钟示例代码来测试时钟设置。
这是我们的初始场景配置!现在,当你运行你的应用程序时,你应该看到以下内容:
效果如下:
实体使用Cesium官网提供的实体:kml下载地址
var options = {
camera: viewer.scene.camera,
canvas: viewer.scene.canvas,
screenOverlayContainer: viewer.container,
};
var dataSourcePromise= Cesium.KmlDataSource.load('/cesium/gdpPerCapita2008.kmz', options);
// viewer.dataSources.add(dataSourcePromise); 可以选择一次性加载
dataSourcePromise.then(dataSource => {
viewer.dataSources.add(dataSource);
var geocacheEntities = dataSource.entities.values;
for (var i = 0; i < geocacheEntities.length; i++) {
var entity = geocacheEntities[i];
if (Cesium.defined(entity.billboard)) {
// 这里可以篡改entity的样式
}
}
})
viewer.camera.flyHome(0);
效果如下:
Entity结构如下:
【引用教程】
新手入门中文教程
文章浏览阅读685次。1.1.什么是有状态?有状态服务,即服务端需要记录每次会话的客户端信息,从而识别客户端身份,根据用户身份进行请求的处理,典型的设计如tomcat中的session。例如登录:用户登录后,我们把登录者的信息保存在服务端session中,并且给用户一个cookie值,记录对应的session。然后下次请求,用户携带cookie值来,我们就能识别到对应session,从而找到用户的信息。缺点是什么?服务端保存大量数据,增加服务端压力 服务端保存用户状态,无法进行水平扩展 客户端请求依赖服务.._无状态token登录
文章浏览阅读293次。SDUT OnlineJudge#include<iostream>using namespace std;int main(){int a,b,c,d;cin>>a;b=a%10;c=a/10%10;d=a/100%10;int key[3];key[0]=b;key[1]=c;key[2]=d;for(int i = 0;i<3;i++){ if(key[i]!=0) { cout<<key[i.
文章浏览阅读2.2k次。年终奖采用的平均每月的收入来评定缴税级数的,速算扣除数也按照月份计算出来,但是最终减去的也是一个月的速算扣除数。为什么这么做呢,这样的收的税更多啊,年终也是一个月的收入,凭什么减去12*速算扣除数了?这个霸道(不要脸)的说法,我们只能合理避免的这些跨级的区域了,那具体是那些区域呢?可以参考下面的表格:年终奖一列标红的一对便是盲区的上下线,发放年终奖的数额一定一定要避免这个区域,不然公司多花了钱..._年终奖盲区表
文章浏览阅读7.5k次,点赞5次,收藏19次。matlab结构体struct字段变量值提取_matlab读取struct类型数据中的值
文章浏览阅读4.8k次。1,什么情况下使用fragment通常用来作为一个activity的用户界面的一部分例如, 一个新闻应用可以在屏幕左侧使用一个fragment来展示一个文章的列表,然后在屏幕右侧使用另一个fragment来展示一篇文章 – 2个fragment并排显示在相同的一个activity中,并且每一个fragment拥有它自己的一套生命周期回调方法,并且处理它们自己的用户输_android reader fragment
文章浏览阅读2.8k次。FFT of waveIn audio signalsBy Aqiruse An article on using the Fast Fourier Transform on audio signals. IntroductionThe Fast Fourier Transform (FFT) allows users to view the spectrum content of _fft of wavein audio signals
文章浏览阅读5.9k次。https://jaywcjlove.github.io/awesome-mac/ 这个仓库主要是收集非常好用的Mac应用程序、软件以及工具,主要面向开发者和设计师。有这个想法是因为我最近发了一篇较为火爆的涨粉儿微信公众号文章《工具武装的前端开发工程师》,于是建了这么一个仓库,持续更新作为补充,搜集更多好用的软件工具。请Star、Pull Request或者使劲搓它 issu_awesomemac
文章浏览阅读616次。一.jquery简介 jQuery是一个快速的,简洁的javaScript库,使用户能更方便地处理HTML documents、events、实现动画效果,并且方便地为网站提供AJAX交互 jQuery 的功能概括1、html 的元素选取2、html的元素操作3、html dom遍历和修改4、js特效和动画效果5、css操作6、html事件操作7、ajax_简介java中jquery技术
文章浏览阅读1.6w次,点赞5次,收藏19次。我修改的是表格的固定列滚动而产生的滚动条引用Table的组件的css文件中加入下面的样式:.ant-table-body{ &amp;::-webkit-scrollbar { height: 5px; } &amp;::-webkit-scrollbar-thumb { border-radius: 5px; -webkit-box..._ant design ::-webkit-scrollbar-corner
文章浏览阅读269次。基于JSP的健身俱乐部会员管理系统项目分享:见文末!
文章浏览阅读1.8k次,点赞2次,收藏15次。同学们,是不是又到了一年一度写开题报告的时候呀?是不是还在为不知道论文的开题报告怎么写而苦恼?Take it easy!我带着倾尽我所有开题报告写作经验总结出来的最强保姆级开题报告解说来啦,一定让你脱胎换骨,顺利拿下开题报告这个高塔,你确定还不赶快点赞收藏学起来吗?_开题报告研究难点
文章浏览阅读6k次,点赞4次,收藏17次。原生先获取对象var a = document.getElementById("dom");vue先添加ref <div class="" ref="divBox">获取对象let a = this.$refs.divBox获取父、子、兄弟节点方法var b = a.childNodes; 获取a的全部子节点 var c = a.parentNode; 获取a的父节点var d = a.nextSbiling; 获取a的下一个兄弟节点 var e = a.previ_获取子节点的路径 vue