当前位置: 首页 > java >正文

基于cesium实现鼠标移动动态绘制矩形和圆

基于cesium实现鼠标拖动绘制圆和矩形的示例

<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8" /><meta http-equiv="X-UA-Compatible" /><title>绘制</title><link href="./Cesium/Widgets/widgets.css" rel="stylesheet" /><style>html,body {margin: 0px;overflow: hidden;width: 100%;height: 100%;}</style><script src="jquery1.9.0.min.js"></script><script type="text/javascript" src="./Cesium/Cesium.js"></script>
</head><body><div style="position: absolute;margin: 30px;z-index: 2;color: #fff;height: 26px;"><table><tr><td><button onclick="drawRectangle();">绘制矩形</button></td><td><button onclick="drawCircle();">绘制圆</button></td></tr></table></div><div id="cesiumContainer"></div><script>//初始化viewervar viewer = new Cesium.Viewer('cesiumContainer', {infoBox: false,shouldAnimate: true,selectionIndicator: false});// 存储绘图状态和实体const drawingManager = {isDrawing: false,startPosition: null,endPosition: null,tempRectangle: null,startPoint: null,endPoint: null,rectangleEntities: [],handler: new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas),// 初始化绘图功能init: function() {this.setupMouseEvents();this.addHelpLabel();},// 设置鼠标事件setupMouseEvents: function() {// 左键点击 - 开始/结束绘制this.handler.setInputAction(click => {if (!this.isDrawing) {this.startDrawing(click.position);} else {this.finishDrawing();}}, Cesium.ScreenSpaceEventType.LEFT_CLICK);// 鼠标移动 - 更新矩形this.handler.setInputAction(movement => {if (this.isDrawing) {this.updateRectangle(movement.endPosition);}}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);// 右键点击 - 取消绘制this.handler.setInputAction(() => {if (this.isDrawing) {this.cancelDrawing();}}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);},// 开始绘制startDrawing: function(clickPosition) {this.isDrawing = true;// 获取起始点坐标const ray = viewer.camera.getPickRay(clickPosition);this.startPosition = viewer.scene.globe.pick(ray, viewer.scene);if (!this.startPosition) return;// 创建起始点标记this.startPoint = viewer.entities.add({position: this.startPosition,point: {pixelSize: 2,color: Cesium.Color.RED,outlineColor: Cesium.Color.WHITE,outlineWidth: 2}});// 创建临时矩形this.tempRectangle = viewer.entities.add({rectangle: {coordinates: new Cesium.CallbackProperty(() => {return this.calculateRectangleCoordinates();}, false),material: Cesium.Color.RED.withAlpha(0.3),outline: true,outlineColor: Cesium.Color.RED,outlineWidth: 2,height: 10,// extrudedHeight: 0}});// 显示工具提示this.updateTooltip(this.startPosition, "点击确定矩形起点");},// 更新矩形updateRectangle: function(mousePosition) {if (!this.startPosition) return;// 获取当前鼠标位置坐标const ray = viewer.camera.getPickRay(mousePosition);this.endPosition = viewer.scene.globe.pick(ray, viewer.scene);if (!this.endPosition) return;// 更新或创建终点标记if (!this.endPoint) {this.endPoint = viewer.entities.add({position: this.endPosition,point: {pixelSize: 10,color: Cesium.Color.YELLOW,outlineColor: Cesium.Color.WHITE,outlineWidth: 2}});} else {this.endPoint.position = this.endPosition;}// 更新工具提示this.updateTooltip(this.endPosition, this.getSizeInfo());},// 计算矩形坐标calculateRectangleCoordinates: function() {if (!this.startPosition || !this.endPosition) return null;const startCarto = Cesium.Cartographic.fromCartesian(this.startPosition);const endCarto = Cesium.Cartographic.fromCartesian(this.endPosition);return Cesium.Rectangle.fromDegrees(Cesium.Math.toDegrees(Math.min(startCarto.longitude, endCarto.longitude)),Cesium.Math.toDegrees(Math.min(startCarto.latitude, endCarto.latitude)),Cesium.Math.toDegrees(Math.max(startCarto.longitude, endCarto.longitude)),Cesium.Math.toDegrees(Math.max(startCarto.latitude, endCarto.latitude)));},// 计算挤压高度(用于3D效果)calculateExtrudedHeight: function() {if (!this.startPosition || !this.endPosition) return 0;// 简单示例:根据矩形大小设置高度const startCarto = Cesium.Cartographic.fromCartesian(this.startPosition);const endCarto = Cesium.Cartographic.fromCartesian(this.endPosition);const latDist = Math.abs(startCarto.latitude - endCarto.latitude) * 6378137;const lonDist = Math.abs(startCarto.longitude - endCarto.longitude) * 6378137;return Math.min(latDist, lonDist) * 0.2; // 高度的简单计算},// 获取矩形尺寸信息getSizeInfo: function() {if (!this.startPosition || !this.endPosition) return "";const startCarto = Cesium.Cartographic.fromCartesian(this.startPosition);const endCarto = Cesium.Cartographic.fromCartesian(this.endPosition);// 计算距离(考虑了地球曲率)const geodesic = new Cesium.EllipsoidGeodesic();geodesic.setEndPoints(startCarto, endCarto);const distance = geodesic.surfaceDistance;// 计算面积(近似)const width = Math.abs(startCarto.longitude - endCarto.longitude) * 6378137;const height = Math.abs(startCarto.latitude - endCarto.latitude) * 6378137;const area = width * height;return `宽度: ${(width/1000).toFixed(2)} km\n高度: ${(height/1000).toFixed(2)} km\n对角线: ${(distance/1000).toFixed(2)} km\n面积: ${(area/1000000).toFixed(2)} km²`;},// 完成绘制finishDrawing: function() {if (!this.startPosition || !this.endPosition) {this.cancelDrawing();return;}// 创建最终矩形实体const rectangle = viewer.entities.add({clampToS3M: true,clampToGround: true,rectangle: {coordinates: this.calculateRectangleCoordinates(),material: Cesium.Color.RED.withAlpha(0.3),outline: true,outlineColor: Cesium.Color.RED,outlineWidth: 2,height: 10,// extrudedHeight: 0},name: '绘制矩形 ' + (this.rectangleEntities.length + 1)});this.rectangleEntities.push(rectangle);// 清除临时图形this.cleanupTempEntities();this.hideTooltip();},// 取消绘制cancelDrawing: function() {this.cleanupTempEntities();this.hideTooltip();},// 清理临时实体cleanupTempEntities: function() {if (this.startPoint) viewer.entities.remove(this.startPoint);if (this.endPoint) viewer.entities.remove(this.endPoint);if (this.tempRectangle) viewer.entities.remove(this.tempRectangle);this.isDrawing = false;this.startPoint = null;this.endPoint = null;this.tempRectangle = null;this.startPosition = null;this.endPosition = null;},// 更新工具提示updateTooltip: function(position, text) {const tooltip = document.getElementById('tooltip');if (!position || !text) {tooltip.style.display = 'none';return;}const canvasPosition = Cesium.SceneTransforms.wgs84ToWindowCoordinates(viewer.scene, position);if (canvasPosition) {tooltip.style.display = 'block';tooltip.style.left = (canvasPosition.x + 10) + 'px';tooltip.style.top = (canvasPosition.y + 10) + 'px';tooltip.textContent = text;}},// 隐藏工具提示hideTooltip: function() {document.getElementById('tooltip').style.display = 'none';},// 添加帮助标签addHelpLabel: function() {viewer.entities.add({position: Cesium.Cartesian3.fromDegrees(0, 0),label: {text: '左键点击确定起点,移动鼠标调整矩形大小\n再次左键点击完成绘制,右键取消',font: '14pt sans-serif',style: Cesium.LabelStyle.FILL_AND_OUTLINE,outlineWidth: 2,verticalOrigin: Cesium.VerticalOrigin.TOP,pixelOffset: new Cesium.Cartesian2(0, 20),heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,disableDepthTestDistance: Number.POSITIVE_INFINITY}});},// 清除所有绘制的矩形clearAllRectangles: function() {this.rectangleEntities.forEach(entity => {viewer.entities.remove(entity);});this.rectangleEntities = [];}};// 绘制矩形function drawRectangle(params) {// 初始化绘图管理器drawingManager.init();}// 绘制圆function drawCircle(params) {// 存储绘图状态和实体let drawing = false;let centerPosition = null;let radius = 0;let tempCircle = null;let centerPoint = null;// 鼠标处理器const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);// 鼠标左键点击事件 - 确定圆心handler.setInputAction(function(click) {if (!drawing) {// 开始绘制drawing = true;// 获取点击位置的笛卡尔坐标const ray = viewer.camera.getPickRay(click.position);centerPosition = viewer.scene.globe.pick(ray, viewer.scene);// 添加圆心点centerPoint = viewer.entities.add({position: centerPosition,point: {pixelSize: 2,color: Cesium.Color.RED,outlineColor: Cesium.Color.WHITE,outlineWidth: 2}});// 创建临时圆形tempCircle = viewer.entities.add({position: centerPosition,classificationType: Cesium.ClassificationType.S3M_TILE, //贴模型clampToS3M: true,clampToGround: true,ellipse: {semiMajorAxis: new Cesium.CallbackProperty(function() {return radius;}, false),semiMinorAxis: new Cesium.CallbackProperty(function() {return radius;}, false),height: 10,material: Cesium.Color.RED.withAlpha(0.3),outline: true,outlineColor: Cesium.Color.BLUE,outlineWidth: 2}});} else {// 结束绘制drawing = false;centerPosition = null;radius = 0;// 移除临时图形viewer.entities.remove(centerPoint);viewer.entities.remove(tempCircle);centerPoint = null;tempCircle = null;}}, Cesium.ScreenSpaceEventType.LEFT_CLICK);// 鼠标移动事件 - 动态更新半径handler.setInputAction(function(movement) {if (drawing && centerPosition) {// 获取当前鼠标位置const ray = viewer.camera.getPickRay(movement.endPosition);const currentPosition = viewer.scene.globe.pick(ray, viewer.scene);if (currentPosition) {// 计算圆心到当前鼠标位置的距离(半径)radius = Cesium.Cartesian3.distance(centerPosition, currentPosition);}}}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);// 右键点击取消绘制handler.setInputAction(function() {viewer.entities.add({position: centerPosition,classificationType: Cesium.ClassificationType.S3M_TILE, //贴模型clampToS3M: true,clampToGround: true,ellipse: {semiMajorAxis: radius,semiMinorAxis: radius,height: 10,material: Cesium.Color.RED.withAlpha(0.3),outline: true,outlineColor: Cesium.Color.RED,outlineWidth: 2}});if (drawing) {drawing = false;centerPosition = null;radius = 0;// 移除临时图形// if (centerPoint) {//     viewer.entities.remove(centerPoint);//     centerPoint = null;// }if (tempCircle) {viewer.entities.remove(tempCircle);tempCircle = null;}}}, Cesium.ScreenSpaceEventType.RIGHT_CLICK);}</script>
</body></html>

http://www.xdnf.cn/news/1958.html

相关文章:

  • Rust 学习笔记:函数和控制流
  • React 中什么时候用事件总线
  • 微信小程序直传阿里云 OSS 实践指南(V4 签名 · 秒传支持 · 高性能封装)
  • ROS1、ROS2如何把预编译好的二进制文件封装成功能包?
  • 【Django】新增字段后兼容旧接口 This field is required
  • 代码随想录:数组
  • 如何实现Android屏幕和音频采集并启动RTSP服务?
  • 如何使用@KafkaListener实现从nacos中动态获取监听的topic
  • 【Hive入门】Hive数据导出完全指南:从HDFS到本地文件系统的专业实践
  • 利用JMeter代理服务器方式实现高效压测
  • Leetcode 2845 题解
  • C++_数据结构_详解红黑树
  • 微软官网Win10镜像下载快速获取ISO文件
  • 第18章:MCP在创作领域中的应用
  • Java集成Redisson实现分布式锁(实战)
  • 学生管理系统微服务方式实现
  • WebUI可视化:第3章:Gradio入门实战
  • FerretDB:基于PostgreSQL的MongoDB替代产品
  • 2、Ubuntu 环境下安装RabbitMQ
  • PDFMathTranslate:基于LLM的PDF文档翻译及双语对照的工具【使用教程】
  • Golang | 迭代器模式
  • 学习整理在centos7上安装mysql8.0版本教程
  • 同步定时器的用户数要和线程组保持一致,否则jmeter会出现接口不执行’stop‘和‘×’的情况
  • 基于线性LDA算法对鸢尾花数据集进行分类
  • 【uniapp】vue2 搜索文字高亮显示
  • 【Java】BitSet简介
  • 10.ArkUI Grid的介绍和使用
  • HTML 地理定位(Geolocation)教程
  • 从 “制造” 到 “品牌”:官网建设助力中国企业突围东南亚
  • python打印颜色(python颜色、python print颜色、python打印彩色文字、python print彩色、python彩色文字)