Cesium.js基本使用

整体效果如下:

对于cesium的一些初始工作,可在前几篇博客中自行参考,本文不做过多阐述;

点、线、模型(及运动轨道)的添加

在cesium官网文档cesium.com/learn/cesiu...中可看到一些相关属性

这里我们只取最常用的几个:

点的添加:

less 复制代码
viewer.entities.add({
    name: '添加点',
    position: Cesium.Cartesian3.fromDegrees(lng, lat, height), //经、纬、高度
    point: {
        color: new Cesium.Color(0, 0, 0, 1.0), // 颜色
        pixelSize: 10, // 大小
        outlineColor: Cesium.Color.RED, // 轮廓颜色
        outlineWidth: 5 //轮廓宽度
    }
})

线的添加:

php 复制代码
//起始点
const startPosition = Cesium.Cartesian3.fromDegrees(lng, lat, height);
//结束点
const endPosition = Cesium.Cartesian3.fromDegrees(lng, lat, height);


viewer.entities.add({
    name: '添加线',
    polyline: {
        positions: Cesium.Cartesian3.fromDegreesArray([startPosition, endPosition]),
        width: 2,
        material: Cesium.Color.RED,
    }
})

模型的添加:

php 复制代码
 shipEntity.value = viewer.entities.add({
    id: "shipEntity",
    name: "shipEntity",
    position: Cesium.Cartesian3.fromDegrees(122.35782164573101, 34.12, 100),
    model: {
      uri: '/data/model/hwj.gltf', //模型相对路径  放在public目录下
      minimumPixelSize: 100,
      maximumScale: 20000,
    },
    properties: {         //属性存放
      name: "test-name",
      description: "test-desc"
    }
  })

  shipEntity2.value = viewer.entities.add({
    id: "shipEntity2",
    name: "shipEntity2",
    position: Cesium.Cartesian3.fromDegrees(122.35782164573101, 34.9, 100),
    model: {
      uri: '/data/model/hm.gltf', //模型相对路径  放在public目录下
      minimumPixelSize: 100,
      maximumScale: 20000,
    },
    properties: {        //属性存放
      name: "test-name",
      description: "test-desc"
    }
  })

飞行路线及飞行模型添加

ini 复制代码
const createAirplane = () => {
  if (!window.viewer || airplaneEntity.value) return;

  // 初始化时间
  startTime.value = Cesium.JulianDate.fromDate(new Date());
  stopTime.value = Cesium.JulianDate.addSeconds(startTime.value, 360, new Cesium.JulianDate());

  // 设置时钟
  window.viewer.clock.startTime = startTime.value.clone();
  window.viewer.clock.currentTime = startTime.value.clone();
  window.viewer.clock.stopTime = stopTime.value.clone();
  window.viewer.clock.multiplier = 5;
  window.viewer.timeline.zoomTo(startTime.value, stopTime.value);
  window.viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;

  // 计算飞行路线
  const property = computeFlyRoute();
  const orientation = new Cesium.VelocityOrientationProperty(property);

  // 设置视角偏移
  const viewFrom = new Cesium.Cartesian3();
  viewFrom.z = 1466.61814287398;
  viewFrom.x = -3306.272590514738;
  viewFrom.y = 135.03403439279646;

  // 创建飞机实体
  airplaneEntity.value = window.viewer.entities.add({
    name: 'airplane',
    availability: new Cesium.TimeIntervalCollection([
      new Cesium.TimeInterval({
        start: startTime.value,
        stop: stopTime.value
      })
    ]),
    position: property,
    orientation: orientation,
    viewFrom: viewFrom,
    model: {
      uri: '/data/model/feiji.glb',
      minimumPixelSize: 100,
      maximumScale: 2000,
    },
    path: {
      resolution: 1,
      material: new Cesium.PolylineGlowMaterialProperty({
        glowPower: 0.1,
        color: Cesium.Color.GREEN.withAlpha(1),
      }),
      width: 9,
    },
  });
}

测试文件数据:

这里创建一个json文件(包含点和线)

测试数据如下:

点线整合代码:

ini 复制代码
/**
 * 创建边的数据源(提取的独立函数)
 * @param {Object} viewer - Cesium 实例
 * @param {Array} nodes - 节点数据
 * @param {Array} edges - 边数据
 * @param {String} dataSourceName - 数据源名称
 * @param {Boolean} clampToGround - 是否贴合地面
 * @param {String} color - 线条颜色
 */
const createEdgesDataSource = function (viewer, nodes = [], edges = [], dataSourceName = 'edgesDataSource', clampToGround = true, color = null) {
    // 查找是否已存在同名的数据源
    let dataSource = viewer.dataSources.getByName(dataSourceName);

    if (dataSource.length === 0) {
        // 创建新的数据源
        dataSource = new Cesium.CustomDataSource(dataSourceName);
        viewer.dataSources.add(dataSource);
    } else {
        dataSource = dataSource[0];
    }

    // 清空现有实体
    dataSource.entities.removeAll();

    // 创建边(连接线)- 使用优化后的逻辑
    if (edges && edges.length > 0) {
        edges.forEach((item, index) => {
            const lineArr = [];

            // 查找源节点和目标节点的坐标
            for (let i = 0; i < nodes.length; i++) {
                const node = nodes[i];
                const hasCoordinates = (node.hasOwnProperty('longitude') && node.hasOwnProperty('latitude')) ||
                    (node.hasOwnProperty('经度') && node.hasOwnProperty('纬度'));

                if (hasCoordinates) {
                    if (item.source == node.id) {
                        const lng = node['经度'] !== undefined ? node['经度'] : node.longitude;
                        const lat = node['纬度'] !== undefined ? node['纬度'] : node.latitude;
                        const height = node['高度'] !== undefined ? node['高度'] : (node.height || 0);

                        lineArr.push(lng || 0, lat || 0, height || 0);
                    }

                    if (item.target == node.id) {
                        const lng = node['经度'] !== undefined ? node['经度'] : node.longitude;
                        const lat = node['纬度'] !== undefined ? node['纬度'] : node.latitude;
                        const height = node['高度'] !== undefined ? node['高度'] : (node.height || 0);

                        lineArr.push(lng || 0, lat || 0, height || 0);
                    }
                }
            }

            // 如果成功获取了两个点的坐标,创建连线
            if (lineArr.length === 6) { // 两个点,每个点有3个坐标值
                const startPosition = Cesium.Cartesian3.fromDegrees(lineArr[0], lineArr[1], lineArr[2]);
                const endPosition = Cesium.Cartesian3.fromDegrees(lineArr[3], lineArr[4], lineArr[5]);

                let polylineColor = Cesium.Color.YELLOW;
                if (color) {
                    polylineColor = Cesium.Color.fromCssColorString(color);
                } else if (item.color) {
                    polylineColor = Cesium.Color.fromCssColorString(item.color);
                }

                dataSource.entities.add({
                    id: `edge_${item.source}_${item.target}_${index}`,
                    name: item.name || '连接线',
                    polyline: {
                        positions: [startPosition, endPosition],
                        width: item.width || 7,
                        material: new Cesium.PolylineArrowMaterialProperty(polylineColor),
                        clampToGround: item.clampToGround !== undefined ? item.clampToGround : clampToGround,
                        arcType: Cesium.ArcType.GEODESIC
                    }
                });
            } else {
                console.warn(`无法创建边: 节点 ${item.source} 或 ${item.target} 的坐标不完整`);
            }
        });
    }

    return dataSource;
};

/**
 * Cesium 加载点的方法(改进版,贴合地球表面)
 * viewer: cesium实例
 * array: 节点数据需要id,经纬度
 * dataSourceName: 数据源名称,用于统一管理
 * edges: 边数据,包含连接的节点id
 * clampToGround: 是否贴合地面,默认为true
 */
const createNodesDataSource = function (viewer, nodes = [], height = 0, dataSourceName = 'nodesDataSource', clampToGround = true) {
    // 查找是否已存在同名的数据源
    let dataSource = viewer.dataSources.getByName(dataSourceName);

    if (dataSource.length === 0) {
        // 创建新的数据源
        dataSource = new Cesium.CustomDataSource(dataSourceName);
        viewer.dataSources.add(dataSource);
    } else {
        dataSource = dataSource[0];
    }

    // 清空现有实体
    dataSource.entities.removeAll();

    // 存储节点位置,用于边的连接
    const nodePositions = {};

    // 创建节点
    nodes.forEach((item) => {
        // 使用地形高度采样获取准确的地面高度
        const longitude = item.经度 !== undefined ? item.经度 : item.longitude;
        const latitude = item.纬度 !== undefined ? item.纬度 : item.latitude;

        const cartographicPosition = Cesium.Cartographic.fromDegrees(longitude, latitude);
        const sampledHeight = viewer.scene.globe.getHeight(cartographicPosition) || 0;
        const finalHeight = clampToGround ? sampledHeight + (height || 0) : height;

        const position = Cesium.Cartesian3.fromDegrees(longitude, latitude, finalHeight);
        nodePositions[item.id] = position;

        dataSource.entities.add({
            id: item.id,
            name: item.name,
            position: position,
            point: {
                pixelSize: 20,
                color: new Cesium.Color(1, 1, 0, 1),
                heightReference: clampToGround ? Cesium.HeightReference.CLAMP_TO_GROUND : Cesium.HeightReference.NONE
            },
            label: {
                text: item.name || '暂无名称',
                font: '10px',
                fillColor: Cesium.Color.WHITE,
                backgroundColor: Cesium.Color.SKYBLUE,
                showBackground: false,
                outlineWidth: 2,
                pixelOffset: new Cesium.Cartesian2(1, -34),
                verticalOrigin: Cesium.VerticalOrigin.TOP,
                horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
                heightReference: clampToGround ? Cesium.HeightReference.CLAMP_TO_GROUND : Cesium.HeightReference.NONE
            },
        });
    });
    

    return dataSource;
};

效果如下:

指北针添加

可参考www.npmjs.com/package/ces...

css 复制代码
npm install cesium-navigation-es6 --save
ini 复制代码
import {  Viewer,Rectangle} from "cesium";
import 'cesium/Build/Cesium/Widgets/widgets.css';
import CesiumNavigation from "cesium-navigation-es6";

const viewer = new Viewer("cesiumContainer",{
    animation:false,
    timeline:false
});

const options = {};
// 用于在使用重置导航重置地图视图时设置默认视图控制。接受的值是Cesium.Cartographic 和 Cesium.Rectangle.
// options.defaultResetView = Rectangle.fromDegrees(80, 22, 130, 50)
options.defaultResetView = new Cartographic(CesiumMath.toRadians(111.50623801848565), CesiumMath.toRadians(2.8997206760441205), 8213979.400955964)
//相机方向
options.orientation = {
    heading: CesiumMath.toRadians(350.94452087411315),
    pitch: CesiumMath.toRadians(-66.6402342251215),
    roll: CesiumMath.toRadians(360)
}
//相机延时
options.duration = 4//默认为3s

// 用于启用或禁用罗盘。true是启用罗盘,false是禁用罗盘。默认值为true。如果将选项设置为false,则罗盘将不会添加到地图中。
options.enableCompass= true;
// 用于启用或禁用缩放控件。true是启用,false是禁用。默认值为true。如果将选项设置为false,则缩放控件将不会添加到地图中。
options.enableZoomControls= true;
// 用于启用或禁用距离图例。true是启用,false是禁用。默认值为true。如果将选项设置为false,距离图例将不会添加到地图中。
options.enableDistanceLegend= true;
// 用于启用或禁用指南针外环。true是启用,false是禁用。默认值为true。如果将选项设置为false,则该环将可见但无效。
options.enableCompassOuterRing= true;

//修改重置视图的tooltip
options.resetTooltip = "重置视图";
//修改放大按钮的tooltip
options.zoomInTooltip = "放大";
//修改缩小按钮的tooltip
options.zoomOutTooltip = "缩小";

//如需自定义罗盘控件,请看下面的自定义罗盘控件
new CesiumNavigation(viewer, options);

CZML文件加载

javascript 复制代码
const entitiesCzmlInit = () => {
  //测试文件路径
  let czmlFiles = [`1`, `2`, `3`, `4`,`5`,`6`,'7',`8`, `9`, `10`, `11`,`12`,`13`,'14',`15`, `16`, `17`, `18`,`19`,`20`,'21',`22`, `23`, `24`, `25`,`26`];
  // 测试
  czmlFiles.forEach((file) => {
    viewer.dataSources.add(Cesium.CzmlDataSource.load(`/czmlFile/${file}.czml`));
  });
};

onMounted(async () => {
  Cesium.Ion.defaultAccessToken =
    "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIyYTNkYjhhNC04NDQ4LTRiMDItYTg4OS03YWU3ZWVjNjBiNTgiLCJpZCI6ODYyMDMsImlhdCI6MTY4MTM3ODA5M30.M1tBPd6f5Of1l2ElUqecFjv9GcZ-Ntcwm2iain-fvkk";
  const viewer = new Viewer("cesiumContainer", {
    infoBox: false,
    animation: true, // 是否显示动画控件
    homeButton: false, // 是否显示home键
    geocoder: false, // 是否显示地名查找控件
    baseLayerPicker: false, // 是否显示图层选择控件
    timeline: true, // 是否显示时间线控件
    fullscreenButton: false, // 是否全屏显示
    infoBox: false, // 是否显示点击要素之后显示的信息
    sceneModePicker: false, // 是否显示投影方式控件  三维/二维
    navigationInstructionsInitiallyVisible: false,
    navigationHelpButton: false, // 是否显示帮助信息控件
    orderIndependentTranslucency: false,
    shouldAnimate: true,
    scene3DOnly: false, // 每个几何实例将只能以3D渲染以节省GPU内存
    selectionIndicator: false, // 取消点击有绿框
    // imageryProvider: false, // 不提供地图
    baseLayerPicker: true, //是否显示图层选择控件
    sceneMode: Cesium.SceneMode.SCENE3D, // 设置场景为3D模式
  });
 
  // 设置开始时间
  viewer.clock.startTime = Cesium.JulianDate.fromDate(
    new Date(2024, 10, 10, 8, 30)
  ); // 设置为2024年10月10日 08:30
  // 控制播放状态
  // viewer.clock.shouldAnimate = true;  // 启用动画(时间流动)
  //设置版权等信息不显示
  viewer._cesiumWidget._creditContainer.style.display = "none";


  cesiumViewer.value = viewer;
  window.viewer = viewer;
  
  
  entitiesCzmlInit();
});

声明:

本数据的发布仅为技术演示和学习目的,不对使用本数据引发的任何误用或误解负责。

相关推荐
拿不拿铁192 小时前
Webpack 5.x 开发模式启动流程详解
前端
百***35943 小时前
如何在树莓派部署Nginx并实现无公网ip远程访问内网制作的web网站
前端·tcp/ip·nginx
花果山总钻风3 小时前
Chrome 插件框架 Plasmo 基本使用示例
前端·chrome
资讯第一线3 小时前
《Chrome》 [142.0.7444.60][绿色便携版] 下载
前端·chrome
会篮球的程序猿3 小时前
原生表格文本过长展示问题,参考layui长文本,点击出现文本域
前端·javascript·layui
top_designer3 小时前
Firefly 样式参考:AI 驱动的 UI 资产“无限”生成
前端·人工智能·ui·aigc·ux·设计师
蜗牛前端3 小时前
使用 Trae AI 开发完整的开源 npm 包:snail-git-add
前端
Dontla3 小时前
React useMemo(当依赖项未变化,重复渲染时直接返回上一次缓存计算结果,而非重新执行计算)
前端·react.js·缓存
花生Peadar4 小时前
AI编程从入门到精通
前端·后端·代码规范