Cesium 测量距离

news2024/11/25 17:21:12

Cesium 测量距离

    • 需求
    • 分析
      • 第一种方式:使用测距 Measure
      • 第二中方式:使用 distance,自己封装
      • 第三种方式:自己封装(样式不太好)

需求

实际开发中我们经常需要用到量测工具,而Cesium没有直接提供量测功能,如何在 Cesium 中实现两点间距离测量
在这里插入图片描述

分析

第一种方式:使用测距 Measure

在Cesium中,可以使用Measure类进行测距操作。以下是测距的简单示例代码:

// 创建测量工具对象
var measure = new Cesium.Measure(viewer, {
    lineColor: Cesium.Color.YELLOW, // 线颜色
    lineOpacity: 1, // 线透明度
    lineOutline: true, // 线是否显示轮廓
    lineOutlineColor: Cesium.Color.BLACK, // 线轮廓颜色
    labelFont: '16px sans-serif', // 标签字体
    labelColor: Cesium.Color.BLACK, // 标签颜色
    labelOffset: new Cesium.Cartesian2(0, 20), // 标签偏移
    measureUnits: Cesium.MeasureUnits.METERS // 测量单位
});

// 开始测距
measure.startMeasure();

在按下鼠标左键开始绘制第一个点之后,测距工具将会创建一个用于显示测距结果的线段、标签等元素。测量结果将实时更新,直到鼠标左键抬起。

除了直接使用Measure类进行测距外,还可以使用Cesium.MeasureHandler类创建自定义的测距工具,这样可以根据具体需求进行更加详细的设置,例如支持多线段测量等。具体使用方法可以参考Cesium官方文档。

参考文献:

  • https://cesium.com/docs/cesiumjs-ref-doc/Measure.html
  • https://cesium.com/docs/cesiumjs-ref-doc/MeasureHandler.html

第二中方式:使用 distance,自己封装

  • 预览效果

在这里插入图片描述

  • 源码:
data(){
	viewer: null,
	handler: null,
	positions : [],
	entityCollection: [],
    leftClickFlag:0,//单击Flag
    centerPoint:[],//中点
    lengthText:0 , // 计算距离
},
watch: {
    leftClickFlag(val){
        if( val!==1 && val %2 == 1){
            this.addLabel(this.centerPoint, this.lengthText); 
        }
    }
},
methods:{
	 //注册鼠标事件,调用该函数实现其他方法调用
   registerEvents() {
       this.leftClickEvent();
   },

   /**
    * 添加标签
    * @param position
    * @param text
    */
   addLabel(centerPoint, text) {
       return this.viewer.entities.add(new Cesium.Entity({
           position: centerPoint,
           label: {
               text: text,
               font: '14px sans-serif',
               style: Cesium.LabelStyle.FILL_AND_OUTLINE, //FILL  FILL_AND_OUTLINE OUTLINE
               fillColor: Cesium.Color.YELLOW,
               showBackground: true, //指定标签后面背景的可见性
               backgroundColor: new Cesium.Color(0.165, 0.165, 0.165, 0.8), // 背景颜色
               backgroundPadding: new Cesium.Cartesian2(6, 6), //指定以像素为单位的水平和垂直背景填充padding
               pixelOffset: new Cesium.Cartesian2(0, -25),
               disableDepthTestDistance: Number.POSITIVE_INFINITY
           }
       }));
   },
   // 添加点
   addPoint(position) {
       return this.viewer.entities.add({
           position: position,
           point:{
               pixelSize: 10,
               color: Cesium.Color.YELLOW
           }
       });
   },
   // 添加线
   addLine(position) {
       const lonlat = [];
       for (let index = 0; index < position.length; index++) {
           const longitude =  Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(position[index]).longitude);
           const latitude =  Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(position[index]).latitude);
           lonlat.push(longitude,latitude);
       }
       console.log(lonlat)
       return this.viewer.entities.add({
           name: 'distance-line',
           polyline: {
               positions: Cesium.Cartesian3.fromDegreesArray(lonlat),
               width: 2,
               material: Cesium.Color.RED,
               // clampToGround: true
           }
       });
   },
   //逻辑代码如下
   getLengthText(firstPoint, secondPoint) {
       // 计算距离
       var length = Cesium.Cartesian3.distance(firstPoint, secondPoint);
       if (length > 1000) {
           length = (length / 1000).toFixed(2) + " 公里";
       } else {
           length = length.toFixed(2) + " 米";
       }
       return length;
   },
   //鼠标移动事件
   mouseMoveEvent() {
       var labelEntity = null; // 标签实体
       this.viewer.screenSpaceEventHandler.setInputAction((moveEvent) => {
       //var movePosition = this.viewer.scene.pickPosition(moveEvent.endPosition); // 鼠标移动的点
       var movePosition = this.viewer.scene.globe.pick(this.viewer.camera.getPickRay(moveEvent.endPosition), this.viewer.scene);
           if(!movePosition){
               return false;
           }
           if (this.positions.length == 2) {
               this.positions.pop();
               this.positions.push(movePosition);

               // 绘制label
               if (labelEntity) {
                   this.viewer.entities.remove(labelEntity);
                   this.entityCollection.splice(this.entityCollection.indexOf(labelEntity), 1);
               }
               // 计算中点
               this.centerPoint = Cesium.Cartesian3.midpoint(this.positions[0], this.positions[1], new Cesium.Cartesian3());
               // 计算距离
               this.lengthText = "距离:" + this.getLengthText(this.positions[0], this.positions[1]);

               labelEntity = this.addLabel(this.centerPoint, this.lengthText);
               this.entityCollection.push(labelEntity);
           } else {
               this.positions.push(movePosition);
               // 绘制线
               // this.addLine(this.positions);
           }
       }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
   },

	//左键点击事件
  leftClickEvent() {
      //单击鼠标左键画点点击事件
      this.viewer.screenSpaceEventHandler.setInputAction(e => {
          this.leftClickFlag +=1;
          this.viewer._element.style.cursor = 'default';
          // 坐标
          let position = this.viewer.scene.pickPosition(e.position);
          // 存储第一个点
          if (!position){
              return false;
          }
          if (this.positions.length == 0) { 
              this.positions.push(position.clone())
              //添加一个点
              this.addPoint(position);
              // 注册鼠标移动事件
              this.mouseMoveEvent();
          }else{
              // 存储第二个点
              this.positions.pop();
              this.positions.push(position);
              this.addPoint(position);
              this.addLine(this.positions);
              // 移出事件
              // this.viewer.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
              // this.viewer.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.MOUSE_MOVE);
              // this.leftClickFlag = 0;
              if(this.positions.length == 2){
                  this.positions.length = 0; //置空
                  this.leftClickFlag += 1;
              }
          }
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
  },
mounted(){
	this.viewer = window.viewer;
	this.fetchData();
},

第三种方式:自己封装(样式不太好)

  1. 新建一个MeasureTool.js文件,代码如下:
import Cesium from "cesium/Cesium";
import widgets from "cesium/Widgets/widgets.css";

export default {

    //测量空间直线距离
    /******************************************* */
    measureLineSpace(viewer, handler) {
        // 取消双击事件-追踪该位置
        viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);

        handler = new Cesium.ScreenSpaceEventHandler(viewer.scene._imageryLayerCollection);
        var positions = [];
        var poly = null;
        // var tooltip = document.getElementById("toolTip");
        var distance = 0;
        var cartesian = null;
        var floatingPoint;
        // tooltip.style.display = "block";

        handler.setInputAction(function (movement) {
            // tooltip.style.left = movement.endPosition.x + 3 + "px";
            // tooltip.style.top = movement.endPosition.y - 25 + "px";
            // tooltip.innerHTML = '<p>单击开始,右击结束</p>';
            // cartesian = viewer.scene.pickPosition(movement.endPosition);
            let ray = viewer.camera.getPickRay(movement.endPosition);
            cartesian = viewer.scene.globe.pick(ray, viewer.scene);
            //cartesian = viewer.scene.camera.pickEllipsoid(movement.endPosition, viewer.scene.globe.ellipsoid);
            if (positions.length >= 2) {
                if (!Cesium.defined(poly)) {
                    poly = new PolyLinePrimitive(positions);
                } else {
                    positions.pop();
                    // cartesian.y += (1 + Math.random());
                    positions.push(cartesian);
                }
                distance = getSpaceDistance(positions);
                // console.log("distance: " + distance);
                // tooltip.innerHTML='<p>'+distance+'米</p>';
            }
        }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

        handler.setInputAction(function (movement) {
            // tooltip.style.display = "none";
            // cartesian = viewer.scene.camera.pickEllipsoid(movement.position, viewer.scene.globe.ellipsoid);
            // cartesian = viewer.scene.pickPosition(movement.position);
            let ray = viewer.camera.getPickRay(movement.position);
            cartesian = viewer.scene.globe.pick(ray, viewer.scene);
            if (positions.length == 0) {
                positions.push(cartesian.clone());
            }
            positions.push(cartesian);
            //在三维场景中添加Label
            //   var cartographic = Cesium.Cartographic.fromCartesian(cartesian);
            var textDisance = distance + "米";
            // console.log(textDisance + ",lng:" + cartographic.longitude/Math.PI*180.0);
            floatingPoint = viewer.entities.add({
                name: '空间直线距离',
                // position: Cesium.Cartesian3.fromDegrees(cartographic.longitude / Math.PI * 180, cartographic.latitude / Math.PI * 180,cartographic.height),
                position: positions[positions.length - 1],
                point: {
                    pixelSize: 5,
                    color: Cesium.Color.RED,
                    outlineColor: Cesium.Color.WHITE,
                    outlineWidth: 2,
                },
                label: {
                    text: textDisance,
                    font: '18px sans-serif',
                    fillColor: Cesium.Color.GOLD,
                    style: Cesium.LabelStyle.FILL_AND_OUTLINE,
                    outlineWidth: 2,
                    verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
                    pixelOffset: new Cesium.Cartesian2(20, -20),
                }
            });
        }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

        handler.setInputAction(function (movement) {
            handler.destroy(); //关闭事件句柄
            positions.pop(); //最后一个点无效
            // viewer.entities.remove(floatingPoint);
            // tooltip.style.display = "none";

        }, Cesium.ScreenSpaceEventType.RIGHT_CLICK);

        var PolyLinePrimitive = (function () {
            function _(positions) {
                this.options = {
                    name: '直线',
                    polyline: {
                        show: true,
                        positions: [],
                        material: Cesium.Color.CHARTREUSE,
                        width: 10,
                        clampToGround: true
                    }
                };
                this.positions = positions;
                this._init();
            }

            _.prototype._init = function () {
                var _self = this;
                var _update = function () {
                    return _self.positions;
                };
                //实时更新polyline.positions
                this.options.polyline.positions = new Cesium.CallbackProperty(_update, false);
                viewer.entities.add(this.options);
            };

            return _;
        })();

        //空间两点距离计算函数
        function getSpaceDistance(positions) {
            var distance = 0;
            for (var i = 0; i < positions.length - 1; i++) {

                var point1cartographic = Cesium.Cartographic.fromCartesian(positions[i]);
                var point2cartographic = Cesium.Cartographic.fromCartesian(positions[i + 1]);
                /**根据经纬度计算出距离**/
                var geodesic = new Cesium.EllipsoidGeodesic();
                geodesic.setEndPoints(point1cartographic, point2cartographic);
                var s = geodesic.surfaceDistance;
                //console.log(Math.sqrt(Math.pow(distance, 2) + Math.pow(endheight, 2)));
                //返回两点之间的距离
                s = Math.sqrt(Math.pow(s, 2) + Math.pow(point2cartographic.height - point1cartographic.height, 2));
                distance = distance + s;
            }
            return distance.toFixed(2);
        }
    },

    //****************************测量空间面积************************************************//
    measureAreaSpace(viewer, handler){
        // 取消双击事件-追踪该位置
        viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
        // 鼠标事件
        handler = new Cesium.ScreenSpaceEventHandler(viewer.scene._imageryLayerCollection);
        var positions = [];
        var tempPoints = [];
        var polygon = null;
        // var tooltip = document.getElementById("toolTip");
        var cartesian = null;
        var floatingPoint;//浮动点
        // tooltip.style.display = "block";

        handler.setInputAction(function(movement){
            // tooltip.style.left = movement.endPosition.x + 3 + "px";
            // tooltip.style.top = movement.endPosition.y - 25 + "px";
            // tooltip.innerHTML ='<p>单击开始,右击结束</p>';
            // cartesian = viewer.scene.pickPosition(movement.endPosition);
            let ray = viewer.camera.getPickRay(movement.endPosition);
            cartesian = viewer.scene.globe.pick(ray, viewer.scene);
            //cartesian = viewer.scene.camera.pickEllipsoid(movement.endPosition, viewer.scene.globe.ellipsoid);
            if(positions.length >= 2){
                if (!Cesium.defined(polygon)) {
                    polygon = new PolygonPrimitive(positions);
                }else{
                    positions.pop();
                    // cartesian.y += (1 + Math.random());
                    positions.push(cartesian);
                }
                // tooltip.innerHTML='<p>'+distance+'米</p>';
            }
        },Cesium.ScreenSpaceEventType.MOUSE_MOVE);

        handler.setInputAction(function(movement){
            // tooltip.style.display = "none";
            // cartesian = viewer.scene.pickPosition(movement.position);
            let ray = viewer.camera.getPickRay(movement.position);
            cartesian = viewer.scene.globe.pick(ray, viewer.scene);
            // cartesian = viewer.scene.camera.pickEllipsoid(movement.position, viewer.scene.globe.ellipsoid);
            if(positions.length == 0) {
                positions.push(cartesian.clone());
            }
            //positions.pop();
            positions.push(cartesian);
            //在三维场景中添加点
            var cartographic = Cesium.Cartographic.fromCartesian(positions[positions.length - 1]);
            var longitudeString = Cesium.Math.toDegrees(cartographic.longitude);
            var latitudeString = Cesium.Math.toDegrees(cartographic.latitude);
            var heightString = cartographic.height;
            tempPoints.push({ lon: longitudeString, lat: latitudeString ,hei:heightString});
            floatingPoint = viewer.entities.add({
                name : '多边形面积',
                position : positions[positions.length - 1],
                point : {
                    pixelSize : 5,
                    color : Cesium.Color.RED,
                    outlineColor : Cesium.Color.WHITE,
                    outlineWidth : 2,
                    heightReference:Cesium.HeightReference.CLAMP_TO_GROUND
                }
            });
        },Cesium.ScreenSpaceEventType.LEFT_CLICK);

        handler.setInputAction(function(movement){
            handler.destroy();
            positions.pop();
            //tempPoints.pop();
            // viewer.entities.remove(floatingPoint);
            // tooltip.style.display = "none";
            //在三维场景中添加点
            // var cartographic = Cesium.Cartographic.fromCartesian(positions[positions.length - 1]);
            // var longitudeString = Cesium.Math.toDegrees(cartographic.longitude);
            // var latitudeString = Cesium.Math.toDegrees(cartographic.latitude);
            // var heightString = cartographic.height;
            // tempPoints.push({ lon: longitudeString, lat: latitudeString ,hei:heightString});

            var textArea = getArea(tempPoints) + "平方公里";
            viewer.entities.add({
                name : '多边形面积',
                position : positions[positions.length - 1],
                // point : {
                //  pixelSize : 5,
                //  color : Cesium.Color.RED,
                //  outlineColor : Cesium.Color.WHITE,
                //  outlineWidth : 2,
                //  heightReference:Cesium.HeightReference.CLAMP_TO_GROUND
                // },
                label : {
                    text : textArea,
                    font : '18px sans-serif',
                    fillColor : Cesium.Color.GOLD,
                    style: Cesium.LabelStyle.FILL_AND_OUTLINE,
                    outlineWidth : 2,
                    verticalOrigin : Cesium.VerticalOrigin.BOTTOM,
                    pixelOffset : new Cesium.Cartesian2(20, -40),
                    heightReference:Cesium.HeightReference.CLAMP_TO_GROUND
                }
            });
        }, Cesium.ScreenSpaceEventType.RIGHT_CLICK );

        var radiansPerDegree = Math.PI / 180.0;//角度转化为弧度(rad)
        var degreesPerRadian = 180.0 / Math.PI;//弧度转化为角度

        //计算多边形面积
        function getArea(points) {

            var res = 0;
            //拆分三角曲面

            for (var i = 0; i < points.length - 2; i++) {
                var j = (i + 1) % points.length;
                var k = (i + 2) % points.length;
                var totalAngle = Angle(points[i], points[j], points[k]);


                var dis_temp1 = distance(positions[i], positions[j]);
                var dis_temp2 = distance(positions[j], positions[k]);
                res += dis_temp1 * dis_temp2 * Math.abs(Math.sin(totalAngle)) ;
                console.log(res);
            }


            return (res/1000000.0).toFixed(4);
        }

        /*角度*/
        function Angle(p1, p2, p3) {
            var bearing21 = Bearing(p2, p1);
            var bearing23 = Bearing(p2, p3);
            var angle = bearing21 - bearing23;
            if (angle < 0) {
                angle += 360;
            }
            return angle;
        }
        /*方向*/
        function Bearing(from, to) {
            var lat1 = from.lat * radiansPerDegree;
            var lon1 = from.lon * radiansPerDegree;
            var lat2 = to.lat * radiansPerDegree;
            var lon2 = to.lon * radiansPerDegree;
            var angle = -Math.atan2(Math.sin(lon1 - lon2) * Math.cos(lat2), Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(lon1 - lon2));
            if (angle < 0) {
                angle += Math.PI * 2.0;
            }
            angle = angle * degreesPerRadian;//角度
            return angle;
        }

        var PolygonPrimitive = (function(){
            function _(positions){
                this.options = {
                    name:'多边形',
                    polygon : {
                        hierarchy : [],
                        // perPositionHeight : true,
                        material : Cesium.Color.GREEN.withAlpha(0.5),
                        // heightReference:20000
                    }
                };

                this.hierarchy = positions;
                this._init();
            }

            _.prototype._init = function(){
                var _self = this;
                var _update = function(){
                    return _self.hierarchy;
                };
                //实时更新polygon.hierarchy
                this.options.polygon.hierarchy = new Cesium.CallbackProperty(_update,false);
                viewer.entities.add(this.options);
            };

            return _;
        })();

        function distance(point1,point2){
            var point1cartographic = Cesium.Cartographic.fromCartesian(point1);
            var point2cartographic = Cesium.Cartographic.fromCartesian(point2);
            /**根据经纬度计算出距离**/
            var geodesic = new Cesium.EllipsoidGeodesic();
            geodesic.setEndPoints(point1cartographic, point2cartographic);
            var s = geodesic.surfaceDistance;
            //console.log(Math.sqrt(Math.pow(distance, 2) + Math.pow(endheight, 2)));
            //返回两点之间的距离
            s = Math.sqrt(Math.pow(s, 2) + Math.pow(point2cartographic.height - point1cartographic.height, 2));
            return s;
        }
    }


}
  1. 引用MeasureTool.js文件,并调用测量方法:
<template>
    <div id="cesiumContainer">

    </div>
</template>

<script>
    import MeasureTool from '../../public/js/MeasureTool'
    export default {
        name: 'CeLiang',
        components: {},
        data(){
            return{

            }
        },
        mounted() {
            let viewer = new Cesium.Viewer('cesiumContainer');
            //测量距离
            MeasureTool.measureLineSpace(viewer, null);
            //测量面积
            MeasureTool.measureAreaSpace(viewer, null);
        }
    }
</script>

<style>
    #cesiumContainer {
        width: 100%;
        height: 100%;
        margin: 0;
        padding: 0;
        overflow: hidden;
    }
</style>
  1. 效果
    在这里插入图片描述
    在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【AD操作】【原理图标注配置器】批量更新原理图的元件标签

原理图标注配置器 快捷键 T-A-A 1.调整编号顺序 2.设置起始编号 3.更新 和 执行变更 对 学习笔记&#xff0c;供自己复习参考。

Java基于微信小程序的自习室系统的设计,附源码、教程

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝30W、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 文章目录 1 简介2 技术栈3 需求分析3.1用户需求分析3.1.1 学生用户3.1.3 管理员用户 4 数据库设计4.4.1 E…

使用Chatgpt编写的PHP数据库pdo操作类(增删改查)

摘要 将PDO封装成PHP类进行调用有很多好处&#xff0c;包括&#xff1a; 1、封装性和抽象性&#xff1a; 通过将PDO封装到一个类中&#xff0c;您可以将数据库操作逻辑与应用程序的其他部分分离开来&#xff0c;提高了代码的组织性和可维护性。这样&#xff0c;您只需在一个地…

面对IT部门和业务部门跨网文件交换的不同需求,怎样才能兼顾呢?

文件交换是企业中必不可少的一环&#xff0c;无论是内部员工之间&#xff0c;还是与外部客户、供应商、合作伙伴之间&#xff0c;都需要频繁地进行文件的发送和接收。然而&#xff0c;由于企业内外网之间的隔离&#xff0c;跨网文件交换往往面临着诸多困难和挑战。如何在保证文…

【Verilog语法】比较不同计数器的运算方式,其中有一个数是延迟打一拍的效果,目的是使得两个计数器的结果相同。

比较不同计数器的运算方式&#xff0c;其中有一个数是延迟打一拍的效果&#xff0c;目的是使得两个计数器的结果相同。 1&#xff0c;第一种2&#xff0c;第二种3&#xff0c;第三种 第三种方案&#xff0c;完成实现。 1&#xff0c;第一种 &#xff08;1&#xff09;RTL modu…

基于Python开发的火车票分析助手(源码+可执行程序+程序配置说明书+程序使用说明书)

一、项目简介 本项目是一套基于Python开发的火车票分析助手&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Python学习者。 包含&#xff1a;项目源码、项目文档等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&#xff0c;…

企业如何使员工保持工作的积极性?

保持员工的工作积极性对于企业来说至关重要。激发员工的热情和投入度可以提高工作效率、创造力和团队合作&#xff0c;进而为企业带来更好的成果和竞争优势。以下是一些企业可以采取的方法来确保员工保持积极性&#xff1a; 提供发展机会 员工希望在职业生涯中不断成长和发展…

数据库管理-第105期 安装Database Valut组件(20230919)

数据库管理-第105期 安装Database Valut组件&#xff08;20230919&#xff09; 之前无论是是EXPDP还是PDB中遇到的一些问题&#xff0c;其实都跟数据库的DV&#xff08;Database Valut&#xff09;组件有关&#xff0c;因为目标库没有安装DV导致启动时会出现问题。 1 DV/OLS …

Seata 源码篇之AT模式启动流程 - 上 - 02

Seata 源码篇之AT模式启动流程 - 02 自动配置两个关键点 初始化初始化TM初始化RM初始化TC 全局事务执行流程TM 发起全局事务GlobalTransactional 注解处理全局事务的开启 TM 和 RM 执行分支事务IntroductionDelegatingIntroductionInterceptorDelegatePerTargetObjectIntroduct…

Linux开发工具之编辑器-vim

vim简单来说就是一款文本编辑器&#xff0c;用于写代码&#xff0c;更是一款多模式编辑器 vim的基本概念 vim有许多种模式&#xff0c;但是铁三角是以下三种模式&#xff1a;命令模式&#xff0c;插入模式&#xff0c;底行模式 1 正常/普通/命令模式&#xff08;默认打开&…

搭建私人图床结合内网穿透实现公网访问,让您的摄影作品连接世界

文章目录 1. 树洞外链网站搭建1.1 下载安装树洞外链1.2 树洞外链网页测试1.3 cpolar的安装和注册 2.本地网页发布2.1 Cpolar临时数据隧道2.2 Cpolar稳定隧道&#xff08;云端设置&#xff09;2.3 Cpolar稳定隧道&#xff08;本地设置&#xff09; 3.公网访问测试 社交平台具有庞…

Go 语言学习总结(9)—— Go 与 Java 全面对比总结

基本语法格式 Golang: 编码风格相对统一&#xff0c;简单&#xff0c;没有太多的语法糖等&#xff0c;Java层次清晰&#xff0c;全面面向对象。 变量相关 变量的声明及使用 在Java或者PHP、Python中&#xff0c;声明了变量&#xff0c;可以不使用&#xff0c;也不报错。 p…

win11 新建markdown文件 添加到右键新建项 无反应(已解决)

需要操作 2 处注册表 1. win R输入【regedit】 定位路径 【计算机\HKEY_CLASSES_ROOT.md】 点击.md文件夹, 双击右侧(默认)项&#xff0c;将数值数据改为【Typora.md】 右键.md文件夹 > 新建 > 项&#xff0c;把新建的项命名为【ShellNew】 右键ShellNew > 新建 >…

基于Spring Boot+ Vue的健身房管理系统与实现

小熊学Java全能学面试指南&#xff1a;https://javaxiaobear.cn 摘要 随着健身行业的快速发展&#xff0c;健身房管理系统成为了提高管理效率和用户体验的重要工具。本论文旨在设计与实现一种基于前后端分离的健身房管理系统&#xff0c;通过前后端分离的架构模式&#xff0c;…

如何代码降重

目录 一、使用的相关工具二、冗余代码的分类和压缩策略2.1 无用代码2.2 重复代码2.3 相似代码 三、长久治理机制3.1 git-hooks 一、使用的相关工具 以下工具都有各自详细说明的文档。除非有必要&#xff0c;下文不再对其相关使用作详细说明。 仓库代码查重工具&#xff1a;http…

WebStorm 2023年下载、安装教程、亲测有效

文章目录 简介安装步骤常用快捷键 简介 WebStorm 是JetBrains公司旗下一款JavaScript 开发工具。已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源&#xff0c;继承了IntelliJ IDEA强大的JS部分的…

PostgreSQL 主从复制故障切换

文章目录 前言环境准备搭建主从节点配置主从节点从节点加入主节点查看主从信息 主从故障切换 前言 PostgreSQL的主从复制是一种非常简单且常用的高可用性和可扩展性解决方案&#xff0c;本质上是将主服务器的数据复制到一个或多个从服务器上&#xff0c;从而提高系统的性能和可…

会话控制学习

文章目录 介绍cookieexpress中使用cookie获取cookie session配置区别 介绍 cookie express中使用cookie 退出登录就是删除cookie 获取cookie 添加中间键后&#xff0c;直接获取 session 配置 区别

Linux 内核代码是 AMD GPU 驱动代码

导读Linux 内核代码是 AMD GPU 驱动代码 1/7 的 Linux 内核代码是 AMD GPU 驱动代码 随着开发中的 Linux 6.6 内核增加了对更多即将推出的 Radeon 图形处理器的支持&#xff0c;现在内核中 AMD GPU 驱动代码的行数已超过 500 万行。其中很大一部分是 AMD 在每一代新版本中不断…

Python的协程异步IO(asyncio)详解

一、协程简介 1.1 定义 协程不是系统级线程&#xff0c;很多时候协程被称为“轻量级线程”、“微线程”、“纤程(fiber)”等。简单来说可以认为协程是线程里不同的函数&#xff0c;这些函数之间可以相互快速切换。 协程和用户态线程非常接近&#xff0c;用户态线程之间的切换…