📋 文章目录

  • 引言
  • 功能概述
  • 环境准备
  • 核心实现步骤
    • 地图初始化
    • 多边形绘制
    • 顶点编辑功能
    • 颜色与透明度自定义
    • 面积计算与显示
  • 常见问题解决方案
    • 多边形颜色显示异常
    • 面积标签不可见
    • 控制台alpha类型错误
    • 地图交互无法恢复
  • 完整代码
  • 总结与扩展

引言

Cesium作为一款强大的3D地理信息可视化库,在WebGIS开发中有着广泛的应用。本文将详细介绍如何在Vue框架下基于Cesium实现交互式多边形绘制与编辑功能,包括颜色自定义、透明度调整以及面积实时计算等实用功能,并解决开发过程中遇到的各种常见问题。

无论是GIS应用、智慧城市还是工程测量系统,多边形绘制都是核心功能之一。通过本文的实现方案,你将能够快速集成专业的多边形编辑工具到自己的Cesium项目中,并掌握Cesium事件处理和状态管理的最佳实践。

功能概述

本文实现的多边形工具具有以下特性:

交互式绘制:左键点击添加顶点,右键结束绘制 ✅ 顶点编辑:拖拽顶点实时调整多边形形状 ✅ 样式自定义:支持颜色选择和透明度调整 ✅ 面积计算:自动计算并显示多边形面积(平方公里) ✅ 交互控制:绘制/编辑时禁用地图默认交互,完成后恢复

环境准备

在开始之前,请确保你的项目中已安装以下依赖:

# 安装Cesium
npm install cesium --save# 安装Turf.js用于面积计算
npm install @turf/turf --save

核心实现步骤

1. 地图初始化

首先,我们需要初始化Cesium地图实例。在Vue组件的mounted钩子中完成地图的加载:

import initMap from '@/config/initMap.js';
import { mapConfig } from '@/config/mapConfig';export default {data() {return {viewer: null,// 绘制状态管理isDrawing: false,isEditing: false,currentPolygon: null,polygonPoints: [],dynamicPoints: [],vertexEntities: [],vertexHandlers: [], // 顶点事件处理器数组handler: null,polygonColor: '#0000FF', // 默认蓝色polygonAlpha: 0.5,       // 默认透明度areaLabel: null          // 面积标签实体};},mounted() {// 初始化地图this.viewer = initMap(mapConfig.gaode.url3, false);// 初始化绘制处理器this.initDrawHandler();}
}

2. 多边形绘制

多边形绘制是通过监听鼠标事件实现的,主要分为三个阶段:

  1. 左键点击:添加顶点并更新多边形
  2. 鼠标移动:动态显示多边形轮廓
  3. 右键点击:结束绘制并创建最终多边形

核心代码实现:

// 开始绘制多边形
startDrawPolygon() {if (this.isEditing) this.stopEditPolygon();this.isDrawing = true;this.polygonPoints = [];this.dynamicPoints = [];this.disableMapInteraction();// 左键点击添加顶点this.handler.setInputAction(this.handleLeftClick, Cesium.ScreenSpaceEventType.LEFT_CLICK);// 鼠标移动更新动态轮廓this.handler.setInputAction(this.handleMouseMove, Cesium.ScreenSpaceEventType.MOUSE_MOVE);// 右键结束绘制this.handler.setInputAction(this.handleRightClick, Cesium.ScreenSpaceEventType.RIGHT_CLICK);// 创建动态多边形实体this.createDynamicPolygon();
},// 创建动态多边形(绘制过程中的临时多边形)
createDynamicPolygon() {// 移除已存在的动态多边形if (this.currentPolygon) {this.viewer.entities.remove(this.currentPolygon);}this.currentPolygon = this.viewer.entities.add({polygon: {hierarchy: new Cesium.CallbackProperty(() => {return new Cesium.PolygonHierarchy(this.dynamicPoints);}, false),material: Cesium.Color.RED.withAlpha(0.3),outline: true,outlineColor: Cesium.Color.RED}});
}

3. 顶点编辑功能

编辑功能允许用户通过拖拽顶点来调整多边形形状,实现思路是为每个顶点创建可交互的点实体,并监听其拖拽事件:

// 为每个顶点添加拖拽事件
addVertexDragHandler(vertexEntity, index) {const vertexHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);// 将处理器存储到数组,以便后续销毁this.vertexHandlers.push(vertexHandler);vertexHandler.setInputAction((event) => {const pick = this.viewer.scene.pick(event.position);if (Cesium.defined(pick) && pick.id === vertexEntity) {// 开始拖拽const moveHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);moveHandler.setInputAction((moveEvent) => {const newCartesian = this.getCartesianFromMouse(moveEvent.endPosition);if (newCartesian) {// 更新顶点位置this.polygonPoints[index] = newCartesian;vertexEntity.position.setValue(newCartesian);// 更新多边形this.currentPolygon.polygon.hierarchy.setValue(new Cesium.PolygonHierarchy(this.polygonPoints));// 更新面积显示this.calculateAndShowArea();}}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);// 结束拖拽vertexHandler.setInputAction(() => {moveHandler.destroy();}, Cesium.ScreenSpaceEventType.LEFT_UP);}}, Cesium.ScreenSpaceEventType.LEFT_DOWN);
}

4. 颜色与透明度自定义

通过添加颜色选择器和透明度滑块,允许用户自定义多边形样式:

// 更新多边形样式
updatePolygonStyle() {if (!this.currentPolygon) return;try {const color = Cesium.Color.fromCssColorString(this.polygonColor).withAlpha(this.polygonAlpha);this.currentPolygon.polygon.material = color;} catch (e) {console.error('颜色解析错误:', e);// 使用默认颜色作为fallbackthis.currentPolygon.polygon.material = Cesium.Color.BLUE.withAlpha(0.5);}
}

5. 面积计算与显示

使用Turf.js库计算多边形面积,并在多边形中心显示面积标签:

// 计算并显示多边形面积
calculateAndShowArea() {try {if (this.polygonPoints.length < 3) return;// 将笛卡尔坐标转换为经纬度const coordinates = this.polygonPoints.map(cartesian => {const cartographic = Cesium.Cartographic.fromCartesian(cartesian);return [Cesium.Math.toDegrees(cartographic.longitude),Cesium.Math.toDegrees(cartographic.latitude)];});// 闭合多边形coordinates.push(coordinates[0]);// 使用Turf.js计算面积const polygon = turf.polygon([coordinates]);const areaSquareMeters = turf.area(polygon);const areaSquareKm = areaSquareMeters / 1000000;const areaText = `面积: ${areaSquareKm.toFixed(4)} 平方公里`;// 显示面积标签this.showAreaLabel(areaText);} catch (e) {console.error('面积计算错误:', e);this.showAreaLabel('面积计算失败');}
},// 在多边形中心显示面积标签
showAreaLabel(text) {// 移除旧标签if (this.areaLabel) {this.viewer.entities.remove(this.areaLabel);}// 计算多边形中心点const center = this.calculatePolygonCenter();// 创建新标签this.areaLabel = this.viewer.entities.add({position: center,label: {text: text,font: '16px sans-serif',fillColor: Cesium.Color.YELLOW,backgroundColor: Cesium.Color.BLACK.withAlpha(0.7),padding: new Cesium.Cartesian2(12, 8),horizontalOrigin: Cesium.HorizontalOrigin.CENTER,verticalOrigin: Cesium.VerticalOrigin.CENTER,disableDepthTestDistance: Number.POSITIVE_INFINITY,outline: true,outlineColor: Cesium.Color.WHITE,outlineWidth: 1}});
}

常见问题解决方案

在开发过程中,我们可能会遇到以下问题:

1. 多边形颜色显示异常

问题:设置颜色后多边形显示为白色或不生效。

解决方案

  • 确保颜色值是有效的CSS颜色字符串
  • 检查透明度值是否为数字类型
  • 添加错误处理和默认颜色 fallback
// 安全的颜色设置方法
try {const color = Cesium.Color.fromCssColorString(this.polygonColor).withAlpha(Number(this.polygonAlpha) || 0.5); // 确保alpha为数字this.currentPolygon.polygon.material = color;
} catch (e) {console.error('颜色解析错误:', e);// 使用默认颜色作为fallbackthis.currentPolygon.polygon.material = Cesium.Color.BLUE.withAlpha(0.5);
}

2. 面积标签不可见

问题:面积标签不显示或被地形遮挡。

解决方案

  • 提升标签高度,避免被地形遮挡
  • 使用醒目颜色和背景提高可见性
  • 设置disableDepthTestDistance确保标签始终显示在最前面
// 计算中心点时提升高度
calculatePolygonCenter() {// ... 经纬度计算逻辑 ...// 将中心点转换回笛卡尔坐标,并提升高度return Cesium.Cartesian3.fromDegrees(centerLon, centerLat, 50); // 提升50米高度
}

3. 控制台alpha类型错误

问题Expected alpha to be typeof number, actual typeof was string

解决方案

  • 确保透明度值为数字类型
  • 在Vue中使用.number修饰符或手动转换类型
<!-- Vue模板中 -->
<input type="range" v-model.number="polygonAlpha" min="0" max="1" step="0.1">

4. 地图交互无法恢复

问题:结束绘制或编辑后,地图依然不能缩放或移动。

解决方案

  • 增强交互恢复方法,确保所有控制参数被正确设置
  • 管理所有事件处理器的生命周期,确保完全销毁
  • 在所有退出路径调用交互恢复方法
 
// 恢复地图交互(增强版)
enableMapInteraction() {const controller = this.viewer.scene.screenSpaceCameraController;// 确保所有输入被启用controller.enableInputs = true;// 恢复所有相机控制controller.enableRotate = true;controller.enableZoom = true;controller.enableTranslate = true;controller.enableTilt = true;controller.enableLook = true;console.log("地图交互已完全恢复");
},// 停止编辑多边形(修复版)
stopEditPolygon() {this.isEditing = false;// 销毁所有顶点拖拽事件处理器this.vertexHandlers.forEach(handler => {if (handler && !handler.isDestroyed()) {handler.destroy();}});this.vertexHandlers = []; // 清空处理器数组this.enableMapInteraction();
}

完整代码

Vue组件代码

<template><div id="cesiumContainer" style="width: 100%; height: 100vh"><div class="polygon-controls"><label>多边形颜色:</label><input type="color" v-model="polygonColor" @input="updatePolygonStyle" /><label>透明度:</label><inputtype="range"min="0"max="1"step="0.1"v-model.number="polygonAlpha"@input="updatePolygonStyle"/></div><div class="">结束绘制</div></div>
</template><script>
import initMap from '@/config/initMap.js';
import { mapConfig } from '@/config/mapConfig';
// import * as Cesium from 'cesium';
import * as turf from '@turf/turf';export default {data() {return {viewer: null,// 绘制状态管理isDrawing: false,isEditing: false,currentPolygon: null,polygonPoints: [],dynamicPoints: [],vertexEntities: [],handler: null,polygonColor: '#0000FF', // 默认蓝色polygonAlpha: 0.5, // 默认透明度areaLabel: null, // 面积标签实体vertexHandlers: [], // 新增:存储顶点拖拽事件处理器};},mounted() {this.viewer = initMap(mapConfig.gaode.url3, false);this.initDrawHandler();},methods: {// 初始化绘制事件处理器initDrawHandler() {this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);this.startDrawPolygon();},// 开始绘制多边形startDrawPolygon() {console.log('开始绘制多边形');if (this.isEditing) this.stopEditPolygon();this.isDrawing = true;this.polygonPoints = [];this.dynamicPoints = [];this.disableMapInteraction();// 左键点击添加顶点this.handler.setInputAction(this.handleLeftClick,Cesium.ScreenSpaceEventType.LEFT_CLICK);// 鼠标移动更新动态轮廓this.handler.setInputAction(this.handleMouseMove,Cesium.ScreenSpaceEventType.MOUSE_MOVE);// 右键结束绘制this.handler.setInputAction(this.handleRightClick,Cesium.ScreenSpaceEventType.RIGHT_CLICK);// 创建动态多边形实体this.createDynamicPolygon();},// 处理左键点击添加顶点handleLeftClick(event) {const cartesian = this.getCartesianFromMouse(event.position);if (!cartesian) return;this.polygonPoints.push(cartesian);this.dynamicPoints.push(cartesian);// 添加顶点标记this.addVertexMarker(cartesian);},// 处理鼠标移动更新轮廓handleMouseMove(event) {if (this.polygonPoints.length === 0 || !this.isDrawing) return;const cartesian = this.getCartesianFromMouse(event.endPosition);if (!cartesian) return;// 更新动态点if (this.dynamicPoints.length > this.polygonPoints.length) {this.dynamicPoints.pop();}this.dynamicPoints.push(cartesian);},// 处理右键结束绘制handleRightClick() {if (this.polygonPoints.length < 3) {alert('至少需要3个顶点才能形成多边形');this.clearDrawing();return;}// 移除动态点this.dynamicPoints.pop();this.isDrawing = false;// 保存最终多边形this.saveFinalPolygon();// 清除临时事件this.handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);this.handler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);this.handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK);// 开启编辑模式this.startEditPolygon();// 确保交互已恢复(双重保险)setTimeout(() => {this.enableMapInteraction();}, 100);},// 开始编辑多边形startEditPolygon() {this.isEditing = true;this.disableMapInteraction();// 为每个顶点添加拖拽事件this.vertexEntities.forEach((vertex, index) => {this.addVertexDragHandler(vertex, index);});},// 添加顶点拖拽事件addVertexDragHandler(vertexEntity, index) {const vertexHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);// 将处理器存储到数组,以便后续销毁this.vertexHandlers.push(vertexHandler);vertexHandler.setInputAction((event) => {const pick = this.viewer.scene.pick(event.position);if (Cesium.defined(pick) && pick.id === vertexEntity) {// 开始拖拽const moveHandler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);moveHandler.setInputAction((moveEvent) => {const newCartesian = this.getCartesianFromMouse(moveEvent.endPosition);if (newCartesian) {// 更新顶点位置this.polygonPoints[index] = newCartesian;vertexEntity.position.setValue(newCartesian);// 更新多边形this.currentPolygon.polygon.hierarchy.setValue(new Cesium.PolygonHierarchy(this.polygonPoints));// 更新面积显示this.calculateAndShowArea();}}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);// 结束拖拽vertexHandler.setInputAction(() => {moveHandler.destroy();}, Cesium.ScreenSpaceEventType.LEFT_UP);}}, Cesium.ScreenSpaceEventType.LEFT_DOWN);},// 停止编辑多边形stopEditPolygon() {this.isEditing = false;// 销毁所有顶点拖拽事件处理器this.vertexHandlers.forEach((handler) => {if (handler && !handler.isDestroyed()) {handler.destroy();}});this.vertexHandlers = []; // 清空处理器数组this.enableMapInteraction();},// 创建动态多边形createDynamicPolygon() {// 移除已存在的动态多边形if (this.currentPolygon) {this.viewer.entities.remove(this.currentPolygon);}this.currentPolygon = this.viewer.entities.add({polygon: {hierarchy: new Cesium.CallbackProperty(() => {return new Cesium.PolygonHierarchy(this.dynamicPoints);}, false),material: Cesium.Color.RED.withAlpha(0.3), // 绘制过程中使用红色outline: true,outlineColor: Cesium.Color.RED,},});},// 保存最终多边形(修复重复定义问题)saveFinalPolygon() {// 移除动态多边形this.viewer.entities.remove(this.currentPolygon);try {// 验证颜色和透明度console.log('当前颜色值:',this.polygonColor,'透明度:',this.polygonAlpha);const color = Cesium.Color.fromCssColorString(this.polygonColor).withAlpha(Number(this.polygonAlpha) || 0.5);// 创建最终多边形,应用自定义颜色和透明度this.currentPolygon = this.viewer.entities.add({polygon: {hierarchy: new Cesium.PolygonHierarchy(this.polygonPoints),material: color,outline: true,outlineColor: Cesium.Color.BLACK,outlineWidth: 2,},});// 计算并显示面积this.calculateAndShowArea();} catch (e) {console.error('创建多边形失败:', e);// 使用默认颜色作为fallbackthis.currentPolygon = this.viewer.entities.add({polygon: {hierarchy: new Cesium.PolygonHierarchy(this.polygonPoints),material: Cesium.Color.BLUE.withAlpha(0.5),outline: true,outlineColor: Cesium.Color.BLACK,},});}},// 添加顶点标记addVertexMarker(position) {const vertexEntity = this.viewer.entities.add({position: position,point: {pixelSize: 10,color: Cesium.Color.YELLOW,outlineColor: Cesium.Color.BLACK,outlineWidth: 2,disableDepthTestDistance: Number.POSITIVE_INFINITY,},});this.vertexEntities.push(vertexEntity);},// 从鼠标位置获取笛卡尔坐标getCartesianFromMouse(position) {const ray = this.viewer.camera.getPickRay(position);if (!ray) return null;return this.viewer.scene.globe.pick(ray, this.viewer.scene);},// 清除绘制状态clearDrawing() {this.isDrawing = false;this.polygonPoints = [];this.dynamicPoints = [];if (this.currentPolygon) {this.viewer.entities.remove(this.currentPolygon);}this.vertexEntities.forEach((vertex) =>this.viewer.entities.remove(vertex));this.vertexEntities = [];if (this.areaLabel) {this.viewer.entities.remove(this.areaLabel);this.areaLabel = null;}this.enableMapInteraction();},// 更新多边形样式updatePolygonStyle() {if (!this.currentPolygon) return;try {const color = Cesium.Color.fromCssColorString(this.polygonColor).withAlpha(Number(this.polygonAlpha) || 0.5);this.currentPolygon.polygon.material = color;console.log('样式更新成功:', color);} catch (e) {console.error('颜色解析错误:', e);this.currentPolygon.polygon.material = Cesium.Color.BLUE.withAlpha(0.5);}},// 计算并显示多边形面积calculateAndShowArea() {try {if (this.polygonPoints.length < 3) return;// 将笛卡尔坐标转换为经纬度const coordinates = this.polygonPoints.map((cartesian) => {const cartographic = Cesium.Cartographic.fromCartesian(cartesian);return [Cesium.Math.toDegrees(cartographic.longitude),Cesium.Math.toDegrees(cartographic.latitude),];});// 确保多边形闭合if (coordinates.length > 0 &&!(coordinates[0][0] === coordinates[coordinates.length - 1][0] &&coordinates[0][1] === coordinates[coordinates.length - 1][1])) {coordinates.push([...coordinates[0]]);}// 使用Turf.js计算面积const polygon = turf.polygon([coordinates]);const areaSquareMeters = turf.area(polygon);const areaSquareKm = areaSquareMeters / 1000000;const areaText = `面积: ${areaSquareKm.toFixed(4)} 平方公里`;console.log('计算面积:', areaText);// 显示面积标签this.showAreaLabel(areaText);} catch (e) {console.error('面积计算错误:', e);this.showAreaLabel('面积计算失败');}},// 在多边形中心显示面积标签(优化版本)showAreaLabel(text) {// 移除旧标签if (this.areaLabel) {this.viewer.entities.remove(this.areaLabel);}// 计算多边形中心点(优化算法)const center = this.calculatePolygonCenter();// 创建新标签,增强可见性this.areaLabel = this.viewer.entities.add({position: center,label: {text: text,font: '16px sans-serif',fillColor: Cesium.Color.YELLOW, // 使用醒目颜色backgroundColor: Cesium.Color.BLACK.withAlpha(0.8), // 增强对比度padding: new Cesium.Cartesian2(12, 8),horizontalOrigin: Cesium.HorizontalOrigin.CENTER,verticalOrigin: Cesium.VerticalOrigin.CENTER,disableDepthTestDistance: Number.POSITIVE_INFINITY, // 始终显示在最前面pixelOffset: new Cesium.Cartesian2(0, 0),outline: true,outlineColor: Cesium.Color.WHITE,outlineWidth: 1,},});},// 计算多边形中心点(更可靠的方法)calculatePolygonCenter() {if (this.polygonPoints.length === 0) return Cesium.Cartesian3.ZERO;// 计算经纬度平均值let totalLon = 0,totalLat = 0;const cartographics = this.polygonPoints.map((cartesian) =>Cesium.Cartographic.fromCartesian(cartesian));cartographics.forEach((cartographic) => {totalLon += Cesium.Math.toDegrees(cartographic.longitude);totalLat += Cesium.Math.toDegrees(cartographic.latitude);});const centerLon = totalLon / cartographics.length;const centerLat = totalLat / cartographics.length;// 将中心点转换回笛卡尔坐标,并提升高度避免被地形遮挡return Cesium.Cartesian3.fromDegrees(centerLon, centerLat, 50);},// 禁用地图交互disableMapInteraction() {const controller = this.viewer.scene.screenSpaceCameraController;controller.enableRotate = false;controller.enableZoom = false;controller.enableTranslate = false;controller.enableTilt = false;controller.enableLook = false;},// 恢复地图交互enableMapInteraction() {const controller = this.viewer.scene.screenSpaceCameraController;// 确保所有输入被启用controller.enableInputs = true;// 恢复所有相机控制controller.enableRotate = true;controller.enableZoom = true;controller.enableTranslate = true;controller.enableTilt = true;controller.enableLook = true;// 重置鼠标事件处理if (this.handler) {this.handler.destroy();this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);}console.log('地图交互已完全恢复');},},beforeDestroy() {if (this.viewer) {this.viewer.destroy();}if (this.handler) {this.handler.destroy();}// 移除控制面板const controlPanel = document.querySelector('.polygon-controls');if (controlPanel) {controlPanel.remove();}},
};
</script>

CSS样式

<style lang="scss" scoped>
#cesiumContainer {width: 100%;height: 100vh;touch-action: none;.polygon-controls {position: absolute;top: 20px;right: 20px;z-index: 1000;background: white;padding: 15px;border-radius: 5px;box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);}.polygon-controls label {display: block;margin: 10px 0 5px;font-weight: bold;}.polygon-controls input {width: 100%;margin-bottom: 10px;}
}
</style>

总结与扩展

本文详细介绍了如何基于Cesium和Vue实现交互式多边形绘制与编辑功能,包括核心功能实现、样式自定义和面积计算等关键技术点。特别解决了开发过程中常见的颜色显示异常、标签不可见、类型错误和交互无法恢复等问题。

通过事件监听、动态属性更新和地理空间计算,我们构建了一个功能完善的多边形编辑工具。重点强调了事件处理器生命周期管理和状态控制的最佳实践,这些经验对于开发复杂Cesium交互功能具有普遍参考价值。

功能扩展方向

  1. 添加删除功能:允许用户删除多边形或单个顶点
  2. 支持多个多边形:管理多个多边形图层
  3. 导入导出:支持GeoJSON格式导入导出
  4. 测量工具:添加距离测量、角度测量等功能
  5. 样式库:预设多种多边形样式供选择
  6. 撤销/重做:实现操作历史记录功能

希望本文能帮助你快速掌握Cesium多边形绘制技术,如果有任何问题或建议,欢迎在评论区留言讨论!

原创不易,转载请注明出处
如果本文对你有帮助,别忘了点赞和关注哦!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/news/914080.shtml
繁体地址,请注明出处:http://hk.pswp.cn/news/914080.shtml
英文地址,请注明出处:http://en.pswp.cn/news/914080.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SQL判断先判断条件1是否符合,条件1不符合再判断条件2

伪代码假设存在条件1和条件2SELECT * FROM table1 WHERE 条件1 AND 条件2方法1&#xff1a;先判断条件1是否符合,条件1不符合再判断条件2是否满足&#xff1a;SELECT * FROM table1 WHERE (条件1) OR (NOT 条件1 AND 条件2);方法 2: 使用 IF 或数据库特有函数&#xff08;…

游戏的程序员会不会偷偷改自己账号的数据?

看到这个问题&#xff0c;我忍不住笑了。 作为一个在程序员这条路上摸爬滚打了快10年的老司机&#xff0c;虽然我主要专精嵌入式开发&#xff0c;但我也接触过不少游戏开发的朋友&#xff0c;对游戏行业的内部运作有一定了解。这个问题可以说是每个游戏玩家都曾经想过的&#x…

uniapp小程序tabbar跳转拦截与弹窗控制

一、第一步1、App.vue中定义globalData用于全局存储状态globalData:{needShowReleaseConfirm: false, // 标记是否需要显示发布页面确认弹窗allowReleaseJump: false ,// 标记是否允许跳转到发布页面},2、在App.vue中的onLaunch写入监听事件onLaunch: function() {// 添加switc…

华为网路设备学习-26(BGP协议 一)

一、AS&#xff08;自治系统&#xff09;AS&#xff08;自治系统&#xff09;的大小通常指其分配的唯一编号&#xff0c;范围分为两种&#xff1a;‌2字节AS号‌&#xff1a;取值范围1至65535&#xff08;其中64512-65535为私有AS号&#xff09; ‌‌4字节AS号‌&#xff1a;取…

大模型开发框架LangChain之函数调用

1.前言 之前一直使用 dify开发 agent&#xff0c;虽然功能很全面、效果也稳定&#xff0c;但是也存在流程固化、不灵活&#xff0c;以及 dify本身太重&#xff08;内部包含10个容器&#xff09;等问题。 故最近研究了大名顶顶的 langchain&#xff0c;先从函数调用开始&#xf…

pycharm中自动补全方法返回变量

使用IDEA开发java中&#xff0c;可以使用altenter 快捷键快速补全方法放回的变量使用pycharm也想实现此效果&#xff0c;如下图操作方法&#xff1a;pycharm中默认的补全方法返回变量的快捷键是&#xff1a;CtrlAltv 可以直接使用默认快捷键&#xff0c;也可以在settings->k…

Set 二分 -> 剑指算法竞赛

C【STL】集合set 标准库提供 set 关联容器分为&#xff1a; 按关键字有序保存元素&#xff1a;set&#xff08;关键字即值&#xff0c;即只保存关键字的容器&#xff09;、multiset&#xff08;关键字可重复出现的 set&#xff09;&#xff1b; 无序集合&#xff1a;unordered…

php的原生类

前言&#xff1a;累麻了&#xff01; 反射类 反射类 ReflectionClass&#xff1a;ReflectionClass 类报告了一个类的有关信息。正如其名用于映射反射一个类的类&#xff01; new ReflectionClass(MyClass) 会创建一个 ReflectionClass 实例&#xff0c;代表 MyClass 这个类。 …

PC网站和uniapp安卓APP、H5接入支付宝支付

首先我们需要完成支付宝账号注册&#xff0c;支持的账号类型&#xff1a;支付宝企业账号、支付宝个人账号、个体工商户。 到支付宝商家平台 产品中心开通APP支付、手机网站支付、电脑网站支付的产品权限。 一、电脑PC网站接入 电脑PC网站支付是指商户在电脑网页展示商品或服务&…

MCU芯片内部的ECC安全机制

MCU&#xff08;微控制器单元&#xff09;芯片内部的 ECC&#xff08;错误检测与纠正&#xff09;安全机制 是一种至关重要的硬件级可靠性技术&#xff0c;主要用于保护关键存储单元&#xff08;如 SRAM、Flash、Cache&#xff09;中的数据完整性&#xff0c;防止因外部干扰或硬…

【自动驾驶】经典LSS算法解析——深度估计

LSS-Lift.Splat,Shoot 论文题目&#xff1a;Lift, Splat, Shoot: Encoding Images From Arbitrary Camera Rigs by Implicitly Unprojecting to 3D 代码&#xff1a;https://github.com/nv-tlabs/lift-splat-shoot 概括&#xff1a;先做深度估计和特征融合&#xff0c;然后投…

《【第八篇-图片总结篇】Python图片处理自动化:终极工厂!从裁剪压缩到智能加水印,打造你的视觉内容生产流水线!》

在数字时代&#xff0c;图片无处不在。然而&#xff0c;高质量的图片背后&#xff0c;往往隐藏着繁琐的后期处理&#xff1a;图片文件太大导致加载慢&#xff1b;尺寸不符需要裁剪&#xff1b;版权保护要加水印&#xff1b; 为了兼容性还得批量转换格式……这些重复、机械的工…

frame 与新窗口切换操作【selenium 】

&#x1f9ed; 一、切换到 iframe 内部进行操作在浏览器自动化测试中&#xff0c;iframe 是一个特别的存在。它相当于在当前页面中嵌入了另一个独立的 HTML 页面。当我们试图直接访问 iframe 中的元素时&#xff0c;往往会发现定位不到&#xff0c;比如&#xff1a;elements w…

MYSQL C_API使用全解

文章目录C_API&#xff08;简单的&#xff09;安装这个库使用流程初始化连接mysql_init建立连接mysql_real_connect执行SQL语句mysql_query处理结果mysql_store_resultmsyql_use_resultmysql_num_rowsmsyql_free_resultmysql_num_fieldsmysql_fetch_row多线程安全关闭连接mysql…

闲庭信步使用图像验证平台加速FPGA的开发:第二课——RGB转YCbCr的FPGA硬件编程详解

&#xff08;本系列只需要modelsim即可完成数字图像的处理&#xff0c;每个工程都搭建了全自动化的仿真环境&#xff0c;只需要双击文件就可以完成整个的仿真&#xff0c;大大降低了初学者的门槛&#xff01;&#xff01;&#xff01;&#xff01;如需要该系列的工程文件请关注…

RK3566/RK3568 Android11 修改selinux模式

概述RK3566/RK3568 Android11 SDK默认的selinux是Enforcing模式(强制模式)。Enforcing&#xff1a;强制模式&#xff1a;SELinux在运行中&#xff0c;且已经开始限制domain/type之间的验证关系 Permisssive&#xff1a;宽容模式&#xff1a;SELinux在运行中&#xff0c;如果验证…

iOS Widget 开发-3:Widget 的种类与尺寸(主屏、锁屏、灵动岛)

iOS 支持多种类型的 Widget&#xff0c;分布在主屏幕、锁屏、灵动岛、待机模式、控制中心等多个系统位置。每种 Widget 都有各自的尺寸、交互能力与限制。 本篇将系统梳理 iOS 当前支持的 Widget 类型与尺寸规格。主屏 Widget&#xff08;Home Screen Widgets&#xff09; 主屏…

ffmpeg 中 write_option()函数详细注释

author: hjjdebug date: 2025年 07月 11日 星期五 10:51:23 CST descrip: ffmpeg 中 write_option()函数详细注释 文章目录1. 函数原型1.1 参数说明1.2 SpecifierOpt 说明符选项结构2. write_option 代码注释2.1 谁调用了write_option 函数?3. 小结:write_option()不仅在ffmpe…

PandaCoder重大产品更新-引入Jenkinsfile文件支持

写在前面 安装这个插件可以直接平替 Jenkinsfile Pro &#xff0c;节省200元关于插件介绍的处女篇&#xff1a;https://mp.weixin.qq.com/s/fwMEhmx8vxVlvfnipx09Ag为什么叫「熊猫编码助手」&#xff1f; 熊猫是中国的国宝&#xff0c;备受世界喜爱&#xff0c;代表着中国特色和…

链表算法之【判断链表中是否有环】

目录 LeetCode-141题 LeetCode-141题 给定一个链表的头节点&#xff0c;判断链表中是否存在环 class Solution {public boolean hasCycle(ListNode head) {// checkif (head null || head.next null)return false;// 定义两个指针&#xff0c;一个快指针[fast]&#xff0c…