openlayers系列:加载arcgis和geoserver在线离线切片
https://www.freesion.com/article/1751396517/
1.背景
有个项目需要使用openlayer加载各种服务上发布的数据,坐标系也不同,我们都知道openalyer默认可以加载EPAG:3857,要加载4490的坐标系的数据需要重新定义一下,之后再加载。一想起要重新定义坐标系感觉很难,就想放弃,其实静下心了做一下也没那么难。在此做个简单的记录,要加载的数据如下:
1.1 arcgis 服务

1.2 本地切好的瓦片服务

1.3结果 加载好天地图、4490arcgisserver 服务、本地影像切片

2.解决思路
2.1 原理
使用proj4js 给所有坐标和范围提供视图投影系(默认是EPAG:3857),给每个要加载的图层设置此坐标系即可正常加载。
2.2 资源
(1).API OpenLayers v7.4.0 API
(2)epsg EPSG.io: Coordinate Systems Worldwide
了解有关各种投影的参数定义
(3)proj4js proj4js (v2.9.0) https://www.bootcdn.cn/proj4js/
2.3 重新定义坐标系步骤
(1)proj4引用 前端添加Proj4js有三种方式:
- 从 http://trac.osgeo.org/proj4js/wiki/Download下载,获取产品包中dist/proj4.js文件。
- 引入CDN上的Proj4js: https://cdnjs.com/libraries/proj4js
- 本地有Node.js,可以直接使用npm install proj4 --save进行安装。
(2)基础使用
proj4.js中预定义了三个坐标系,其他的坐标系则需要自己定义了,下面以从WGS84(4326)到Web墨卡托(3857)的转换为例
function Wgs84ToMector2(lat,lng) {const proj4 = require('proj4');return proj4(proj4('EPSG:4326'), proj4('EPSG:3857'), [lng, lat])
}
定义坐标系:
function init4490(){proj4.defs("EPSG:4490","+proj=longlat +ellps=GRS80 +no_defs +type=crs");
//4490的坐标系注册进openlayer的projection中register(proj4);
//重写projection4490,地图投影var projection = new Projection({code: 'EPSG:4490',units: 'degrees',axisOrientation: 'neu'});addProjection(projection);projection.setExtent([-180, -90, 180, 90]);projection.setWorldExtent([-180, -90, 180, 90]);projection.getMetersPerUnit = function(){return 2 * Math.PI * 6378137 / 360;};addCoordinateTransforms( "EPSG:4326","EPSG:4490", function( coordinate){return proj4("EPSG:4490", "EPSG:4326",coordinate);},function(coordinate){return proj4("ERSG:4490" , "EPSG:4326" , coordinate);});
}
其中 proj4.defs("EPSG:4490","+proj=longlat +ellps=GRS80 +no_defs +type=crs");是从epsg的网站上获取的参数,如下图:【输入4490坐标系】---【选择proj4js】---【复制】即可。

定义好4490坐标系后,需要注册和重写projection
3.加载多源不同坐标系的地图
3.1加载arcgis server wmts服务
function getWMTSLayer(options) {const projections = options.projection?options.projection:projection4326;const res = getResolutionsAndMids(projections);return new TileLayer({source: new WMTS({name: "中国",url: options.url,layer: options.layer, // 图层名version: '1.0.0',// WMTS版本style: options.style?options.style:"default",matrixSet: options.matrixSet?options.matrixSet:"c", // 投影坐标系矩阵集,一定要和WMTS capabilities文档中一致,否则会加载失败format: options.format?options.format:"tiles", // 图片格式wrapX: true,tileGrid: new WMTSTileGrid({// 投影坐标系origin: getTopLeft(projections.getExtent()),resolutions: res.resolutions,matrixIds: res.matrixIds,}),projection: projections // 投影坐标系}),})
}
3.2加载切好的本地图层
function getXYZLayer(options) {const projections = options.projection?options.projection:projection4326;return new TileLayer({title: '泾阳',source: new XYZ({url: options.url,projection: projections})})
}
4.图层顺序
在 openlayer 中,图层是使用 layer 对象表示的,主要有 WebGLPoints Layer、 热度图(HeatMap Layer)、图片图层(lmage Layer)、切片图层(Tile Layer)和 矢量图层(Vector Layer)五种类型,它们都是继承 Layer 类的。
常用参数
- source,指定了图层的数据来源,图层作用是以一定的样式渲染数据,source则指定了数据visible ,是否可见;
- zlndex,图层的叠加次序,默认是0,最底层,如果使用setMap方法添加的图层,zlndex值是Infinity,在最上层:
- extent,图层消染的区域,即浏览器窗口中可见的地图区域。extent是一个矩形范用,格式是number, number,number, numberl 分别代表[left,botom.right.top]。为了提升染效率和加载速度,extent范用之外的瓦片是不会请求的,当然也不会演染className,图层各个元素的样式:
- opacity,透明度,默认为 1,即完全透明:
找到新建Map对象的时候,调整layers的顺序,layer越往右,图层越往上显示。
var layer = new Vector({source: new Vector({projection: 'EPSG:4326',format: new GeoJSON()}),style: styleFunction,zIndex:9999
});
5.控制图层显示影藏
//获取某一图层
const getLayerInfo = (map,name) => {const layers = map?.getAllLayers();if (layers) {return layers.find((item) => item?.getProperties().title == name);}
};
//在某一视域范围内显示
function change(map){
// 定义指定区域的边界坐标(经度、纬度)//var extent = transformExtent([westLongitude, southLatitude, eastLongitude, northLatitude], 'EPSG:4326', 'EPSG:3857');var extent = transformExtent(["108.495435118675", "34.4888700423221","108.952496945858", "34.7379809617996"], 'EPSG:4326', 'EPSG:3857');// 监听视图变化事件map.getView().on('change', function() {var view = map.getView();var currentExtent = view.calculateExtent(map.getSize());// 判断当前视图的范围是否在指定区域内var isWithinBounds = containsExtent(extent, currentExtent);let layer = getLayerInfo(map,"cia")console.log(layer)if (isWithinBounds) {console.log('当前视域在指定区域内');layer?.setVisible(false);} else {console.log('当前视域不在指定区域内');layer?.setVisible(true);}});
}
6.整体demo
openalyer.vue
<template lang="pug">
#map
</template>
<script setup>
import Map from 'ol/Map.js';
import View from 'ol/View.js';
import {onMounted, onUnmounted, reactive} from "vue";
import {img_c} from "./map.js";
import {fromLonLat} from 'ol/proj'
onMounted(()=>{const layers1 = img_c()const map = new Map({layers: layers1,target: 'map',view: new View({center: fromLonLat([108.68, 34.6]),//地图中心// extent : [ 119.54811, 29.92294, 120.50942, 30.69748 ],zoom: 12,}),});})</script>
<style scoped lang="less">
#map {position: absolute;width: 100%;height: 900px;
}
</style>
map.js
import {register} from 'ol/proj/proj4'
import {Projection,addProjection,addCoordinateTransforms,get} from 'ol/proj';
import TileLayer from 'ol/layer/Tile.js';
import {WMTS,XYZ} from 'ol/source.js';
import WMTSTileGrid from 'ol/tilegrid/WMTS.js';
import {getWidth,getTopLeft} from 'ol/extent';
import proj4 from 'proj4';function init4490(){proj4.defs("EPSG:4490","+proj=longlat +ellps=GRS80 +no_defs +type=crs");
//4490的坐标系注册进openlayer的projection中register(proj4);
//重写projection4490,地图投影var projection = new Projection({code: 'EPSG:4490',units: 'degrees',axisOrientation: 'neu'});addProjection(projection);projection.setExtent([-180, -90, 180, 90]);projection.setWorldExtent([-180, -90, 180, 90]);projection.getMetersPerUnit = function(){return 2 * Math.PI * 6378137 / 360;};addCoordinateTransforms( "EPSG:4326","EPSG:4490", function( coordinate){return proj4("EPSG:4490", "EPSG:4326",coordinate);},function(coordinate){return proj4("ERSG:4490" , "EPSG:4326" , coordinate);});
}init4490()
//transform([118,32] , 'EPSG:4326' , 'EPSG:4490 ');
const projection4490 = new get('EPSG:4490' );
const projection4326 = new get('EPSG:4326' );
const projection3857 = new get('EPSG:3857' );function getResolutionsAndMids(projection) {const projections = projection?projection:projection4326;let projectionExtent = projections.getExtent();let size = getWidth(projectionExtent) / 256; //size就是一个像素代表的经纬度let matrixIds = [];let resolutions = [];for (let z = 0; z < 20; ++z) {resolutions[z] = size / Math.pow(2, z);matrixIds[z] = z;}return {"resolutions":resolutions,"matrixIds":matrixIds};
}export function getProjection() {return projection4490
}
// WMTS 形式
function getWMTSLayer(options) {const projections = options.projection?options.projection:projection4326;const res = getResolutionsAndMids(projections);return new TileLayer({source: new WMTS({name: "中国",url: options.url,layer: options.layer, // 图层名version: '1.0.0',// WMTS版本style: options.style?options.style:"default",matrixSet: options.matrixSet?options.matrixSet:"c",
// 投影坐标系矩阵集,一定要和WMTS capabilities文档中一致,否则会加载失败format: options.format?options.format:"tiles", // 图片格式wrapX: true,tileGrid: new WMTSTileGrid({// 投影坐标系origin: getTopLeft(projections.getExtent()),resolutions: res.resolutions,matrixIds: res.matrixIds,}),projection: projections // 投影坐标系}),})
}
function getXYZLayer(options) {const projections = options.projection?options.projection:projection4326;return new TileLayer({title: '泾阳',source: new XYZ({url: options.url,projection: projections})})
}
const key ='b9031f80391e6b65bd1dd80dcde1b097';
/**\* 矢量底图 + 矢量注记*/
export function vec_c() {return [getWMTSLayer({"url":'http://t{0-7}.tianditu.gov.cn/vec_c/wmts?tk=' + key, "layer":'vec',"projection":projection4490}),getWMTSLayer({"url":'http://t{0-7}.tianditu.gov.cn/cva_c/wmts?tk=' + key, "layer":'cva',"projection":projection4490}),]
}/**\* 影像底图 + 影像注记*/
export function img_c() {return [// getWMTSLayer({"url":'http://t{0-7}.tianditu.gov.cn/img_c/wmts?tk=' + key, "layer":'img',"projection":projection4490}), getXYZLayer({"url":'https://xxxx/jingyang/imgyx/jyx/{z}/{x}/{y}.png',"projection":projection3857}),getWMTSLayer({"url":'http://xxxx:6080/arcgis/rest/services/jingyang/jingyang1/MapServer/WMTS?',"layer":'jingyang_jingyang1',"projection":projection4490}),getWMTSLayer({"url":'http://t{0-7}.tianditu.gov.cn/cia_c/wmts?tk=' + key, "layer":'cia'}),// getXYZLayer({"url":'http://xxxx:6080/arcgis/rest/services/jingyang/jingyang1/MapServer/tiles/{z}/{x}/{y}.png',"projection":projection4490}),]
}
/**\* 地形底图 + 地形注记*/
export function ter_c() {return [getWMTSLayer({"url":'http://t{0-7}.tianditu.gov.cn/ter_c/wmts?tk=' + key, "layer":'ter',"projection":projection4490}),getWMTSLayer({"url":'http://t{0-7}.tianditu.gov.cn/cta_c/wmts?tk=' + key, "layer":'cta',"projection":projection4490}),]
}
7.其他
7.1 Layer分类
- TitleLayer: 切片图层,用于加载切片数据。切片是指利用网格将一幅地图切成大小相等的小正方形。切片尺寸一般是256*256或者512*512
- ImageLayer:图片图层,主要用于服务器渲染的图像,
- VectorLayer:矢量图层,是指在客户端渲染的图层类型
- VectorTileLayer:矢量切片图层,和栅格切片一样的思路。
7.2 source类型
source 是 Layer 的重要组成部分,表示图层的来源,也就是服务地址。除了在构造函数中制定外,可以使用 layer.setSource(source) 稍后指定。
基类(不能被实例化,只负责被继承):
- ol.source.Image,提供单一图片数据的类型,直接继承自 ol.source.Source;
- ol.source.Tile,提供被切分为网格切片的图片数据,继承自 ol.source.Source;
- ol.source.Vector,提供矢量图层数据,继承自 ol.source.Source;
可以实例化的类:
- ol.source.BingMaps ,必应地图的切片数据,继承自ol.source.TileImage;
- ol.source.Cluster,聚簇矢量数据,继承自ol.source.Vector;
- ol.source.ImageCanvas,数据来源是一个 canvas 元素,其中的数据是图片,继承自 ol.source.Image;
- ol.source.ImageMapGuide,Mapguide 服务器提供的图片地图数据,继承自 ol.source.Image,fire ol.source.ImageEvent;
- ol.source.ImageStatic,提供单一的静态图片地图,继承自ol.source.Image;
- ol.source.ImageVector,数据来源是一个 canvas 元素,但是其中的数据是矢量来源 ol.source.Vector,继承自 ol.source.ImageCanvas;
- ol.source.ImageWMS,WMS 服务提供的单一的图片数据,继承自 ol.source.Image,触发 ol.source.ImageEvent;
- ol.source.MapQuest,MapQuest 提供的切片数据,继承自 ol.source.XYZ;
- ol.source.OSM,OpenStreetMap 提供的切片数据,继承自 ol.source.XYZ;
- ol.source.Stamen,Stamen 提供的地图切片数据,继承自 ol.source.XYZ;
- ol.source.TileVector,被切分为网格的矢量数据,继承自 ol.source.Vector;
- ol.source.TileDebug,并不从服务器获取数据,而是为切片渲染一个网格,继承自 ol.source.Tile;
- ol.source.TileImage,提供切分成切片的图片数据,继承自 ol.source.Tile,触发 ol.source.TileEvent;
- ol.source.TileUTFGrid,TileJSON 格式 的 UTFGrid 交互数据,继承自 ol.source.Tile;
- ol.source.TileJSON,TileJSON 格式的切片数据,继承自 ol.source.TileImage;
- ol.source.TileArcGISRest,ArcGIS Rest 服务提供的切片数据,继承自 ol.source.TileImage;
- ol.source.WMTS,WMTS 服务提供的切片数据。继承自 ol.source.TileImage;
- ol.source.XYZ,XYZ 格式的切片数据,继承自 ol.source.TileImage;
- ol.source.Zoomify,Zoomify 格式的切片数据,继承自 ol.source.TileImage。
7.3 proj常见方法
(1)ol.proj.addCoordinateTransforms(source, destination, forward, inverse)
注册坐标转换函数来转换源投影和目标投影之间的坐标。正、反函数转换坐标对;此函数将这些转换为内部使用的处理区段和坐标数组的函数
source:源投影
destination:目标投影
forward:接受ol的正向变换函数(即从源投影到目标投影)。作为参数,并返回转换后的ol.Coordinate
inverse:接受ol的逆变换函数(即从目标投影到源投影)。作为参数,并返回转换后的ol.Coordinate
(2)ol.proj.addEquivalentProjections(projections)
注册不改变坐标的转换函数。它们允许在具有相同含义的投影之间进行转换。
(3)ol.proj.addProjection(projection)
将投影对象添加到受支持的投影列表中,这些投影可以通过它们的SRS码进行查找。
(4)ol.proj.equivalent(projection1, projection2)
检查两个投影是否相同,即一个投影中的每个坐标确实表示另一个投影中的相同地理点。
(5)ol.proj.fromLonLat(coordinate, opt_projection)
将经纬度坐标转换为不同的投影
coordinate:经纬度数组,经度在前,纬度在后
projection:目标投影。默认是Web Mercator,即“EPSG: 3857”
(6)ol.proj.get(projectionLike)
获取指定代码的投影对象。
(7)ol.proj.getTransform(source, destination)
给定类似于投影的对象,搜索转换函数将坐标数组从源投影转换为目标投影。
(8)ol.proj.setProj4(proj4)
proj4注册。如果没有显式注册,则假定proj4js将加载在全局名称空间中
ol.proj.setProj4(proj4);
(9)ol.proj.toLonLat(coordinate, opt_projection)
将坐标转换为经度/纬度
coordinate:投影坐标
projection:坐标的投影,默认是Web Mercator,即“EPSG: 3857”
(10)ol.proj.transform(coordinate, source, destination)
将坐标从源投影转换为目标投影,这将返回一个新的坐标(并且不修改原始坐标)。
coordinate:坐标
source:源投影
destination:目标投影
(11)ol.proj.transformExtent
将范围从源投影转换为目标投影,这将返回一个新范围(并且不修改原始范围)。
(12)ol.proj.Units{string}
投影单位:'degrees', 'ft', 'm', 'pixels', 'tile-pixels' or 'us-ft'
8. 参考文章
开源GIS(二)——openlayers加载Arcgis和geoserver在线离线切片 - 灰信网(软件开发博客聚合)
相关文章:
openlayers系列:加载arcgis和geoserver在线离线切片
https://www.freesion.com/article/1751396517/ 1.背景 有个项目需要使用openlayer加载各种服务上发布的数据,坐标系也不同,我们都知道openalyer默认可以加载EPAG:3857,要加载4490的坐标系的数据需要重新定义一下,之后再加载。一想起要重新…...
《人工智能安全》课程总体结构
1 课程内容 人工智能安全观:人工智能安全问题、安全属性、技术体系等基本问题进行了归纳整理。人工智能安全的主要数据处理方法,即非平衡数据分类、噪声数据处理和小样本学习。人工智能技术赋能网络空间安全攻击与防御:三个典型实例及攻击图…...
unity关于匀速移动某些值的方法
可能很多人会用到Verctor3.Lerp、Mathf.LerpUnclamped等等 这种其实不是匀速 看一下这个整体差不多的逻辑 public static float Lerp(float a, float b, float t){return a (b - a) * t;};这个逻辑就是,从a值到b值,返回一个a值加(b值-a值&…...
解决VScode下载太慢的问题记录
最近突然想重新下载vscoded便携免安装版,发现下载很慢,于是乎查询一下,以便记录 下载地址 VScode官方网站: https://code.visualstudio.com/ 根据个人的需求选择下载,页面加载下载需要等一会, 然后就会…...
Gitlab服务器备份恢复及系统升级
居安思危,思则有备,有备无患。 基于此,申请了一个测试服务器,准备先安装同版本服务器,按照最新的数据进行恢复,然后再将现在的服务器升级到Gitlab的最新版本,记录一下完整的过程,以…...
docker入门讲解
目录 第 1 章 Docker核心概念与安装 为什么使用容器? Docker是什么 Docker设计目标 Docker基本组成 容器 vs 虚拟机 Docker应用场景 Linux 安装 Docker 第 2 章 Docker镜像管理 镜像是什么 镜像从哪里来? 镜像与容器联系 镜像常用管理命令 镜像存储核心技术:联…...
【Matlab】基于卷积神经网络的数据回归预测(Excel可直接替换数据))
【Matlab】基于卷积神经网络的数据回归预测(Excel可直接替换数据) 1.模型原理2.数学公式3.文件结构4.Excel数据5.分块代码6.完整代码7.运行结果1.模型原理 基于卷积神经网络(Convolutional Neural Network,CNN)的数据回归预测是一种常见的机器学习方法,适用于处理具有空…...
在Springboot集成Activiti工作流引擎-引入、调用,测试【基础讲解】
工作流 通过计算机对业务流程自动化执行管理 他主要解决的是使在多个参与者之间按照某种“预定义规则”自动进行传递稳定 信息或任务的过程 通俗来讲 业务上一个玩着的审批流程 比如请假,出差 外出采购等 工作流引擎就是来解决流程问题的 提高我们的工作效率 如果…...
Java书签 #解锁MyBatis的4种批量插入方式及ID返回姿势
1. 今日书签 项目开发中,我们经常会用到单条插入和批量插入。但是实际情况可能是,项目初期由于种种原因,在业务各处直接使用单条插入SQL进行开发(未开启批处理),在后面的迭代中,系统性能问题渐…...
在react项目中如何引入国际化
react-i18next 在 React 项目中引入国际化(Internationalization,简称 i18n)可以使用第三方库来实现。其中,最常用且流行的国际化库是 react-i18next,它基于 i18next 实现,提供了方便易用的国际化功能。下…...
spring学习笔记十三
注解实现管理第三方Bean和为第三方Bean注入资源 1、添加pom坐标 <dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.16</version></dependency> 2、SpringConfig配置类 Configuratio…...
react native 本地存储 AsyncStorage
An asynchronous, unencrypted, persistent, key-value storage system for React Native. Async Storage 只能用来储存字符串数据,所以为了去储存object类型的数据,得先进行序列化(JSON.stringify())当你想要使用数据的时候&…...
Postgresql数据库中的时间类型汇总
PostgreSQL数据库有以下几种时间类型 1 日期 date:表示日期,格式为YYYY-MM-DD。 2 时间 time:表示时间,格式为HH:MI:SS。 3 日期和时间 timestamp:表示日期和时间,格式为YYYY-MM-DD HH:MI:SS。 4 带…...
算法刷题Day 51 最佳买卖股票时机含冷冻期+买卖股票的最佳时期含手续费
Day 51 动态规划 309. 最佳买卖股票时机含冷冻期 关键是要画出状态转移图 然后根据状态转移图来写状态转移方程 class Solution { public:int maxProfit(vector<int>& prices) {int len prices.size();vector<vector<int>> dp(len, vector<int&g…...
编程导航算法村 第五关 | 白银挑战
编程导航算法村 第五关 | 白银挑战 用栈实现队列 LeetCode 232题 class MyQueue {private Stack<Integer> stack; // 保存private Stack<Integer> tempstack; // 临沭队列public MyQueue() {stack new Stack<>();tempstack new Stack<>();}public…...
(十六十七)时序数据库是怎么存储用户名和密码的从InfluxDB OSS迁移数据
以下内容来自 尚硅谷,写这一系列的文章,主要是为了方便后续自己的查看,不用带着个PDF找来找去的,太麻烦! 第 16 章 时序数据库是怎么存储用户名和密码的 1、InfluxDB内部自带了一个用Go语言写的BlotDB,Blo…...
5分钟开发一个AI论文抓取和ChatGPT提炼应用
5分钟开发一个AI论文抓取和ChatGPT提炼应用 第一步 点击“即刻开始” -选择模板 python -修改标题 “AIPaper”,项目标识“AIPaper”,点击“创建项目” 第二步 在编程区域右侧AI区域,输入框输入以下内容: 请根据下面的内容&…...
SK5代理与网络安全:保障爬虫隐匿性与HTTP连接稳定性
一、SK5代理简介 SK5代理,即socks5代理,是一种网络协议,用于在客户端和服务器之间进行数据传输。相比其他代理协议,如HTTP代理,SK5代理具有更高的性能和安全性,支持TCP和UDP连接,并可以处理更复…...
基于4G网络的嵌入式设备远程升级系统设计与实现(学习一)
摘要 随着无线通信技术的不断更新发展,嵌入式设备的联网应用领域得以大规模扩大,远程升级功能成为产品开发中必不可少的一部分。 本文对嵌入式设备远程升级进行了研究,在不改变设备硬件集成度基础上,设计实现了分离式升级的远程…...
陪诊小程序软件|陪诊系统定制|医院陪诊小程序
开发一个陪诊小程序需要投入一定的费用,具体金额会因项目的复杂程度、功能需求和推广政策而有所差异在投入资金之前,建议进行市场调研和需求分析,制定出合理的预算,并选择专业的开发团队进行合作,那么开发陪诊小程序需…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
4. TypeScript 类型推断与类型组合
一、类型推断 (一) 什么是类型推断 TypeScript 的类型推断会根据变量、函数返回值、对象和数组的赋值和使用方式,自动确定它们的类型。 这一特性减少了显式类型注解的需要,在保持类型安全的同时简化了代码。通过分析上下文和初始值,TypeSc…...
(一)单例模式
一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...
背包问题双雄:01 背包与完全背包详解(Java 实现)
一、背包问题概述 背包问题是动态规划领域的经典问题,其核心在于如何在有限容量的背包中选择物品,使得总价值最大化。根据物品选择规则的不同,主要分为两类: 01 背包:每件物品最多选 1 次(选或不选&#…...
n8n:解锁自动化工作流的无限可能
在当今快节奏的数字时代,无论是企业还是个人,都渴望提高工作效率,减少重复性任务的繁琐操作。而 n8n,这个强大的开源自动化工具,就像一位智能的数字助手,悄然走进了许多人的工作和生活,成为提升…...
Python网页自动化测试,DrissonPage库入门说明文档
🛰️ 基本逻辑 操作浏览器的基本逻辑如下: 创建浏览器对象,用于启动或接管浏览器获取一个 Tab 对象使用 Tab 对象访问网址使用 Tab 对象获取标签页内需要的元素对象使用元素对象进行交互 除此以外,还能执行更为复杂的操作&am…...
如何处理React中表单的双向数据绑定?
在前端开发中,双向数据绑定(Two-way Data Binding)是指视图(View)与数据模型(Model)之间保持同步:当模型发生变化时,视图会自动更新;当视图(用户输…...
Vite 双引擎架构 —— Esbuild 概念篇
Vite 底层采用 双引擎架构,核心构建引擎是 Esbuild 和 Rollup,二者在开发和生产环境中分工协作,共同实现高性能构建。不可否认,作为 Vite 的双引擎之一,Esbuild 在很多关键的构建阶段(如依赖预编译、TS 语法转译、代码…...
搭建nginx的负载均衡
1、编写一个configMap的配置文件 events {worker_connections 1024; # 定义每个worker进程的最大连接数 }http {# 定义通用代理参数(替代proxy_params文件)proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-F…...
【CSS-7】深入解析CSS伪类:从基础到高级应用
CSS伪类是前端开发中不可或缺的强大工具,它们允许我们根据文档树之外的信息或简单选择器无法表达的状态来样式化元素。本文将全面探讨CSS伪类的各种类型、使用场景和最佳实践。 1. 伪类基础概念 1.1 什么是伪类? 伪类(Pseudo-class&#x…...
