拖拽和旋转

本文介绍了一种使用OpenLayers库实现地图拖拽和旋转的方法。通过整合DragRotateAndZoom交互功能,用户可以直观地操作地图视角,提升地理信息系统应用的用户体验。文章详细展示了HTML、CSS和JavaScript代码配置过程。
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>拖拽和旋转</title>
    <link rel="stylesheet"
          href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.1.1/css/ol.css"
          type="text/css">
    <script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io@master/en/v6.1.1/build/ol.js"></script>
    <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL"></script>
    <script src="https://code.jquery.com/jquery-2.2.3.min.js"></script>
    <style>
        .map {
            width: 100%;
            height: 400px;
        }
    </style>
</head>
<body>
<div id="map" class="map"></div>
<script type="text/javascript">
    var map = new ol.Map({
       interactions:ol.interaction.defaults().extend([
           new ol.interaction.DragRotateAndZoom()
       ]) ,
        layers:[
            new ol.layer.Tile({
                source:new ol.source.OSM()
            })
        ],
        target:'map',
        view:new ol.View({
            center:[0,0],
            zoom: 2
        })
    });
</script>
</body>
</html>
在 Cesium 中实现 **3D 模型的拖动旋转**,可以通过监听鼠标事件(如鼠标按下、移动、释放)并结合 `Entity` 或 `Model` 实例的属性操作来实现。Cesium 本身提供了一些基础交互功能,但如果你需要自定义的拖动旋转操作,需要自己实现交互逻辑。 --- ## ✅ 实现目标 - 点击模型后可以 **拖动模型**(平移)。 - 使用键盘 + 鼠标组合可以 **旋转模型**。 --- ## ✅ 示例代码:使用 `Entity` 实现模型拖动旋转 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <title>Cesium Model Drag and Rotate</title> <script src="https://cesium.com/downloads/cesiumjs/releases/1.111/Build/Cesium/Cesium.js"></script> <link href="https://cesium.com/downloads/cesiumjs/releases/1.111/Build/Cesium/Widgets/widgets.css" rel="stylesheet"> <style> html, body, #cesiumContainer { width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden; } </style> </head> <body> <div id="cesiumContainer"></div> <script> // 初始化 Viewer Cesium.Ion.defaultAccessToken = 'YOUR_ION_TOKEN'; // 替换为你的 token const viewer = new Cesium.Viewer('cesiumContainer', { terrain: Cesium.Terrain.fromWorldTerrain() }); // 加载模型 const position = Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883, 0); const entity = viewer.entities.add({ position: position, model: { uri: 'https://sandcastle.cesium.com/SampleData/models/CesiumAir/Cesium_Air.glb', minimumPixelSize: 128, maximumScale: 20000 } }); viewer.zoomTo(entity); // 定义变量 let isDragging = false; let isRotating = false; let lastPosition = null; let originalHeading = 0; // 获取屏幕空间事件处理器 const handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas); // 鼠标左键按下:开始拖动 handler.setInputAction((movement) => { const picked = viewer.scene.pick(movement.position); if (picked && picked.id === entity) { isDragging = true; lastPosition = movement.position.clone(); } }, Cesium.ScreenSpaceEventType.LEFT_DOWN); // 鼠标左键释放:结束拖动 handler.setInputAction(() => { isDragging = false; }, Cesium.ScreenSpaceEventType.LEFT_UP); // 鼠标移动:拖动模型 handler.setInputAction((movement) => { if (isDragging && lastPosition) { const delta = movement.endPosition.x - lastPosition.x; // 计算新的位置 const cartographic = Cesium.Cartographic.fromCartesian(entity.position.getValue()); const heading = Cesium.Math.toRadians(delta * 0.01); // 简单的平移转换为经度偏移 const newPosition = Cesium.Cartesian3.fromRadians( cartographic.longitude + heading, cartographic.latitude, cartographic.height ); entity.position = new Cesium.ConstantPositionProperty(newPosition); lastPosition = movement.endPosition.clone(); } }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); // 鼠标右键按下:开始旋转 handler.setInputAction(() => { isRotating = true; originalHeading = entity.orientation.getValue().heading || 0; }, Cesium.ScreenSpaceEventType.RIGHT_DOWN); handler.setInputAction(() => { isRotating = false; }, Cesium.ScreenSpaceEventType.RIGHT_UP); handler.setInputAction((movement) => { if (isRotating) { const deltaX = movement.endPosition.x - movement.startPosition.x; const rotation = Cesium.Math.toRadians(deltaX * 0.5); entity.orientation = new Cesium.CallbackProperty(() => { return new Cesium.QuaternionOrientationProperty( Cesium.Quaternion.fromHeadingPitchRoll( originalHeading + rotation, 0, 0 ) ); }, false); } }, Cesium.ScreenSpaceEventType.MOUSE_MOVE); </script> </body> </html> ``` --- ## 🔍 代码解释: - `viewer.entities.add({ model: { uri: ... } })`:加载一个 3D 模型。 - `ScreenSpaceEventHandler`:用于监听鼠标事件。 - `entity.position`:设置模型的当前位置。 - `entity.orientation`:设置模型的朝向(旋转)。 - `Cesium.Cartesian3.fromRadians()`:用于将经纬度转换为笛卡尔坐标。 - `Cesium.Quaternion.fromHeadingPitchRoll()`:构造一个旋转方向。 --- ## ✅ 说明 - 上面的拖动是基于经度偏移实现的,适用于简单演示。 - 旋转是基于 heading(偏航角)实现的。 - 你可以根据需求扩展为基于屏幕坐标转换为地面坐标,实现更精确的拖动。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值