Vue 中使用 Cesium 實現可拖拽點標記及坐標實時顯示功能

在 Cesium 地圖開發中,實現點標記的拖拽交互并實時顯示坐標信息是一個常見的需求。本文將詳細介紹如何在 Vue 框架中使用 Cesium 的 Primitive 方式創建點標記,并實現拖拽功能及坐標提示框跟隨效果。

先看效果圖

功能實現概述

我們將實現的功能包括:

  • 使用 Primitive 方式創建可交互的點標記
  • 實現點標記的拖拽功能(點擊選中、跟隨鼠標移動、釋放確定位置)
  • 拖拽過程中實時顯示坐標信息提示框
  • 拖拽時禁用地圖默認交互,提升操作體驗

核心技術點解析

1. 創建可拖拽點標記

使用PointPrimitiveCollection創建點集合,添加點標記并設置基本樣式:

createPoint_primitives() {// 創建點集合const pointCollection = new Cesium.PointPrimitiveCollection();// 添加點this.draggablePoint = pointCollection.add({position: Cesium.Cartesian3.fromDegrees(116.4074, 39.9042, 0), // 初始位置(北京坐標)color: Cesium.Color.RED, // 點顏色pixelSize: 30, // 點大小outlineColor: Cesium.Color.WHITE, // 輪廓顏色outlineWidth: 2, // 輪廓寬度id: 'draggable-point', // 唯一標識});// 將點集合添加到場景圖元中this.viewer.scene.primitives.add(pointCollection);// 設置點的拖動功能this.setupPointDragging();
}

2. 實現拖拽交互邏輯

拖拽功能主要通過監聽鼠標的三個事件實現:左鍵按下、鼠標移動和左鍵釋放。

左鍵按下事件

// 左鍵按下事件 - 開始拖動
handler.setInputAction((click) => {// 拾取鼠標點擊位置的對象const pickedObject = this.viewer.scene.pick(click.position);// 檢查是否拾取到了我們創建的點if (Cesium.defined(pickedObject) &&  // 確保拾取對象存在pickedObject.primitive === this.draggablePoint  // 確認是目標點) {isDragging = true;currentPoint = pickedObject.primitive;currentPoint.color = Cesium.Color.BLUE; // 改變顏色表示選中狀態// 顯示坐標提示框并更新位置this.updateTooltip(currentPoint.position);this.showCoordinates = true;this.disableMapInteraction(); // 禁用地圖默認交互}
}, Cesium.ScreenSpaceEventType.LEFT_DOWN);

這里的Cesium.defined(pickedObject)是 Cesium 提供的工具函數,用于檢查一個值是否 "已定義且非空",避免后續操作出現空指針錯誤。

鼠標移動事件

在鼠標移動時,實時更新點的位置和坐標提示框:

// 鼠標移動事件 - 更新點位置
handler.setInputAction((movement) => {if (!isDragging || !currentPoint) return;// 將鼠標位置轉換為地理坐標const ray = this.viewer.camera.getPickRay(movement.endPosition);const position = this.viewer.scene.globe.pick(ray, this.viewer.scene);if (Cesium.defined(position)) {// 更新點的位置currentPoint.position = position;// 移動時實時更新提示框位置this.updateTooltip(position);}
}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
左鍵釋放事件

拖拽結束時,恢復點的樣式并保存最終位置:

// 左鍵釋放事件 - 結束拖動
handler.setInputAction(() => {if (isDragging && currentPoint) {// 恢復點的原始顏色currentPoint.color = Cesium.Color.RED;// 獲取最終位置的經緯度const cartographic = Cesium.Cartographic.fromCartesian(currentPoint.position);const longitude = Cesium.Math.toDegrees(cartographic.longitude);const latitude = Cesium.Math.toDegrees(cartographic.latitude);console.log(`點位置已更新至: 經度 ${longitude.toFixed(4)}, 緯度 ${latitude.toFixed(4)}`);this.savePointPosition(longitude, latitude);}// 恢復地圖的默認鼠標交互this.enableMapInteraction();isDragging = false;currentPoint = null;
}, Cesium.ScreenSpaceEventType.LEFT_UP);

3. 坐標提示框跟隨功能

實現坐標提示框跟隨點移動的核心是updateTooltip方法,該方法完成兩件事:將三維坐標轉換為經緯度,以及將三維坐標轉換為屏幕坐標用于定位提示框。

updateTooltip(position) {// 1. 計算經緯度信息const cartographic = Cesium.Cartographic.fromCartesian(position);this.coordinate = {lng: Cesium.Math.toDegrees(cartographic.longitude),lat: Cesium.Math.toDegrees(cartographic.latitude),};// 2. 計算屏幕坐標(兼容不同Cesium版本)const screenPosition = Cesium.SceneTransforms.wgs84ToWindowCoordinates? Cesium.SceneTransforms.wgs84ToWindowCoordinates(this.viewer.scene,position): Cesium.SceneTransforms.worldToWindowCoordinates(this.viewer.scene,position);// 3. 設置提示框位置(偏移20px避免遮擋點)if (screenPosition) {this.tooltipPosition = {x: screenPosition.x + 20,y: screenPosition.y - 20,};}
}

4. 地圖交互控制

為了提升拖拽體驗,在拖拽過程中需要禁用地圖的默認交互,拖拽結束后再恢復:

// 禁用地圖交互的方法
disableMapInteraction() {// 禁用鼠標左鍵拖動地圖this.viewer.scene.screenSpaceCameraController.enableRotate = false;// 禁用鼠標右鍵縮放this.viewer.scene.screenSpaceCameraController.enableZoom = false;// 禁用中鍵平移this.viewer.scene.screenSpaceCameraController.enableTranslate = false;// 禁用傾斜this.viewer.scene.screenSpaceCameraController.enableTilt = false;// 禁用旋轉this.viewer.scene.screenSpaceCameraController.enableLook = false;
}// 恢復地圖交互的方法
enableMapInteraction() {// 恢復所有鼠標交互this.viewer.scene.screenSpaceCameraController.enableRotate = true;this.viewer.scene.screenSpaceCameraController.enableZoom = true;this.viewer.scene.screenSpaceCameraController.enableTranslate = true;this.viewer.scene.screenSpaceCameraController.enableTilt = true;this.viewer.scene.screenSpaceCameraController.enableLook = true;
}

完整代碼實現

下面是完整的 Vue 組件代碼,包含了上述所有功能:

高德地圖三個地址
export const mapConfig = {gaode: {url1: 'http://webst02.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scale=1&style=8', //'高德路網中文注記'url2: 'https://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}', //高德影像url3: 'http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}', //高德矢量},
};
?封裝初始化地圖實例,組件直接引用
/*** 初始化地圖實例* @param {string} url - 地圖瓦片服務的URL模板* @param {boolean} is3d - 是否啟用3D地圖模式*/
export default function initMap(url, is3d) {// 初始化地圖// 創建一個Cesium Viewer實例,綁定到ID為'cesiumContainer'的DOM元素const viewer = new Cesium.Viewer('cesiumContainer', {animation: false, // 隱藏動畫控件baseLayerPicker: false, // 隱藏基礎圖層選擇器fullscreenButton: false, // 隱藏全屏按鈕geocoder: false, // 隱藏地理編碼搜索框homeButton: false, // 隱藏主頁按鈕infoBox: false, // 隱藏信息框sceneModePicker: false, // 隱藏場景模式選擇器scene3DOnly: is3d ? true : false, // 是否啟用3D-only模式優化性能,若is3d為true則啟用sceneMode: is3d ? Cesium.SceneMode.SCENE3D : Cesium.SceneMode.SCENE2D, // 場景模式,is3d為true時使用3D場景,否則使用2D場景selectionIndicator: false, // 隱藏選擇指示器timeline: false, // 隱藏時間軸navigationHelpButton: false, // 隱藏導航幫助按鈕navigationInstructionsInitiallyVisible: false, // 初始時不顯示導航說明shouldAnimate: true, // 啟用場景動畫projection: new Cesium.WebMercatorProjection(), // 地圖投影,使用Web墨卡托投影});// 移除默認影像圖層viewer.scene.imageryLayers.remove(viewer.scene.imageryLayers.get(0));// 去除版權信息viewer._cesiumWidget._creditContainer.style.display = 'none';// 向地圖的影像圖層添加一個自定義的瓦片影像服務viewer.imageryLayers.addImageryProvider(new Cesium.UrlTemplateImageryProvider({url: url, // 瓦片服務的URL模板subdomains: ['0', '1', '2', '3'], // 子域名列表maximumLevel: 18, // 最大縮放級別}));// 初始定位viewer.camera.setView({destination: Cesium.Cartesian3.fromDegrees(118.006, 39.7128, 1500000), // (lng, lat, height)});return viewer;
}
地圖組件代碼
<template><div id="cesiumContainer" style="width: 100%; height: 100vh"><!-- 坐標信息提示框 --><divv-if="showCoordinates"class="coordinate-tooltip":style="{ left: tooltipPosition.x + 'px', top: tooltipPosition.y + 'px' }">經度: {{ coordinate.lng.toFixed(6) }}<br />緯度: {{ coordinate.lat.toFixed(6) }}</div></div>
</template><script>
import initMap from '@/config/initMap.js';
import { mapConfig } from '@/config/mapConfig';
export default {data() {return {viewer: null,showCoordinates: false,coordinate: { lng: 0, lat: 0 },tooltipPosition: { x: 0, y: 0 },};},mounted() {this.viewer = initMap(mapConfig.gaode.url3, false);this.$nextTick(async () => {await this.createPoint_primitives(); // primitives方式創建});},methods: {// 創建點標記createPoint_primitives() {// 創建點集合const pointCollection = new Cesium.PointPrimitiveCollection();// 添加點this.draggablePoint = pointCollection.add({position: Cesium.Cartesian3.fromDegrees(116.4074, 39.9042, 0),color: Cesium.Color.RED,pixelSize: 30,outlineColor: Cesium.Color.WHITE,outlineWidth: 2,id: 'draggable-point',});// 將點集合添加到場景圖元中this.viewer.scene.primitives.add(pointCollection);// 設置點的拖動功能this.setupPointDragging();},setupPointDragging() {const handler = new Cesium.ScreenSpaceEventHandler(this.viewer.canvas);let isDragging = false;let currentPoint = null;// 左鍵按下事件 - 開始拖動handler.setInputAction((click) => {const pickedObject = this.viewer.scene.pick(click.position); // 拾取鼠標點擊位置的對象// 檢查是否拾取到了目標點if (Cesium.defined(pickedObject) &&  // 確保拾取對象存在pickedObject.primitive === this.draggablePoint  // 確認是我們創建的點) {isDragging = true;currentPoint = pickedObject.primitive;currentPoint.color = Cesium.Color.BLUE; // 改變點的外觀以指示正在拖動// 初始顯示提示框并更新位置this.updateTooltip(currentPoint.position);this.showCoordinates = true;this.disableMapInteraction(); // 禁用地圖的默認鼠標交互}}, Cesium.ScreenSpaceEventType.LEFT_DOWN);// 鼠標移動事件 - 更新點位置handler.setInputAction((movement) => {if (!isDragging || !currentPoint) return;// 將鼠標位置轉換為地理坐標const ray = this.viewer.camera.getPickRay(movement.endPosition);const position = this.viewer.scene.globe.pick(ray, this.viewer.scene);if (Cesium.defined(position)) {// 更新點的位置currentPoint.position = position;// 移動時實時更新提示框位置this.updateTooltip(position);}}, Cesium.ScreenSpaceEventType.MOUSE_MOVE);// 左鍵釋放事件 - 結束拖動handler.setInputAction(() => {if (isDragging && currentPoint) {// 恢復點的原始顏色currentPoint.color = Cesium.Color.RED;// 獲取最終位置的經緯度const cartographic = Cesium.Cartographic.fromCartesian(currentPoint.position);const longitude = Cesium.Math.toDegrees(cartographic.longitude);const latitude = Cesium.Math.toDegrees(cartographic.latitude);console.log(`點位置已更新至: 經度 ${longitude.toFixed(4)}, 緯度 ${latitude.toFixed(4)}`);this.savePointPosition(longitude, latitude);}// 恢復地圖的默認鼠標交互this.enableMapInteraction();isDragging = false;currentPoint = null;}, Cesium.ScreenSpaceEventType.LEFT_UP);},// 更新提示框位置和坐標信息updateTooltip(position) {// 1. 計算經緯度信息const cartographic = Cesium.Cartographic.fromCartesian(position);this.coordinate = {lng: Cesium.Math.toDegrees(cartographic.longitude),lat: Cesium.Math.toDegrees(cartographic.latitude),};// 2. 計算屏幕坐標(兼容不同Cesium版本)const screenPosition = Cesium.SceneTransforms.wgs84ToWindowCoordinates? Cesium.SceneTransforms.wgs84ToWindowCoordinates(this.viewer.scene,position): Cesium.SceneTransforms.worldToWindowCoordinates(this.viewer.scene,position);// 3. 設置提示框位置(偏移20px避免遮擋點)if (screenPosition) {this.tooltipPosition = {x: screenPosition.x + 20,y: screenPosition.y - 20,};}},// 禁用地圖交互的方法disableMapInteraction() {// 禁用鼠標左鍵拖動地圖this.viewer.scene.screenSpaceCameraController.enableRotate = false;// 禁用鼠標右鍵縮放this.viewer.scene.screenSpaceCameraController.enableZoom = false;// 禁用中鍵平移this.viewer.scene.screenSpaceCameraController.enableTranslate = false;// 禁用傾斜this.viewer.scene.screenSpaceCameraController.enableTilt = false;// 禁用旋轉this.viewer.scene.screenSpaceCameraController.enableLook = false;},// 恢復地圖交互的方法enableMapInteraction() {// 恢復所有鼠標交互this.viewer.scene.screenSpaceCameraController.enableRotate = true;this.viewer.scene.screenSpaceCameraController.enableZoom = true;this.viewer.scene.screenSpaceCameraController.enableTranslate = true;this.viewer.scene.screenSpaceCameraController.enableTilt = true;this.viewer.scene.screenSpaceCameraController.enableLook = true;},// 保存點位置的方法(可根據實際需求實現)savePointPosition(longitude, latitude) {// 示例:可以將位置發送到服務器或保存到本地存儲console.log(`保存點位置: 經度 ${longitude}, 緯度 ${latitude}`);// 實際應用中可能會調用API// fetch('/api/save-point', {//   method: 'POST',//   body: JSON.stringify({ longitude, latitude }),// });},},beforeDestroy() {// 組件銷毀時釋放資源if (this.viewer) {this.viewer.destroy();}},
};
</script><style lang="scss" scoped>
#cesiumContainer {width: 100%;height: 100vh;touch-action: none; /* 優化移動端交互 */position: relative; /* 確保提示框定位正確 */overflow: hidden;
}
.coordinate-tooltip {position: absolute;background-color: rgba(0, 0, 0, 0.7);color: white;padding: 8px 12px;border-radius: 4px;font-size: 12px;pointer-events: none; /* 確保鼠標事件能穿透提示框 */z-index: 1000; /* 確保提示框顯示在最上層 */animation: fadeIn 0.3s ease-out; /* 淡入動畫 */
}@keyframes fadeIn {from {opacity: 0;transform: translateY(10px);}to {opacity: 1;transform: translateY(0);}
}
</style>

總結

本文詳細介紹了在 Vue 中使用 Cesium 實現可拖拽點標記及坐標實時顯示的功能。通過 Primitive 方式創建點標記,結合 Cesium 的事件處理機制實現拖拽交互,并通過坐標轉換實現提示框跟隨效果。

這種實現方式具有較好的性能表現,適用于需要在地圖上進行點位調整和標記的場景。你可以根據實際需求擴展功能,如添加拖拽范圍限制、保存歷史位置、添加更多樣式的視覺反饋等。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/88204.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/88204.shtml
英文地址,請注明出處:http://en.pswp.cn/web/88204.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

HTML 插件:構建網頁的強大工具

HTML 插件:構建網頁的強大工具 引言 HTML 插件是網頁設計中不可或缺的一部分,它們為網頁增添了豐富的交互性和動態效果。本文將深入探討 HTML 插件的概念、類型、應用及其在網頁開發中的重要性。 什么是 HTML 插件? HTML 插件,也稱為 HTML 組件或 HTML 控件,是指嵌入到…

NeRF、3DGS、2DGS下三維重建相關方法介紹及以及在實景三維領域的最新實踐

一、引言 在計算機視覺與圖形學領域&#xff0c;三維重建技術正經歷從傳統幾何建模向智能化神經表征的范式轉變。近年來&#xff0c;隨著深度學習算法的迭代、傳感器技術的進步及計算硬件的升級&#xff0c;以神經輻射場&#xff08;NeRF&#xff09;和高斯潑濺&#xff08;2D…

rt thread studio 和 KEIL對于使用rt thread 的中間件和組件,哪個更方便

下面我從中間件/組件集成和開發體驗兩個角度&#xff0c;詳細對比 RT-Thread Studio 和 Keil MDK 的便利性&#xff1a;1. 中間件和組件集成 RT-Thread Studio 集成RT-Thread生態&#xff1a;內置RT-Thread的包管理器&#xff08;RT-Thread Package Manager&#xff09;&#x…

Spring Boot 項目開發實戰:入門應用部分原理示例講解

前言Spring Boot 作為當前 Java 開發領域最流行的框架之一&#xff0c;以其 "約定優于配置" 的理念極大簡化了企業級應用的開發流程。本文將基于《Spring Boot 項目開發教程&#xff08;慕課版&#xff09;》中的資產管理系統項目&#xff0c;深入解析 Spring Boot 的…

ByteBrain x 清華 VLDB25|時序多模態大語言模型 ChatTS

資料來源&#xff1a;火山引擎-開發者社區 近年來&#xff0c;多模態大語言模型&#xff08;MLLM&#xff09;發展迅速&#xff0c;并在圖像、視頻、音頻等領域取得了突破性成果。然而&#xff0c;相較于這些研究較為成熟的模態&#xff0c;時間序列這一類型的數據與大模型結合…

WPF學習筆記(25)MVVM框架與項目實例

MVVM框架與項目實例一、MVVM框架1. 概述2. 核心組件與優勢一、MVVM項目1.普通項目2. MVVM架構3. MVVM項目實例1. 項目準備2. LoginViewModel與Login2. MainWindowViewModel4. MVVM項目優化1. BaseViewModel2. RealyCommand3. 效果展示總結一、MVVM框架 1. 概述 官方文檔&…

MySQL實操

## 基于MySQL#先啟動MySQL服務#第一次登錄[rootlocalhost ~]# mysql -uroot -P3306#密碼登錄[rootlocalhost ~]# mysql -uroot -pEnter password: Welcome to the MySQL monitor. Commands end with ; or \g.Your MySQL connection id is 9Server version: 8.0.41 Source dist…

ez_rust_writeup

一道簡單的[[rust逆向]] #rust逆向 #位運算 題目信息 文件名&#xff1a;ezrust.exe 題目附件&#xff1a;https://wwfj.lanzoul.com/iczMR30k5j4h 密碼:bueq 題目分析 1. 初步分析 這是一道Rust編寫的逆向題目。通過IDA分析可以看到&#xff0c;這是一個典型的flag驗證程序。 …

【QT】-隱式轉換 explicit用法

通俗易懂的解釋:隱式轉換 vs 顯式轉換 什么是隱式轉換? 隱式轉換就是編譯器偷偷幫你做的類型轉換,你甚至都沒意識到它發生了。 例子: cpp 運行 double x = 5; // 隱式:int → double(5 變成 5.0) int y = x * 2.5; // 隱式:double → int(截斷小數部分) 構造函數的隱…

Django核心知識點詳解:JSON、AJAX、Cookie、Session與用戶認證

1. JSON數據格式詳解1.1 什么是JSON&#xff1f;JSON&#xff08;JavaScript Object Notation&#xff09;是一種輕量級的數據交換格式&#xff0c;具有以下特點&#xff1a;獨立于語言&#xff0c;幾乎所有編程語言都支持易于人閱讀和編寫易于機器解析和生成基于文本&#xff…

[特殊字符] Python 實戰 | 批量統計中文文檔詞頻并導出 Excel

本文展示如何用 Python 腳本&#xff1a; 批量讀取文件夾中的多篇中文文檔&#xff1b; 用 jieba 分詞并統計詞頻&#xff08;過濾停用詞與單字符&#xff09;&#xff1b; 將各文檔詞頻輸出為對應 Excel 文件&#xff1b; 是文本分析、內容審查、報告編寫中的實用技巧。 &…

共享打印機(詳細操作+常見問題:需輸入用戶名密碼、無法連接等)

文章目錄一、設置打印機共享的準備工作二、Windows系統下打印機共享設置1. 啟用主機打印機共享2. 客戶端添加共享打印機三、我所遇到的問題及解決方法客戶機遇到輸入用戶名、密碼錯誤代碼 0x0000011b一、錯誤代碼 0x0000011b 的含義二、解決方法添加打印機沒成功其他問題此次打…

在 Windows 系統上配置 [go-zero](https://go-zero.dev) 開發環境教程

&#x1f4bb; 在 Windows 系統上配置 go-zero 開發環境教程 本教程將詳細介紹如何在 Windows 系統上配置 go-zero 微服務框架的開發環境&#xff0c;包括依賴安裝、路徑配置、常見問題等。 &#x1f9f1; 一、前置環境安裝 1. 安裝 Go 下載地址&#xff1a;https://go.dev/…

開源=白嫖?

國內有一個非常濃重的思想&#xff0c;開源&#xff0c;開源就是免費&#xff0c;就是白嫖&#xff0c;就是不花錢&#xff0c;白給。那么什么是開源&#xff1f;“源代碼”是軟件中大多數計算機用戶從未見過的部分;它是計算機程序員可以操縱的代碼&#xff0c;以改變一個軟件(…

2048-控制臺版本

2048控制臺版 文章目錄2048控制臺版實現效果&#xff1a;在這里插入圖片描述庫函數使用&#xff1a;初始化變量功能函數實現&#xff1a;狀態判斷函數int Judge&#xff08;&#xff09;&#xff1b;數字生成函數 bool CtreateNumber&#xff08;&#xff09;打印游戲界面 void…

提取出Wallpaper Engine壁紙的mpkg類靜態壁紙

github 地址 https://github.com/notscuffed/repkg先下載軟件2853…26目錄這樣獲取有的直接mp4格式&#xff0c;就不能用這方法準備好后 cmd 進入repkg目錄 執行 repkg extract ./294...333/scene.pkg

AI健康小屋“15分鐘服務圈”:如何重構社區健康生態?

AI健康小屋作為“15分鐘服務圈”的核心載體&#xff0c;通過技術賦能與場景重構&#xff0c;正推動社區健康生態從被動治療向主動預防、從單一服務向全周期管理轉型。那我們應該如何重構社區健康生態呢&#xff1f;服務模式創新1.全時段覆蓋AI健康小屋通過分時段服務滿足不同群…

[netty5: WebSocketFrame]-源碼分析

WebSocketFrame WebSocketFrame 是 Netty 中用于表示 WebSocket 消息幀的抽象基類&#xff0c;封裝了幀的內容、分片標志和擴展位信息&#xff0c;供各類具體幀&#xff08;如文本、二進制、控制幀&#xff09;繼承使用。 public abstract class WebSocketFrame extends Buffer…

【加解密與C】非對稱加解密(三)ECC橢圓曲線

ECC橢圓曲線的基本概念橢圓曲線密碼學&#xff08;Elliptic Curve Cryptography&#xff0c;ECC&#xff09;是一種基于橢圓曲線數學的公鑰密碼體制。與傳統的RSA相比&#xff0c;ECC在相同安全級別下使用更短的密鑰&#xff0c;計算效率更高&#xff0c;適用于資源受限的環境。…

力扣網編程150題:加油站(貪心解法)

一. 簡介 前面一篇文章使用暴力解法來解決力扣網150 題目&#xff1a;加油站。文章如下&#xff1a; 力扣網編程150題&#xff1a;加油站&#xff08;暴力解法&#xff09;-CSDN博客 暴力解法就是遍歷了所有元素作為起始點的可能&#xff0c;算法時間復雜度為 O(n*n)&#x…