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

相关推荐
格林威1 天前
常规可见光相机在工业视觉检测中的应用
图像处理·人工智能·数码相机·计算机视觉·视觉检测
格林威1 天前
短波红外相机在工业视觉检测中的应用
人工智能·深度学习·数码相机·算法·计算机视觉·视觉检测
格林威1 天前
UV紫外相机在工业视觉检测中的应用
人工智能·深度学习·数码相机·算法·计算机视觉·视觉检测·uv
格林威1 天前
近红外相机在机器视觉检测中的应用
人工智能·数码相机·opencv·计算机视觉·视觉检测
格林威1 天前
不同光谱的工业相机有哪些?能做什么?
图像处理·人工智能·深度学习·数码相机·计算机视觉·视觉检测
格林威2 天前
MP偏振相机在工业视觉检测中的应用
人工智能·数码相机·opencv·计算机视觉·视觉检测·uv
lqjun08272 天前
VTK相机正射投影中通过多个2D坐标计算3D坐标
数码相机·计算机视觉·3d
liiiuzy3 天前
d435i 标定 imu和相机 用来复现vins_fusion
数码相机
格林威4 天前
液态透镜技术在工业镜头中的应用?
人工智能·数码相机·opencv·计算机视觉·视觉检测·相机·工业镜头
程序员Android4 天前
相机长曝光功能梳理
数码相机