如何 在 Cesium 中选择部分区域 并渲染保存成 图片

在 Cesium 中选择特定区域并渲染保存为图片,可以通过 ‌绘制矩形选区 + 相机视角调整 + 截图保存‌ 实现。以下是完整方案:


步骤 1:添加矩形绘制工具

使用 Cesium.ScreenSpaceEventHandler 监听鼠标事件,绘制选区并获取地理范围。

复制代码
  
  
  
   
   javascript
   
   Copy Code
  
  
  
  
  
  
   
   
   
    
    
    

    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    


    
    
    

   
   
   

   
   
   

    
    let` handler = `new` `Cesium`.`ScreenSpaceEventHandler`(viewer.`scene`.`canvas`);
`let` startPosition = `null`;
`let` rectangle = `null`;
`
   
   
   
  
  
  

// 监听鼠标按下事件

handler.setInputAction((event) => {

startPosition = event.position;

}, Cesium.ScreenSpaceEventType.LEFT_DOWN);

// 监听鼠标移动事件(绘制临时矩形)

handler.setInputAction((event) => {
if (!startPosition) return;
const currentPosition = event.endPosition;

// 清除之前的矩形
if (rectangle) {

viewer.entities.remove(rectangle);

}

// 计算矩形范围(屏幕坐标转地理坐标)
const cartesianStart = viewer.camera.pickEllipsoid(startPosition);
const cartesianEnd = viewer.camera.pickEllipsoid(currentPosition);
const rect = Cesium.Rectangle.fromCartesianArray([cartesianStart, cartesianEnd]);

// 绘制临时矩形

rectangle = viewer.entities.add({
rectangle: {
coordinates: rect,
material: Cesium.Color.RED.withAlpha(0.3),
outline: true,
outlineColor: Cesium.Color.RED

}

});

}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

// 监听鼠标释放事件(确定选区)

handler.setInputAction(async (event) => {
const endPosition = event.position;
const rectCoordinates = rectangle.rectangle.coordinates.getValue();

// 保存选区范围
const selectedRectangle = rectCoordinates;

// 删除临时矩形

viewer.entities.remove(rectangle);

rectangle = null;

// 调整视角并截图(步骤2)
await captureAndSave(selectedRectangle);

}, Cesium.ScreenSpaceEventType.LEFT_UP);


步骤 2:调整相机视角到选区

将相机视角聚焦到选定的矩形区域。

复制代码
 
 
 
  
  javascript
  
  Copy Code
 
 
 
 
 
 
  
  
  
   
   
   

   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   

  
  
  

  
  
  

   
   async` `function` `captureAndSave`(`rectangle`) {
  `// 调整相机视角到矩形区域`
  viewer.`camera`.`flyTo`({
    `destination`: rectangle,
    `complete`: `() =>` {
      `// 等待渲染完成`
      `setTimeout`(`() =>` {
        `// 截图保存(步骤3)`
        `saveAsImage`();
      }, `1000`); `// 延迟确保渲染完成`
    }
  });
}
`
  
  
  
 
 
 

步骤 3:截图保存为图片

使用 canvas.toDataURL 将当前视图保存为 PNG 图片。

复制代码
 
 
 
  
  javascript
  
  Copy Code
 
 
 
 
 
 
  
  
  
   
   
   

   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   

  
  
  

  
  
  

   
   function` `saveAsImage`(``) {
  `// 获取 Canvas 元素`
  `const` canvas = viewer.`scene`.`canvas`;
`
  
  
  
 
 
 

// 转换为 Data URL
const image = canvas.toDataURL('image/png');

// 创建下载链接
const link = document.createElement('a');

link.download = 'cesium-screenshot.png';

link.href = image;

link.click();

}


完整代码整合

复制代码
 
 
 
  
  html
  
  Copy Code
 
 
 
 
 
 
  
  
  
   
   
   

   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   


   
   
   

  
  
  

  
  
  

   
   <!DOCTYPE html>`
`<html>`
`<head>`
  `<link href="https://cesium.com/downloads/cesiumjs/releases/1.95/Build/Cesium/Widgets/widgets.css" rel="stylesheet">`
  `<script src="https://cesium.com/downloads/cesiumjs/releases/1.95/Build/Cesium/Cesium.js"></script>`
`</head>`
`<body>`
  `<div id="cesiumContainer" style="width: 100%; height: 600px;"></div>`
  `<script>
    const viewer = new Cesium.Viewer('cesiumContainer', {
      terrainProvider: Cesium.createWorldTerrain()
    });

   
   
   
    <span class="hljs-keyword">let</span> handler = <span class="hljs-literal">null</span>;
    <span class="hljs-keyword">let</span> startPosition = <span class="hljs-literal">null</span>;
    <span class="hljs-keyword">let</span> rectangle = <span class="hljs-literal">null</span>;

    <span class="hljs-comment">// 启动矩形绘制工具</span>
    <span class="hljs-keyword">function</span> <span class="hljs-title function_">enableRectangleSelection</span>(<span class="hljs-params"></span>) {
      handler = <span class="hljs-keyword">new</span> <span class="hljs-title class_">Cesium</span>.<span class="hljs-title class_">ScreenSpaceEventHandler</span>(viewer.<span class="hljs-property">scene</span>.<span class="hljs-property">canvas</span>);
      
      handler.<span class="hljs-title function_">setInputAction</span>(<span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
        startPosition = event.<span class="hljs-property">position</span>;
      }, <span class="hljs-title class_">Cesium</span>.<span class="hljs-property">ScreenSpaceEventType</span>.<span class="hljs-property">LEFT_DOWN</span>);

      handler.<span class="hljs-title function_">setInputAction</span>(<span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span> (!startPosition) <span class="hljs-keyword">return</span>;
        <span class="hljs-keyword">const</span> currentPosition = event.<span class="hljs-property">endPosition</span>;
        <span class="hljs-keyword">if</span> (rectangle) viewer.<span class="hljs-property">entities</span>.<span class="hljs-title function_">remove</span>(rectangle);
        
        <span class="hljs-keyword">const</span> cartesianStart = viewer.<span class="hljs-property">camera</span>.<span class="hljs-title function_">pickEllipsoid</span>(startPosition);
        <span class="hljs-keyword">const</span> cartesianEnd = viewer.<span class="hljs-property">camera</span>.<span class="hljs-title function_">pickEllipsoid</span>(currentPosition);
        <span class="hljs-keyword">const</span> rect = <span class="hljs-title class_">Cesium</span>.<span class="hljs-property">Rectangle</span>.<span class="hljs-title function_">fromCartesianArray</span>([cartesianStart, cartesianEnd]);
        
        rectangle = viewer.<span class="hljs-property">entities</span>.<span class="hljs-title function_">add</span>({
          <span class="hljs-attr">rectangle</span>: { <span class="hljs-attr">coordinates</span>: rect, <span class="hljs-attr">material</span>: <span class="hljs-title class_">Cesium</span>.<span class="hljs-property">Color</span>.<span class="hljs-property">RED</span>.<span class="hljs-title function_">withAlpha</span>(<span class="hljs-number">0.3</span>) }
        });
      }, <span class="hljs-title class_">Cesium</span>.<span class="hljs-property">ScreenSpaceEventType</span>.<span class="hljs-property">MOUSE_MOVE</span>);

      handler.<span class="hljs-title function_">setInputAction</span>(<span class="hljs-keyword">async</span> (event) =&gt; {
        <span class="hljs-keyword">const</span> rectCoordinates = rectangle.<span class="hljs-property">rectangle</span>.<span class="hljs-property">coordinates</span>.<span class="hljs-title function_">getValue</span>();
        viewer.<span class="hljs-property">entities</span>.<span class="hljs-title function_">remove</span>(rectangle);
        rectangle = <span class="hljs-literal">null</span>;
        <span class="hljs-keyword">await</span> <span class="hljs-title function_">captureAndSave</span>(rectCoordinates);
      }, <span class="hljs-title class_">Cesium</span>.<span class="hljs-property">ScreenSpaceEventType</span>.<span class="hljs-property">LEFT_UP</span>);
    }

    <span class="hljs-keyword">async</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">captureAndSave</span>(<span class="hljs-params">rectangle</span>) {
      viewer.<span class="hljs-property">camera</span>.<span class="hljs-title function_">flyTo</span>({
        <span class="hljs-attr">destination</span>: rectangle,
        <span class="hljs-attr">complete</span>: <span class="hljs-function">() =&gt;</span> {
          <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
            <span class="hljs-keyword">const</span> canvas = viewer.<span class="hljs-property">scene</span>.<span class="hljs-property">canvas</span>;
            <span class="hljs-keyword">const</span> image = canvas.<span class="hljs-title function_">toDataURL</span>(<span class="hljs-string">'image/png'</span>);
            <span class="hljs-keyword">const</span> link = <span class="hljs-variable language_">document</span>.<span class="hljs-title function_">createElement</span>(<span class="hljs-string">'a'</span>);
            link.<span class="hljs-property">download</span> = <span class="hljs-string">'selected-area.png'</span>;
            link.<span class="hljs-property">href</span> = image;
            link.<span class="hljs-title function_">click</span>();
          }, <span class="hljs-number">1000</span>);
        }
      });
    }

    <span class="hljs-comment">// 初始化工具</span>
    <span class="hljs-title function_">enableRectangleSelection</span>();




  
  
  
 
 
 

</script>
</body>
</html>


关键优化

  1. 高清截图‌:

    复制代码
       
       
       
        
        javascript
        
        Copy Code
       
       
       
       
       
       
        
        
        
         
         
         
    
         
         
         
    
        
        
        
    
        
        
        
    
         
         // 提高分辨率(2倍)`
    viewer.`resolutionScale` = `2`;
    `
        
        
        
       
       
       
  2. 去除水印‌:

    复制代码
       
       
       
        
        javascript
        
        Copy Code
       
       
       
       
       
       
        
        
        
         
         
         
        
        
        
    
        
        
        
    
         
         `viewer.`cesiumWidget`.`creditContainer`.`style`.`display` = `'none'`;
    `
        
        
        
       
       
       
  3. 支持文件命名‌:

    复制代码
       
       
       
        
        javascript
        
        Copy Code
       
       
       
       
       
       
        
        
        
         
         
         
        
        
        
    
        
        
        
    
         
         `link.`download` = ``area-${new Date().toISOString()}.png``;
    `
        
        
        
       
       
       

注意事项

  • 确保 Cesium.Camera.flyTo 的动画完成后截图,避免画面未渲染完成。
  • 如果选区跨越大范围,可能需要调整相机的 pitchroll 以垂直俯视。
  • 跨域图片资源可能导致 toDataURL 失效,需配置服务器 CORS。

通过此方案,您可以在 Cesium 中实现交互式选区并保存为图片。

相关推荐
诸葛务农9 小时前
ToF(飞行时间)相机在人形机器人非接触式传感领域内的应用
数码相机·机器人
塞北山巅16 小时前
相机自动曝光(AE)核心算法——从参数调节到亮度标定
数码相机·算法
美摄科技1 天前
相机sdk是什么意思?
数码相机
phyit1 天前
全景相机领域,影石何以杀出重围?
数码相机
鄃鳕1 天前
装饰器【Python】
开发语言·python·数码相机
聪明不喝牛奶2 天前
【已解决】海康威视相机如何升级固件
数码相机
PAQQ2 天前
1站--视觉搬运工业机器人工作站 -- 相机部分
数码相机·机器人
诸葛务农2 天前
人形机器人基于视觉的非接触式触觉传感技术
数码相机·机器人
moonsims3 天前
被动式热成像摄像机也称前视红外 (FLIR) 摄像机-Sierra-Olympia Technologies 中波红外摄像机
数码相机
中达瑞和-高光谱·多光谱3 天前
什么高光谱相机适合用于实验室研究,推荐什么品牌?
数码相机