如何 在 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 中实现交互式选区并保存为图片。

相关推荐
中达瑞和-高光谱·多光谱7 小时前
高光谱相机:温室盆栽高通量植物表型光谱成像研究
数码相机
PHOSKEY1 天前
3D案例丨多个3D工业相机拼接检测 开启360°新视界
数码相机
围垦1 天前
C# visionpro联合编程中遇到的问题之 R6025 - pure virtual function call
数码相机·c#·visual studio
中达瑞和-高光谱·多光谱1 天前
短波红外高光谱相机:高光谱成像在塑料分选中的应用
数码相机
中达瑞和-高光谱·多光谱2 天前
多光谱相机:林业监测应用(病虫害、外来物种、森林防火识别)
数码相机
xiaomu_3472 天前
工业相机使用笔记
笔记·数码相机·计算机视觉
不死鸟.亚历山大.狼崽子2 天前
Cesium.js(6):Cesium相机系统
开发语言·javascript·数码相机
中达瑞和-高光谱·多光谱4 天前
多光谱相机:海洋管道漏油(溢油)监测
数码相机
程序员Android4 天前
相机预览闪花屏条纹问题处理方法
数码相机