掌握高效绘制地图的利器——LeafletJs

news2024/12/29 10:48:21

文章目录

  • 前言
  • 一、leafletJs是什么?
  • 二、快速入门
      • 1、安装
      • 2、快速入门
  • 三、进阶学习
    • 1、Map 控件
    • 2、Marker 标记
    • 3、Popup 弹出窗口
    • 4、图层
  • 四、项目实战
    • 封装文件
    • 4.1 基础点位图
    • 4.2 行驶轨迹图


前言

GIS 作为获取、存储、分析和管理地理空间数据的重要工具,用 GIS 技术绘制地图比用传统的手工操作或自动制图工具更加灵活。今天给大家分享一个专为 GIS 客户端开发提供的 JavaScript 类库包 — leafletJs


一、leafletJs是什么?

引用官方的话来说,Leaflet 是一个开源且对移动端友好的交互式地图 JavaScript 库。并且拥有绝大部分开发者所需要的所有地图特性。而且 Leaflet 可以高效的运行在桌面和移动平台,拥有着大量的扩展插件、优秀的文档、简单易用的 API 和完善的案例,以及可读性较好的源码。中文文档地址:https://leafletjs.cn/reference.html


二、快速入门

1、安装

leafletJs 提供了两种方式引入,大家可根据个人需求任选其一。

方式一:直接引入使用

<link rel = "stylesheet" href = "http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css" />
<script src = "http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>

方式二:npm 安装

npm install leaflet --save
cnpm install leaflet --save

main.js 引入并注册

import Leaflet from 'leaflet'
import "leaflet/dist/leaflet.css"
Vue.use(Leaflet);

2、快速入门

2.1. 准备一个 div 容器,一定要有宽高。

<div class="oilMap" id="oilMap"></div>

2.2. data 中定义一个地图实例

data() {
  return {
    map: null,
  };
},

2.3. 初始化地图实例

mounted() {
  this.initMap(); 
},

// 地图初始化
initMap() {
  // 使用 id 为 map 的 div 容器初始化地图,同时指定地图的中心点和缩放级别
  this.map = L.map("oilMap", {
    center: [39.91, 116.91], //中心经纬度
    zoom: 8, //初始缩放大小
  });
  // 引入图层
  L.tileLayer("http://192.168.0.138/OSM_BLUE/{z}/{x}/{y}.png").addTo(
    this.map
  );
},

2.4. 不要忘了给地图设置宽高

<style lang="scss" scoped>
.oilMap {
  width: 100%;
  height: 100vh;
  z-index: 9;
  background: #00192e;
}
</style>

由此,你就可以得到如下的一个初始化的地图

在这里插入图片描述


三、进阶学习

1、Map 控件

Map 控件主要是用来控制地图显示的工具。

1.1 比例尺控件

L.control.scale({
    metric: true, // 显示米
    imperial: false, // 不显示英尺
  }).addTo(this.map);

1.2 禁用双击放大

this.map = L.map("oilMap", {
  center: [39.91, 116.91], //中心经纬度
  zoom: 8, //初始缩放大小
  doubleClickZoom: false, //禁用双击放大
});

1.3 缩放控件是否显示

this.map = L.map("oilMap", {
  center: [39.91, 116.91], //中心经纬度
  zoom: 8, //初始缩放大小
  zoomControl: true, //缩放控件是否显示
});

1.4 版权控件是否显示

this.map = L.map("oilMap", {
  center: [39.91, 116.91], //中心经纬度
  zoom: 8, //初始缩放大小
  attributionControl: false, //版权控件是否显示
});

1.5 地图最大/小缩放层级

this.map = L.map("oilMap", {
  center: [39.91, 116.91], //中心经纬度
  zoom: 8, //初始缩放大小
  minZoom: 6,//地图最小缩放层级
  maxZoom: 10,//地图最大缩放层级
});

2、Marker 标记

L.Marker 用于在地图上显示可点击/可拖动的图标。

2.1 添加图标标记点

// 定义图标属性
let markerIcon = L.icon({
  iconUrl:"https://unpkg.com/leaflet@1.9.2/dist/images/marker-icon-2x.png",
  iconSize: [20, 34],//图标图像的尺寸,单位是像素。
  iconAnchor: [7, 9],//图标 "tip" 的坐标(相对于其左上角)。图标将被对齐,使该点位于标记的地理位置。如果指定了尺寸,默认为居中,也可以在CSS中设置负的边距。
  popupAnchor: [-3, -3],//弹出窗口(popup)的坐标,相对于图标锚点而言,将从该点打开。
});
// 生成标记点
L.marker([39.91, 116.91], {icon: markerIcon,}).addTo(this.map);

图标标记点实现效果

在这里插入图片描述


2.2 添加圆形标记

L.circle([40.91, 116.91], {
  color: "red", //描边颜色
  fillColor: "yellow", //填充颜色
  fillOpacity: 0.5, //填充的不透明度
  radius: 5000, //圆的半径,以米为单位
}).addTo(this.map);

圆形标记实现效果

在这里插入图片描述


2.3 添加多边形标记

let latlngs = [
  [39.91, 116.91],
  [39.87, 116.11],
  [39.51, 116.51],
  [39.51, 116.81],
  [39.91, 116.91],
];
L.polygon(latlngs,{color:'rgb(51,136,255)',fillColor:'red', fillOpacity:'0.4'}).addTo(this.map);

多边形标记实现效果

在这里插入图片描述

3、Popup 弹出窗口

bindPopup("弹出内容").openPopup() 用于在地图的某些位置打开弹出窗口。

栗子

// 定义图标属性
let markerIcon = L.icon({
  iconUrl:"https://unpkg.com/leaflet@1.9.2/dist/images/marker-icon-2x.png",
  iconSize: [20, 34],//图标图像的尺寸,单位是像素。
  iconAnchor: [7, 9],//图标 "tip" 的坐标(相对于其左上角)。图标将被对齐,使该点位于标记的地理位置。如果指定了尺寸,默认为居中,也可以在CSS中设置负的边距。
  popupAnchor: [-3, -3],//弹出窗口(popup)的坐标,相对于图标锚点而言,将从该点打开。
});
// 生成标记点
L.marker([39.91, 116.91], {icon: markerIcon,}).addTo(this.map).bindPopup("弹出内容").openPopup();

实现效果

在这里插入图片描述


4、图层

Leaflet 中,可以添加到地图的任何内容都是一个图层。因此,上面的标记、圆形、多边形其实都属于图层,也可以理解为地图的要素。

4.1 清除图层

//示例图层
let lineSet = L.polygon(latlngs,{color:'rgb(51,136,255)',fillColor:'red', fillOpacity:'0.4'}).addTo(this.map);
//清除指定layer
this.map.removeLayer(lineSet)
//清除地图上所有layer
this.map.clearLayers()

4.2 地图层级判断

this.map.on("zoom", function (e) {
  if (e.target._zoom > 8) {
    // 执行操作
  }
});

4.3 监听地图缩放

this.map.on("zoom", function () {
 // 执行操作
});

4.4 绑定点击事件

let marker = L.marker([39.91, 116.91]).addTo(this.map);
marker.on("click", function (e) {
  // 执行操作
});

4.5 添加GeoJson图层

//jsondata必须为指定格式为GeoJson格式
let GeoJsonlayer = L.geoJSON(jsondata, {
  style: {
    color: "#4e98f444",
    fillOpacity: 1,
    weight: 1,
  },
});
GeoJsonlayer.setZIndex(1);// 改变网格图层的 zIndex 
this.map.addLayer(GeoJsonlayer);// 将给定的图层添加到组中

四、项目实战

上述所说都是 Leaflet 地图使用的要点,下面我们将上面提到的要点结合项目中的需求实现在地图上各种有趣的操作。

封装文件

// 地图公共方法封装 /utils/index
import * as L from 'leaflet'
import { Message, Notification } from 'element-ui'
export default class LMap {
    // 初始化地图
    /***
     * 【options】参数合集
     * [tileUrl]瓦片地图地址
     * [minZoom]最小级别
     * [maxZoom]最大级别
     * [zoom]初始化级别
     * [crs]坐标系
     * [center]初始化视图中心点
     * [fullscreenControl]是否显示全屏控件
     * [zoomControl]是否显示缩放控件
     * [inertia]是否开启惯性,在拖动和在某一时间段内持续朝同一方向移动建有动力的地图时,会有惯性的效果
     * [attributionControl]属性控制是否默认加载在地图上
     * [renderer]// 渲染方式 (默认使用canvas提高性能)
     * [bounds]// 地图限制拖动区域 [下,上,右,左]
     *
     *
     * ***/
    async initMap(divId, options) {
        // let url = process.env.VUE_APP_MAP_URL + '/OSM_BLUE/{z}/{x}/{y}.png'
        const {
            tileUrl,
            minZoom,
            maxZoom,
            zoom,
            crs,
            center,
            fullscreenControl,
            zoomControl,
            inertia,
            attributionControl,
            renderer,
            bounds
        } = options
        this.map = L.map(divId, {
            minZoom: minZoom ? minZoom : 8, // 地图最小缩放层级
            maxZoom: maxZoom ? maxZoom : 15, // 地图最大缩放层级,
            // crs: crs ? crs : L.CRS.EPSG3857, // 坐标系
            center: center ? center : [39.7506, 118.3423], // 地图中心
            zoom: zoom ? zoom : 8, // 地图默认缩放层级
            fullscreenControl: fullscreenControl ? fullscreenControl : false, // 是否显示全屏控件
            zoomControl: zoomControl ? zoomControl : false, // 是否显示缩放控件
            inertia: inertia ? inertia : true, // 是否开启惯性,在拖动和在某一时间段内持续朝同一方向移动建有动力的地图时,会有惯性的效果
            attributionControl: attributionControl ? attributionControl : false, // 属性控制是否默认加载在地图上
            renderer: renderer ? renderer : L.canvas() //使用canvas 渲染 提高性能
        })
        if (tileUrl) {
            // 将mapbox自定义样式添加到地图中
            // this.map.addLayer(L.tileLayer(tileUrl, { 
            //     tileSize: 256,
            //     zoomOffset: 1, 
            //     attribution: 'stamen',
            //   }))
            this.map.addLayer(L.tileLayer(tileUrl))
        } else {
            console.error('---请配置瓦片图层地址---')
        }
        // 给地图区域做限制的上下左右四部分
        if (bounds) {
            const mapBounds = bounds
            // L.latLngBounds([
            //     [40.7844, 118.2935], // 下
            //     [38.4575, 118.4979], // 上
            //     [39.782, 115.778], // 左
            //     [39.8041, 121.583] // 右
            // ])
            this.map.setMaxBounds(mapBounds)
        }
        // 渲染完成返回true
        return this.map
    }
    getMap() {
        return this.map || {}
    }
    mapArea() {}
    mapDistance() {}
}


4.1 基础点位图

<template>
  <div>
    <div class="zMap" id="map"></div>
    <!-- 点位详情 -->
    <div ref="detailsObj" v-if="showPup">
      <div class="dataBox">
        <div class="item">
          <div>点位名称:</div>
          <div>{{ markerData.name ? markerData.name : "--" }}</div>
        </div>
        <div class="item">
          <div>车牌号:</div>
          <div> {{ markerData.cph ? markerData.cph : "--" }}</div>
        </div>
        <div class="item">
          <div>排放阶段:</div>
          <div>{{ markerData.pfjd ? markerData.pfjd : "--" }}</div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
import areaGeo from "@/utils/area.json"; //引入离线本地json
import LMap from "@/utils/index";//地图公共方法封装
import * as L from "leaflet";
import onlineMarker from "../assets/zaix.png";//不同状态的图片
import offlineMarker from "../assets/lix.png";//不同状态的图片
export default {
  name: "lMap",
  data() {
    return {
      map: null, //地图对象
      lmap: new LMap(), //地图公共方法封装
      labelGroup: null, //文本图层
      markerLayer: null, //marker 图层
      bondarylayer: null, //geojson 图层
      layerPup: null, //弹窗
      markerData: {}, //详情数据
      showPup: false, //详情弹框是否弹出
    };
  },
  mounted() {
    this.initMap(); //初始化地图方法
  },
  methods: {
    //初始化地图
    async initMap() {
      let _this = this;
      let { lmap } = this;
      //配置地图项
      const mapConfig = {
        tileUrl: "http://192.168.0.138/OSM_BLUE/{z}/{x}/{y}.png", //瓦片图层地址
        minZoom: 8, //允许缩放最小级别
        maxZoom: 10, //允许缩放最大级别
        zoom: 8, //初始化级别
        center: [30.536095454317287, 104.15024279778913], //中心经纬度
        bounds: L.latLngBounds([
          [30.536095454317287, 104.15024279778913], // 下
          [30.536095454317287, 104.15024279778913], // 上
          [30.536095454317287, 104.15024279778913], // 左
          [30.536095454317287, 104.15024279778913], // 右
        ]), //限制拖动的区域
      };
      this.map = await lmap.initMap("map", mapConfig);
      if (this.map) {
        this.labelGroup = new L.layerGroup(); //文本图层
        this.labelGroup.addTo(this.map);
        this.markerLayer = new L.layerGroup(); //标记
        this.markerLayer.addTo(this.map);
        this.getGeojsonByName(areaGeo, true);
        this.maptopPoint();
      } else {
        console.error("--地图加载失败!!!--");
      }
    },
    //加载geojson数据
    getGeojsonByName(data, flag) {
      let _this = this;
      this.bondarylayer = L.geoJSON(data, {
        style: {
          color: "#4e98f444",
          fillOpacity: 1,
          weight: 2,
        },
        pane: "overlayPane",
        onEachFeature: (feature, layer) => {
          if (!flag) {
            _this.addText(feature, layer);
          }
        },
      });
      this.bondarylayer.setZIndex(1);
      this.map.addLayer(this.bondarylayer);
    },
    addText(feature, layer) {
      let name = feature.properties.NAME;
      let location = layer._bounds.getCenter();
      //显示文字
      var content = `${name}`;
      // 区县名称文字
      var text = L.divIcon({
        html: "<div>" + content + "</div>",
        iconSize: [60, 20],
        iconAnchor: [0, 10],
        className: "labelStyle",
      });
      let marker = new L.marker(location, { icon: text });
      //中心点位
      this.labelGroup.addLayer(marker);
    },
    //模拟地图点位接口
    maptopPoint() {
      let dataList = [
        {
          lng: "104.882",
          lat: "30.436",
          name: "点位1",
          cph: "川A31255",
          pfjd: "国五",
          status: "0",
        },
        {
          lng: "103.652",
          lat: "30.565",
          name: "点位2",
          cph: "川C32585",
          pfjd: "国四",
          status: "1",
        },
        {
          lng: "104.352",
          lat: "31.136",
          name: "点位3",
          cph: "川X36985",
          pfjd: "国三",
          status: "0",
        },
        {
          lng: "104.452",
          lat: "30.536",
          name: "点位4",
          cph: "川D31255",
          pfjd: "国二",
          status: "1",
        },
        {
          lng: "104.202",
          lat: "30.136",
          name: "点位5",
          cph: "川E31125",
          pfjd: "国一",
          status: "1",
        },
      ];
      this.checkMarkerList(dataList);
    },
    //监测数据对marker进行渲染
    checkMarkerList(list) {
      let _this = this;
      if (!list.length) {
        return;
      }
      list.map((item) => {
        _this.addMarker(item);
      });
    },
    addMarker(item) {
      let _this = this;
      let Icon = _this.getMarkerIcon(item);
      if (Icon) {
        var marker = new L.marker(L.latLng(item.lat, item.lng), {
          icon: Icon,
        });
        //区县编码
        marker["markerInfo"] = item;
        marker.bindTooltip(item.name); //鼠标触摸显示提示信息
        marker.on("click", function (e) {
          let MarkerTarget = e.target; //获取 点击marker
          _this.showMarkerPup(MarkerTarget);
        });
        this.markerLayer.addLayer(marker);
      }
    },
    //显示marker 弹窗信息
    showMarkerPup(marker) {
      let _this = this;
      _this.markerData = marker["markerInfo"];
      let location = marker._latlng;
      _this.showPup = true;
      _this.$nextTick(() => {
        _this.layerPup = L.popup({
          className: "district-pup",
          closeButton: false,
        })
          .setLatLng(location)
          .setContent(_this.$refs.detailsObj)
          .openOn(_this.map);
      });
    },
    //获取marker图标
    getMarkerIcon(data) {
      let markerIcon, imgUrl;
      let { status } = data; //1在线 2离线

      if (status) {
        status = Number(status);
      }
      if (status == 1) {
        imgUrl = onlineMarker;
      } else {
        imgUrl = offlineMarker;
      }
      markerIcon = L.icon({
        iconUrl: imgUrl,
        iconSize: [20, 20],
        iconAnchor: [12, 12],
        popupAnchor: [-3, -3],
      });
      return markerIcon;
    },
  },
};
</script>

<style lang="scss" scoped>
.zMap {
  width: 100%;
  height: 100vh;
  z-index: 9;
}
.dataBox {
  width: 100%;
  .item {
    display: flex;
    padding: 4px 0px;
  }
}
::v-deep {
  .leaflet-popup-content-wrapper,
  .leaflet-popup-tip {
    border: none;
    background: rgba($color: #020a31, $alpha: 0.7) !important;
    border-radius: 4px;
    box-shadow: 0px 0 6px 0px #33aeff inset;
    color: rgba($color: #fff, $alpha: 0.8);
  }
  .leaflet-container a.leaflet-popup-close-button {
    color: #fff;
  }
}
</style>

实现效果

在这里插入图片描述


4.2 行驶轨迹图

<template>
  <div>
    <div class="leftRightBox">
      <!-- 左 -->
      <div class="oilMap" id="map"></div>
      <!-- 右 -->
      <div class="rightTxtBox">
        <el-card class="box-card">
          <!-- 播放轨迹 -->
          <div class="trackBox">
            <div>
              <i title="播放" v-if="playIsShow" @click="playPauseOn" class="el-icon-video-play"></i>
              <i title="暂停" v-else @click="playPauseOn" class="el-icon-video-pause"></i>
            </div>
            <div>
              <el-slider :min="0" :max="points.length - 1" @change="sliderOn" v-model="progress"></el-slider>
            </div>
          </div>
          <div class="multipleBox">
            <span>倍速:</span>
            <el-select @change="multipleOn" style="width:70px" size="mini" v-model="multipleNumber" placeholder="请选择倍速">
              <el-option v-for="item in multipleOptions" :key="item.multipleNumber" :label="item.label" :value="item.value">
              </el-option>
            </el-select>
          </div>
        </el-card>
      </div>
    </div>
  </div>
</template>

<script>
import LMap from "@/mapUtils";
import areaGeo from "@/mapUtils/area.json";
import abnormal from "../../../../assets/overview/normal.png"; //地图图标
export default {
  data() {
    return {
      multipleOptions: [
        {
          value: 800,
          label: "1",
        },
        {
          value: 550,
          label: "1.5",
        },
        {
          value: 400,
          label: "2",
        },
      ],
      map: null,
      lmap: new LMap(), //地图公共方法封装
      labelGroup: null, //文本图层
      tipsLayerGroup: null, //tips
      bondarylayer: null, //geojson 图层
      points: [
        //模拟点位数据
        [39.898457, 116.391844],
        [39.898595, 116.377947],
        [39.898341, 116.368001],
        [39.898063, 116.357144],
        [39.899095, 116.351934],
        [39.905871, 116.35067],
        [39.922329, 116.3498],
        [39.931017, 116.349671],
        [39.939104, 116.349225],
        [39.942233, 116.34991],
        [39.947263, 116.366892],
        [39.947568, 116.387537],
        [39.947764, 116.401988],
        [39.947929, 116.410824],
        [39.947558, 116.42674],
        [39.9397, 116.427338],
        [39.932404, 116.427919],
        [39.923109, 116.428377],
        [39.907094, 116.429583],
        [39.906858, 116.41404],
        [39.906622, 116.405321],
        [39.906324, 116.394954],
        [39.906308, 116.391264],
      ],
      playIsShow: true, //播放/暂停
      multipleNumber: 1, //倍速
      progress: 0, //进度
      marker: null,
      polyline: null,
      duration: 0,
      timer: null, //定时器
      time: 800, //定时器速度
    };
  },
  mounted() {
    this.duration = this.points.length - 1;
    this.initMap();
  },
  watch: {
    progress() {
      this.updatePosition();
    },
  },
  destroyed() {
    clearTimeout(this.timer);
  },
  methods: {
    updatePosition() {
      const position = this.points[this.progress];
      this.marker.setLatLng(position);
      this.map.setView(position, 12); //放大比例
    },
    // 滑动进度
    sliderOn(e) {
      console.log(e, "滑动进度");
    },
    // 选择倍速
    multipleOn(e) {
      clearTimeout(this.timer);
      this.time = e;
      this.recursion();
    },
    // 点击播放暂停按钮
    playPauseOn() {
      if (this.progress == this.points.length - 1) {
        this.progress = 0;
      }
      this.playIsShow = !this.playIsShow;
      this.recursion();
    },
    // 递归
    recursion() {
      if (!this.playIsShow) {
        // 模拟数据变化
        this.timer = setTimeout(() => {
          this.progress++;
          if (this.progress >= this.points.length - 1) {
            this.playIsShow = true;
            this.polyline = L.polyline(this.points, { color: "red" }).addTo(
              this.map
            );
            clearTimeout(this.timer);
          }
          this.recursion();
        }, this.time);
      }
    },
    //初始化地图
    async initMap() {
      let { lmap } = this;
      //配置地图项
      const mapConfig = {
        tileUrl: window.api.teilUrl + "/OSM_BLUE/{z}/{x}/{y}.png", //瓦片图层地址
        crs: L.CRS.EPSG4326,
        minZoom: 8, //允许缩放最小级别
        maxZoom: 15, //允许缩放最大级别
        zoom: 10, //初始化级别
        center: [39.91, 116.91], //初始化中心点
      };
      this.map = await lmap.initMap("map", mapConfig);
      if (this.map) {
        this.labelGroup = new L.layerGroup(); //文本图层
        this.labelGroup.addTo(this.map);
        this.tipsLayerGroup = new L.layerGroup();
        this.tipsLayerGroup.addTo(this.map);
        this.getGeojsonByName(areaGeo, true);
      } else {
        console.error("--地图加载失败!!!--");
      }
      var icon = L.icon({
        iconUrl: abnormal,
        iconSize: [16, 13],
        iconAnchor: [8, 7],
      });
      this.marker = L.marker(this.points[0], { icon: icon }).addTo(this.map);
      this.polyline = L.polyline(this.points, { color: "red" }).addTo(this.map);
      setInterval(() => {
        this.marker.setLatLng(this.points[this.progress]);
        this.polyline.setLatLngs(this.points.slice(0, this.progress + 1));
      }, 100);
    },
    //加载geojson数据 falg 是否显示名称
    getGeojsonByName(data, flag) {
      let _this = this;
      this.bondarylayer = L.geoJSON(data, {
        style: {
          color: "#4e98f444",
          fillOpacity: 1,
          weight: 1,
        },
        pane: "overlayPane",
        onEachFeature: (feature, layer) => {
          // console.log(layer)
          if (flag) {
            _this.addText(feature, layer);
          }
        },
      });
      this.bondarylayer.setZIndex(1);
      this.map.addLayer(this.bondarylayer);
    },
    //添加市所有区县
    addText(feature, layer) {
      let name = feature.properties.name;
      // let center = feature.properties.center;
      let location = layer._bounds.getCenter(); //[center[1], center[0]]; //
      //显示文字
      var content = `${name}`;
      // 区县名称文字
      var text = L.divIcon({
        html: "<div class='labelStyle'>" + content + "</div>",
        iconSize: [60, 20],
        iconAnchor: [0, 10],
        className: "labelStyle",
      });
      let marker = new L.marker(location, { icon: text });
      //中心点位
      this.labelGroup.addLayer(marker);
    },
  },
};
</script>
<style scoped>
.oilMap {
  height: 500px;
}
</style>


实现效果

在这里插入图片描述

持续更新...

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

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

相关文章

数据结构与算法一览(树、图、排序算法、搜索算法等)- Review

算法基础简介 - OI Wiki (oi-wiki.org) 文章目录1. 数据结构介绍1.1 什么是数据结构1.2 数据结构分类2. 链表、栈、队列&#xff1a;略3. 哈希表&#xff1a;略4. 树4.1 二叉树4.2 B 树与 B 树4.3 哈夫曼&#xff08;霍夫曼&#xff09;树&#xff1a;Huffman Tree4.4 线段树&a…

编辑文件/文件夹权限 - Win系统

前言 我们经常会遇到由于权限不够无法删除文件/文件夹的情况&#xff0c;解决方案一般是编辑文件/文件夹的权限&#xff0c;使当前账户拥有文件的完全控制权限&#xff0c;然后再进行删除&#xff0c;下文介绍操作步骤。 修改权限 查看用户权限 右键文件/文件夹&#xff0c;…

(函数指针) 指向函数的指针

函数指针- 指向函数的指针函数指针的声明和使用通过函数指针调用函数函数指针做参数函数指针数组函数指针的声明和使用 函数指针的声明格式&#xff1a; 返回值类型 (*函数指针名)(参数列表); 其中&#xff1a; *函数指针名 表示函数指针的名称返回值类型 则表示该指针所指向…

【Kubernetes】StatefulSet对象详解

文章目录简介1. StatefulSet对象的概述、作用及优点1.1 对比Deployment对象和StatefulSet对象1.2 以下是比较Deployment对象和StatefulSet对象的优缺点&#xff1a;2. StatefulSet对象的基础知识2.1 StatefulSet对象的定义2.1.1 下表为StatefulSet对象的定义及其属性&#xff1…

上岸川大网安院

一些感慨 一年多没写过啥玩意了&#xff0c;因为考研去了嘿嘿。拟录取名单已出&#xff0c;经历一年多的考研之路也可以顺利打上句号了。 我的初试成绩是380&#xff0c;政治65&#xff0c;英语81&#xff0c;数学119&#xff0c;专业课115。 回顾这一路&#xff0c;考研似乎也…

分类预测 | MATLAB实现CNN-BiLSTM-Attention多输入分类预测

分类预测 | MATLAB实现CNN-BiLSTM-Attention多输入分类预测 目录分类预测 | MATLAB实现CNN-BiLSTM-Attention多输入分类预测分类效果基本介绍模型描述程序设计参考资料分类效果 基本介绍 MATLAB实现CNN-BiLSTM-Attention多输入分类预测&#xff0c;CNN-BiLSTM结合注意力机制多输…

Vue3使用Vant组件库避坑总结

文章目录前言一、问题二、解决方法三、问题出现原因总结经验教训前言 本片文章主要写了&#xff0c;Vue3开发时运用Vant UI库的一些避坑点。让有问题的小伙伴可以快速了解是为什么。也是给自己做一个记录。 一、问题 vue3版本使用vant失败&#xff0c;具体是在使用组件时失效…

IPBX系统快速部署和Freeswitch 1.10.7自动安装

IPBX系统部署文档 IPPBX系统 1.10.7版本Freeswitch &#xff0c;手机互联互通&#xff0c;SIP协议&#xff0c;分机互相拨打免费通话清晰&#xff0c;支持wifi或4G网络互相拨打电话&#xff0c;可以对接OLT设备&#xff0c;系统可以部署到本地物理机&#xff0c;也可以部署到阿…

工程质量之研发过程管理需要关注的点

一、背景 作为程序猿&#xff0c;工程质量是我们逃不开的一个话题&#xff0c;工程质量高带来的好处多多&#xff0c;我在写这篇文章的时候问了一下CHATGPT&#xff0c;就当娱乐一下&#xff0c;以下是ChatGPT的回答&#xff1a; 1、提高产品或服务的可靠性和稳定性。高质量的系…

光时域反射仪那个品牌的好用

光时域反射仪 哪个品牌好用 光时域反射仪要怎么选到合适自己的&#xff0c;这些问题 可能一直在困扰这一线的工作人员&#xff0c;下面小编就为大家一一解答下 首先光时域域反射仪是一款检测光纤线路的损耗 长度 以及 事件点的一款设备&#xff0c;在诊断 光纤线路 故障点的情…

从零开始学架构——CAP理论

CAP定理 CAP 定理&#xff08;CAP theorem&#xff09;又被称作布鲁尔定理&#xff08;Brewer’s theorem&#xff09;&#xff0c;是加州大学伯克利分校的计算机科学家埃里克布鲁尔&#xff08;Eric Brewer&#xff09;在 2000 年的 ACM PODC 上提出的一个猜想。2002 年&…

Web前端 HTML、CSS

HTML与CSSHTML、CSS思维导图一、HTML1.1、HTML基础文本标签1.2、图片、音频、视频标签1.3、超链接、表格标签1.4、布局1.5、表单标签1.6、表单项标签综合使用1.7、HTML小结二、CSS&#xff08;简介&#xff09;2.1、引入方式2.2、选择器2.3、CSS属性Web前端开发总览 Html&…

案例拆解丨ChatGPT+塔罗牌,批量起号、暴利引流,小白也能轻松月入10000+

ChatGPT 的出现&#xff0c;大大拉低了很多行业的门槛&#xff0c;比如客服、教育、翻译、自媒体……而塔罗牌占卜&#xff0c;肯定也是其中之一。 塔罗牌是一种占卜工具&#xff0c;由78张牌组成。可以用于占卜、灵性探索、个人成长和自我发现。 这是一个相对小众&#xff0c…

LinuxGUI自动化测试框架搭建(十三)-创建工具集目录tools并封装文件复制方法cpoyFile.py

(十三)-创建工具集目录tools并封装文件复制方法cpoyFile.py 1 tools的作用2 创建tools目录3 创建文件复制方法cpoyFile.py4 设计cpoyFile.py4.1 安装shutil4.2 导入模块4.3 脚本设计5 目前框架目录1 tools的作用 为了存放框架需要用到的一些常用工具或方法,比如文件复制功能…

OJ系统刷题 第九篇(难篇)

13441 - 求小数的某一位&#xff08;难题&#xff0c;二刷、三刷&#xff01;&#xff09; 时间限制 : 1 秒 内存限制 : 128 MB 分数\tfrac {a}{b}ba​化为小数后&#xff0c;小数点后第n位的数字是多少&#xff1f; 输入 三个正整数a&#xff0c;b&#xff0c;n&#xff0…

使用jni-rs实现Rust与Android代码互相调用

本篇主要是介绍如何使用jni-rs。有关jni-rs内容基于版本0.20.0&#xff0c;新版本写法有所不同。 入门用法 在Rust库交叉编译以及在Android与iOS中使用中我简单说明了jni-rs及demo代码&#xff0c;现在接着补充一些详细内容。 首先贴上之前的示例代码&#xff1a; use std:…

嘉靖王朝最大的一出闹剧和惨剧——大礼仪之争

大礼仪之争 大礼议是指发生在正德十六年&#xff08;1521年&#xff09;到嘉靖三年&#xff08;1524年&#xff09;间的一场皇统问题上的政治争论。 原因是明世宗以地方藩王入主皇位&#xff0c;为其改换父母的问题所引起&#xff0c;是明朝历史第二次小宗入大宗的事件。 “…

罗丹明荧光染料标记叶酸,FA-PEG-RB,叶酸-聚乙二醇-罗丹明;Folic acid-PEG-RB

FA-PEG-RB,叶酸-聚乙二醇-罗丹明 中文名称&#xff1a;叶酸-聚乙二醇-罗丹明 英文名称&#xff1a;FA-PEG-RB, Folic acid-PEG-RB 性状&#xff1a;粉红色固体或液体&#xff0c;取决于分子量 溶剂&#xff1a;溶于水和DMSO、DMF等常规性有机溶剂 保存条件&#xff1a;-2…

【Python】【进阶篇】二十一、Python爬虫的多线程爬虫

目录二十一、Python爬虫的多线程爬虫21.1 多线程使用流程21.2 Queue队列模型21.3 多线程爬虫案例1) 案例分析​2) 完整程序二十一、Python爬虫的多线程爬虫 网络爬虫程序是一种 IO 密集型程序&#xff0c;程序中涉及了很多网络 和 本地磁盘的 IO 操作&#xff0c;这会消耗大量…

自绘 MFC 控件 CComboBox

运行效果: 第一步:在窗口中拖拽一个CComboBox控件,设置如下属性: 类型,设置为:下拉列表包含字符串,设置为:True所有者描述,设置为:Variable 注意: 包含字符串,不设置为True,则使用GetLBText等函数无法获取到Item的text;所有者描述,设置为No,不执行DrawItem、M…