当前位置:网站首页>Mapbox usage, including drawing, loading, modifying, deleting points and faces, displaying pop ups, etc
Mapbox usage, including drawing, loading, modifying, deleting points and faces, displaying pop ups, etc
2022-06-13 08:44:00 【Dependency_ Lai】
Load map data
mapbox api Address :http://www.mapbox.cn/mapbox-gl-js/api/
mapbox-gl-draw git Address : https://github.com/mapbox/mapbox-gl-draw
One 、 stay index.html Introduced the global mapbox-gl Of js and css package , Download address https://download.csdn.net/download/weixin_39150852/19348455
Because the project will involve the calculation of some spatial geometric object relationships , Need a turf.js, Please refer to :https://blog.csdn.net/weixin_39150852/article/details/116758542

Two 、 Create a map component , Initialize map
<template>
<div class="map-wrapper" :id="mapId"></div>
</template>
<script>
var map;
import {
updateVisualOperationMapViewer} from "../../store/map/mapService";
export default {
name: "BaseMapContainer",
props: {
mapId: {
default(){
return 'map'
}
}
},
data() {
return {
};
},
mounted() {
this.initMap();
},
methods: {
// Initialize map
initMap() {
map = new mapboxgl.Map({
container: this.mapId,// Map container
style: {
version: 8,
glyphs: "/font/{fontstack}/{range}.pbf",// The font file
sources: {
"raster-tiles": {
type: "raster",
tiles: [
"http://t4.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=4b01c1b56c6bcba2eb9b8e987529c44f",// Sky map image ( The global )
],
tileSize: 256,
},
},
layers: [
{
id: "simple-tiles",
type: "raster",
source: "raster-tiles",
},
],
},
center: [103.30400138502898, 29.78955907249347],// The initial center point
zoom: 15.5,
minZoom: 9.5,
pitch: 35, // Tangent angle
bearing: 0, // Rotation Angle
});
updateVisualOperationMapViewer(map);// preservation map object , Easy to use on other pages
// For specific implementation methods of data storage, please refer to Akita Introduction and use of
//https://blog.csdn.net/weixin_39150852/article/details/109216097
}
},
};
</script>
<style lang="less">
.map-wrapper {
width: 100%;
height: 100%;
}
</style>
layers Of type Common types
fill: polygon
line: Line
symbol: Icon or text label
circle: Solid round
heatmap: Heat map
raster: image ( Including Gaud ,arcgic, Map world etc. )
background: The background color or pattern of the map ( Unwanted sources)
sources Of type Common types
vector: vector ( When using layer Must specify ’source-layer’ value )
raster: image ( Including Gaud ,arcgic, Map world etc. )
geojson:geojson Format data
image: Images
video: video
3、 ... and 、 Using map components
1、 Reference the map component on the corresponding page 
2、 establish mapjs
Load multiple range faces
import axios from "axios";
import {
getVisualOperationMapViewer} from "../../../store/map/mapService";
var map = getVisualOperationMapViewer();// obtain map object
/** * Convert array , Get color properties */
function arrayGetColor(defaultArray) {
defaultArray.filter((e) => {
if (e.properties[" Functional area type"] == "3") {
return (e.properties.RGB = "rgba(0, 210, 145, 1)");
} else if (e.properties[" Functional area type"] == "4") {
return (e.properties.RGB = "rgba(171, 255, 80, 1)");
} else if (e.properties[" Functional area type"] == "5") {
return (e.properties.RGB = "rgba(255, 73, 73, 1)");
} else if (e.properties[" Functional area type"] == "6") {
return (e.properties.RGB = "rgba(0, 255, 252, 1)");
} else if (e.properties[" Functional area type"] == "7") {
return (e.properties.RGB = "rgba(255, 247, 132, 1)");
} else if (e.properties[" Functional area type"] == "8") {
return (e.properties.RGB = "rgba(176, 124, 255, 1)");
} else if (e.properties[" Functional area type"] == "1") {
return (e.properties.RGB = "rgba(255, 137, 187, 1)");
} else {
return (e.properties.RGB = "rgba(255, 255, 255, 1)");
}
});
return defaultArray;
};
/** * Add Ribbon */
export function addBoundaries() {
removeBoundaries();
// Load multiple range faces
axios.get("/json/ Functional area .json").then((res) => {
let newArr = res.data;
newArr.features = arrayGetColor(newArr.features);// Set up RGB attribute
// Render map color block layer
map.addSource("Area_Geojson", {
type: "geojson",
data: newArr,
});
map.addLayer({
id: "maine",
type: "fill",
source: "Area_Geojson",
layout: {
},
paint: {
"fill-color": ["get", "RGB"],// Display polygons of different colors according to different types
"fill-opacity": 0.5,
},
// Filter data , To filter out geometry.type Not Polygon Type data
//filter: ["==", "$type", "Polygon"]
});
});
// Set dimension information for each range face
axios.get("/json/ Functional area .json").then((res) => {
res.data.features.forEach(item=>{
let poly;
if(item.geometry.coordinates.length>1){
// solve 'Each LinearRing of a Polygon must have 4 or more Positions.' error
poly = turf.multiPolygon(item.geometry.coordinates);
}else{
poly = turf.polygon(item.geometry.coordinates);
}
item.geometry = turf.centerOfMass(poly).geometry; // adopt turf Obtain the coordinates of the center point of the face
})
let newCenterArr = res.data;
// Render map surface annotation layer
map.addSource("Area_Center_Geojson", {
type: "geojson",
data: newCenterArr,
});
map.addLayer({
id: "maineCenter",
type: "symbol",
source: "Area_Center_Geojson",
layout: {
"text-field": ["get", " Ribbon categories "],
"text-font": ["Open Sans Semibold,Arial Unicode MS Bold"],// The font file , Corresponding public/font
"text-size": 8,
"text-ignore-placement": true, // Ignore the position of the text
"text-allow-overlap": true // Words are allowed to overlap
},
paint: {
"text-color": "#fff",
}
});
});
}
/** * Remove Ribbon */
export function removeBoundaries(){
// Delete map data related to the ribbon
if (!map) {
map = getVisualOperationMapViewer()
} else {
let layers = map.getStyle().layers;// Get all layers
if (layers.some(value => value.id == "maine")) {
map.removeLayer("maine");
map.removeSource("Area_Geojson");
}
if (layers.some(value => value.id == "maineCenter")) {
map.removeLayer("maineCenter");
map.removeSource("Area_Center_Geojson");
}
}
}
newArr data format :

Realization effect : Insert picture description here 
Bind map Events
/** * Map binding click event */
export function mapBingClick() {
map.on("click", "maine", clickFunctionArea);
map.on("mouseenter", "maine", changeCursor);
map.on("mouseleave", "maine", changeCursor);
}
/** * Change the mouse state */
function changeCursor(e){
if(e.type === "mouseleave"){
map.getCanvas().style.cursor = "";
}else if(e.type === "mouseenter"){
map.getCanvas().style.cursor = "pointer";
}
}
/** * Remove the map binding click event */
export function clearMapBingClick(){
if (!map) {
map = getVisualOperationMapViewer()
} else {
map.off("click", "maine", clickFunctionArea);
map.off("mouseenter", "maine", changeCursor);
map.off("mouseleave", "maine", changeCursor);
}
}
/** * Click on the ribbon */
function clickFunctionArea(e){
if(e.defaultPrevented)return;
while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) {
coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360;
}// Prevent data from crossing boundaries
let areaData = e.features[0];
// Navigate to the current point
map.flyTo({
center: [e.lngLat.lng, e.lngLat.lat],
zoom: 16, // Target level
duration: 800, // Total flight time , Company ms
});
// Highlight the current layer
let sources = map.getStyle().sources;
let sourceArea = sources['Area_Geojson'].data;
sourceArea.features = arrayGetColor(sourceArea.features);// Restore initial
sourceArea.features.forEach(item => {
if (item.properties['Field_smid'] === areaData.properties['Field_smid']) {
item.properties.RGB = "#29f";// Set highlight color
}
})
map.getSource('Area_Geojson').setData(
sourceArea
);
// Stop the event from bubbling
e.preventDefault();
}
Load multiple points
1、 adopt addLayer load , Click event map.on("click", "points", clickFunctionArea);
/** * Load trees */
function addPoint(type) {
let layers = map.getStyle().layers;
// Get layer , If this layer exists ,exist by true, conversely false
let exist = layers.some(value => value.id == "points");
// Determine whether the layer exists , If exist , Delete the layer first
if (exist) {
map.removeLayer("points");
map.removeSource("pointGeoJson");
map.removeImage("pointImg");
}
/** * Pull point data */
axios.get("/json/ tree .json").then((res) => {
let newArr = res.data;
map.loadImage("/img/ tree .png", function(error, image) {
if (error) throw error;
map.addImage("pointImg", image);
map.addSource("pointGeoJson", {
type: "geojson",
data: {
type: "FeatureCollection",
features: newArr,
},
});
map.addLayer({
id: "points",
type: "symbol",
source: "pointGeoJson",
layout: {
"icon-image": "pointImg",
"icon-size": 0.6,
"icon-offset": [0, -19],
"icon-ignore-placement": true, // Icon ignores position ( This layer can overlap )
"icon-allow-overlap": true, // Icons are allowed to overlap ( Multiple layers can overlap )
"text-field": ["get", "mapInfoName"],// Show mapInfoName Content
"text-offset": [0, -3.5],
"text-font": ["Open Sans Semibold,Arial Unicode MS Bold"],
"text-size": 14,
"text-ignore-placement": true, // Text ignore position
"text-allow-overlap": true, // Text is allowed to overlap
// Too many points , When zooming the map , Overlapping points are hidden ,
// This point renders “text” and “icon”, Must be set at the same time “text” and "icon" Ignore location attribute of , Individual settings do not take effect
},
paint: {
"text-color": "#d1d1d1",
},
});
});
});
}
newArr data format :
Realization effect :
2. adopt marker load ( Not recommended , No color is displayed on the ribbon surface when loading for the second time , All other functions are normal , The cause has not been found yet )
/** * Load trees */
var facilityMapMarkers = [];// All points loaded by the map
var facilityMapMarkersText = [];// All point annotations loaded by the map
export function drawFacilityMarker(data, type = '') {
// Mark click events
function handleKitten(e) {
e.stopPropagation();
const target = e.target || e.srcElement;
if ( target.getAttribute("dataId")) {
}
}
axios.get("/json/ tree .json").then((res) => {
// Initialize load point data
res.data.forEach(data=> {
let coordinate = [Number(data.facilityLongitude), Number(data.facilityLatitude)];
let el = document.createElement("div");
el.style.backgroundImage = "url(/img/ infrastructure .png)";
el.style.backgroundSize = "100% auto";
el.style.width = 30 + "px";
el.style.height = 38 + "px";
el.setAttribute("dataId", data.id);// Set up id
let marker = new mapboxgl.Marker(el)
.setLngLat(coordinate)
.setOffset([0, -19])
.addTo(map);
facilityMapMarkers.push(marker);
el.addEventListener("click", handleKitten, false);
// Loading point comments
drawFacilityMarkerText(data)
}
/** * Loading point comments */
function drawFacilityMarkerText(data){
let coordinate = [Number(data.facilityLongitude), Number(data.facilityLatitude)];
let text = facilityMarkerData.find(item => item.id === data.id)
let el = document.createElement("div");
el.style.fontSize = '16px';
el.innerHTML = text ? text.facilityName : '';// To modify a point comment, you can get the current dom, change innerHTML value
let markerText = new mapboxgl.Marker(el)
.setLngLat(coordinate)
.setOffset([0, -50])
.addTo(map);
facilityMapMarkersText.push(markerText)
}
/** * Remove point data */
export function removeFacilityMarker() {
facilityMapMarkers.forEach(item => {
item.remove();
})
facilityMapMarkersText.forEach(item => {
item.remove();
})
}

Realization effect :
Change layer display state
/** * Change the layer display state */
export function showLayers(id, show) {
let layers = map.getStyle().layers;
if (layers.some((value) => value.id === id)) {
map.setLayoutProperty(id, 'visibility', show ? 'visible' : 'none');
}
}
Modify the layer data to realize the addition, deletion and modification of the map interface
/** * Change the map state ( Map data ) */
export function changeSource(data, type) {
let sources = map.getStyle().sources;
if (type === 'edit') {
if (data.geometry.type === 'Polygon') {
// Modify the face dimension content
let sourceAreaCenter = sources['planAreaCenter'].data;
sourceAreaCenter.features.forEach(item => {
if (item.properties['id'] === data['id']) {
item.properties.mapInfoName = data.name
}
})
map.getSource('planAreaCenter').setData(
sourceAreaCenter
);
} else if (data.geometry.type === 'Point') {
// Modify the point dimension content
let sourcePoint = sources['planPoint'].data;
sourcePoint.features.forEach(item => {
if (item.properties['id'] === data['id']) {
item.properties.mapInfoName = data.name
}
})
map.getSource('planPoint').setData(
sourcePoint
);
}
} else if (type === 'delete') {
let sources = map.getStyle().sources;
if (data.geometry.type === 'Polygon') {
let sourceArea = sources['planArea'].data;
// Delete face data
sourceArea.features = sourceArea.features.filter(item => item.properties['id'] !== data['id']);
map.getSource('planArea').setData(
sourceArea
);
// Delete face dimensions
let sourceAreaCenetr = sources['planAreaCenter'].data;
sourceAreaCenetr.features = sourceAreaCenetr.features.filter(item => item.properties['id'] !== data['id']);
map.getSource('planAreaCenter').setData(
sourceAreaCenetr
);
} else if (data.geometry.type === 'Point') {
let sourcePoint = sources['planPoint'].data;
// Delete point data
sourcePoint.features = sourcePoint.features.filter(item => item.properties['id'] !== data['id']);
map.getSource('planPoint').setData(
sourcePoint
);
}
}
}
data format :
Show map pop-up
- Define the spring frame assembly
<template>
<div class="operateform_box" id="operateForm">
<p class="title_box"> infrastructure
<span class="title-close" @click="onClose"><i class="el-icon-close"></i></span>
</p>
<div class="content_box">
<el-form
ref="infrastructureForm"
:model="formdata"
label-width="80px"
size="mini"
>
<el-form-item
label=" Facility name "
prop="name"
:rules="[
{
required: true, message: ' Please enter the facility name ', trigger: 'blur' },
]"
>
<el-input v-model="formdata.name" maxlength="30"></el-input>
</el-form-item>
</el-form>
<div style="width:100%; display: flex;justify-content: flex-end;">
<el-button @click="onClose" size="mini"> Cancel </el-button>
<el-button @click="onSubmit" size="mini"> preservation </el-button>
</div>
</div>
</div>
</template>
<script>
import {
removeFacilityPopup} from "../mapjs/InfrastructureMap";
export default {
name: "OperateForm",
props: {
facilityData: {
default() {
return {
}
}
}
},
data() {
return {
formdata: {
name: "",
},
};
},
mounted() {
if(this.facilityData.id){
this.formdata.name = this.facilityData.facilityName;
}
},
methods: {
onSubmit() {
this.$refs["infrastructureForm"].validate((valid) => {
if (valid) {
}
});
},
onClose(){
removeFacilityPopup()
}
},
};
</script>
<style lang="less" scoped>
.operateform_box {
border: 1px solidrgba(48, 214, 255, 0.77);
background: rgba(1, 10, 13, 0.6);
padding: 15px;
box-sizing: border-box;
.title_box {
height: 30px;
font-size: 14px;
color: #ffffff;
position: relative;
.title-close{
position: absolute;
right: 0;
top: 0;
color: #999;
cursor: pointer;
font-size: 20px;
}
}
.content_box {
display: inline-block;
}
}
</style>
- modify mapbox Default style of pop-up frame
// Map pop-up box setting background transparency
.mapboxgl-popup-content {
background: transparent;
}
.mapboxgl-popup-tip {
display: none;
}
- stay mapjs Refer to the bullet frame components in
import Vue from "vue";
import OperateForm from "../dialog/OperateForm.vue";
const MapFacilityPopupComponent = Vue.extend(OperateForm);
var facilityMapPopup, popupData;
/** * Show pop ups */
function showFacilityPopup(data) {
popupData = data;
removeFacilityPopup();
// Load infrastructure pop-up
let popupHTML = '<div id="popup-box"></div>';
let coordinate = [Number(data.facilityLongitude), Number(data.facilityLatitude)];
facilityMapPopup = new mapboxgl.Popup({
closeButton: false,
closeOnClick: false,
offset: [0, -10],
})
.setLngLat(coordinate)
.setHTML(popupHTML)
.setMaxWidth("none")
.addTo(map);
new MapFacilityPopupComponent({
propsData: {
facilityData: data,
}
}).$mount("#popup-box");
}
/** * Remove the bullet frame */
export function removeFacilityPopup() {
if (facilityMapPopup) {
facilityMapPopup.remove();
facilityMapPopup = null;
}
}
data format :
Realization effect :
Position to a face
/** * Calculate a maximum and a minimum */
function getPolygonBoundingBox(feature) {
// bounds [xMin, yMin][xMax, yMax]
var bounds = [[], []];
var polygon;
var latitude;
var longitude;
for (var i = 0; i < feature.geometry.coordinates.length; i++) {
if (feature.geometry.coordinates.length === 1) {
// Polygon coordinates[0][nodes]
polygon = feature.geometry.coordinates[0];
} else {
// Polygon coordinates[poly][0][nodes]
polygon = feature.geometry.coordinates[i][0];
}
for (var j = 0; j < polygon.length; j++) {
longitude = polygon[j][0];
latitude = polygon[j][1];
bounds[0][0] = bounds[0][0] < longitude ? bounds[0][0] : longitude;
bounds[1][0] = bounds[1][0] > longitude ? bounds[1][0] : longitude;
bounds[0][1] = bounds[0][1] < latitude ? bounds[0][1] : latitude;
bounds[1][1] = bounds[1][1] > latitude ? bounds[1][1] : latitude;
}
}
return bounds;
}
map.off("click", "maine", (e)=>{
let boundingBox = getPolygonBoundingBox(e.features[0]);
map.fitBounds(boundingBox, {
padding: 100});// Pan and zoom the map within the specified geographic boundaries , To include its visible area .padding: The amount of padding from the boundary
});
e.features[0] and boundingBox data structure :
Realization effect :
Navigate to a line
let coordinates = e.features[0].geometry.coordinates.slice();//slice Returns an array
let bounds = coordinates.reduce(function (bounds, coord) {
return bounds.extend(coord);
}, new mapboxgl.LngLatBounds(coordinates[0], coordinates[0]));
map.fitBounds(bounds, {
padding: 20
});
data format :
Go to a point
map.flyTo({
center: [e.lngLat.lng, e.lngLat.lat],
zoom: 16, // Target level
duration: 800, // Total flight time , Company ms
})
Drawing graphics
One 、 stay index.html Introduced the global mapbox-gl-draw Of js and css, Refer to appeal mapbox-gl References to
Two 、 Initialize when initializing the map draw
draw = new MapboxDraw({
displayControlsDefault: false,// Whether to display the default map control
controls: {
// Map control displayed , Do not set when customizing the control
polygon: true,
line_string:true,
point:true,
trash: true
}
});
updateMapDraw(draw);// preservation draw object , Easy to use on other pages
3、 ... and 、 stay mapjs Monitor drawing status in
map.addControl(draw, "top-left"); // Control display position
map.on('draw.create', updateArea);
map.on('draw.delete', updateArea);
map.on('draw.update', updateArea);
export function updateArea(e) {
if (e.type === 'draw.create') {
// The drawing is finished
}else if(e.type === 'draw.update'){
// After modifying the drawing
}else if(e.type === 'draw.delete'){
// Delete drawing graphics
}
Realization effect :
Custom control , Delete controls, Define the button on the corresponding page , Switch the drawing type
<div class="map-btn">
<el-button @click="changeDrawModel('draw_point')" class="audit-btn" size="mini"> Plot </el-button>
<el-button @click="changeDrawModel('draw_polygon')" class="audit-btn" size="mini"> Painted surface </el-button>
</div>
/** * Change the drawing type */
export function changeDrawModel(type) {
draw.changeMode(type);
}
Customize the point icon or graphic style displayed when drawing
Initializing draw when , modify style
map.loadImage("/img/marker.png", function (error, image) {
if (error) throw error;
map.addImage("pointImg", image);
});
draw = new MapboxDraw({
displayControlsDefault: false,
styles: [
// Draw point icons
{
'id': 'points-are-blue',
'type': 'symbol',
'filter': ['all',
['==', '$type', 'Point'],
['==', 'meta', 'feature'],
['==', 'active', 'false']],
'layout': {
// Set the point icon displayed after drawing
"icon-image": "pointImg",
"icon-size": 1,
"icon-offset": [0, -15],
"icon-ignore-placement": true, // Icon ignores position
},
'paint' : {
"text-color": "#fff",
}
},
{
'id': 'highlight-active-points',
'type': 'symbol',
'filter': ['all',
['==', '$type', 'Point'],
['==', 'meta', 'feature'],
['==', 'active', 'true']],
'layout': {
// The icon displayed when the setpoint is active
"icon-image": "pointImg",
"icon-size": 1,
"icon-offset": [0, -15],
"icon-ignore-placement": true, // Icon ignores position
},
'paint' : {
"text-color": "#fff",
}
},
// Set face style
{
"id": "gl-draw-polygon-fill",
"type": "fill",
"filter": ["all",
["==", "$type", "Polygon"],
["!=", "mode", "static"]],
"paint": {
// Set the fill color and transparency displayed when drawing faces
"fill-color": "#D20C0C",
"fill-outline-color": "#D20C0C",
"fill-opacity": 0.1
}
},
{
"id": "gl-draw-polygon-stroke-active",
"type": "line",
"filter": ["all", ["==", "$type", "Polygon"], ["!=", "mode", "static"]],
"layout": {
"line-cap": "round",
"line-join": "round"
},
"paint": {
// Set the stroke color displayed when drawing faces 、 Line type 、 Width
"line-color": "#fbb03b",
"line-dasharray": [0.2, 2],
"line-width": 2
}
},
{
"id": "gl-draw-polygon-and-line-vertex-halo-active",
"type": "circle",
"filter": ["all", ["==", "meta", "vertex"], ["==", "$type", "Point"], ["!=", "mode", "static"]],
"paint": {
// Set the size of the turning point displayed when drawing the face , Border color
"circle-radius": 5,
"circle-color": "#fff"
}
},
{
"id": "gl-draw-polygon-and-line-vertex-active",
"type": "circle",
"filter": ["all", ["==", "meta", "vertex"], ["==", "$type", "Point"], ["!=", "mode", "static"]],
"paint": {
// Set the size of the turning point displayed when drawing the face , Fill color
"circle-radius": 3,
"circle-color": "#705080",
}
}
]
});
Realization effect 

Mapbox Common expression :
https://blog.csdn.net/hequhecong10857/article/details/115425431
draw Common methods :
https://blog.csdn.net/u011435933/article/details/104778290
边栏推荐
- JS to download files in batches
- MySQL queries difference sets (missing data) by linking tables based on an associated field
- 淘宝商品销量接口/淘宝商品销量监控接口/商品累计销量接口
- 8、 JS data type conversion
- JS gets the first month of the year, the second month to the last month, and the first day to the last day
- WARNING:tornado.access:404 GET /favicon.ico (172.16.8.1) 1.84ms [附静态文件设置]
- JS string method
- VI editor
- redis. exceptions. ConnectionError: Error 111 connecting to 172.16.8.128:6379. Connection refused.
- Deploy Yum warehouse and NFS shared services
猜你喜欢
![WARNING:tornado. access:404 GET /favicon. ICO (172.16.8.1) 1.84ms [with static file settings]](/img/6d/6eef1f0ebcab45e9a209a3b6c62b03.png)
WARNING:tornado. access:404 GET /favicon. ICO (172.16.8.1) 1.84ms [with static file settings]

VI editor

1. Learning sequence of SolidWorks modules

Buffer Overflow Vulnerability Lab

Disk management and disk partition operation

2020-12-28

How app inventor accesses resource files in assets directory

About RSA encryption and decryption principle

JS - set countdown for Date object case

4. Relationship selector (parent-child relationship, ancestor offspring relationship, brother relationship)
随机推荐
A solution to create a new EXCEL workbook on win10 computer and change the suffix to xlsm (normally it should be xlsx)
淘宝商品销量接口/淘宝商品销量监控接口/商品累计销量接口
Container concept and cloud native
Object array de encapsulation
Filebeat collects logs to elk
Taobao commodity sales interface / Taobao commodity sales monitoring interface / cumulative commodity sales interface
2021-04-16
[leetcode weekly race record] record of the 80th biweekly race
À propos des principes de chiffrement et de décryptage RSA
Browser render passes
JS array using the reduce() method
Notes on development experience: TP5 exp query, SQL analysis, JQ, applet, right-click menu, Linux skills, shell skills, mysql, etc
Document contains question type
MySQL parsing serialized fields
GBase 8a磁盘问题及处理
Explanation of JS event loop mechanism and asynchronous tasks
Buuctf web (VII)
Deploy Yum warehouse and NFS shared services
Buuctf web (IV)
Batch package and download Alibaba OSS files