Cesium實戰:交互式多邊形繪制與編輯功能完全指南(最終修復版)

📋 文章目錄

  • 引言
  • 功能概述
  • 環境準備
  • 核心實現步驟
    • 地圖初始化
    • 多邊形繪制
    • 頂點編輯功能
    • 顏色與透明度自定義
    • 面積計算與顯示
  • 常見問題解決方案
    • 多邊形顏色顯示異常
    • 面積標簽不可見
    • 控制臺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…