uniapp canvas 生成海报并保存到相册
前言:
之前写过一篇canvas小程序画图只要是canvas各种方法的实际应用,有兴趣的小伙伴也可以看看
微信小程序:使用canvas 生成图片 并分享_小程序canvas生成图片-CSDN博客
上一篇文章是小试牛刀,这次是更加全面的记录生成海报的实战应用
一.实现核心原理
1.uni.createCanvasContext----创建canvas画布
uni.createCanvasContext(canvasId, componentInstance) | uni-app官网
2.uni.canvasToTempFilePath ---- 保存临时图片uni.canvasToTempFilePath(object, componentInstance) | uni-app官网
3.uni.saveImageToPhotosAlbum ----下载图片到本地
uni-app官网
利用canvas 先画出二倍图(这样导出的图片不会模糊),canvas容器本身通过visibility: hidden 进行隐藏,实际用image展示画好的海报,并通过uni.saveImageToPhotosAlbum 可进行下载。
二.实现代码
模板部分:
<!-- canvas 绘制海报 --><view class="poster_box" v-if="showPoster"><view class="poster_title_box"><view class="poster_title">生成海报</view><image @click="() => showPoster = false" class="poster_close"src="close.png"mode="scaleToFill" /></view><image class="canvas_image" :src="lastGeneratedImage" alt="" show-menu-by-longpress/><view class="poster_save_box" @click="savePosterByQR"><image class="poster_save"src="https://bhk-cms.oss-accelerate.aliyuncs.com/wechat/static/image/poster/poster_save.png"mode="scaleToFill" /><view class="poster_save_text">保存海报到本地</view></view><canvas canvas-id="positionPoster" class="canvas" :style="{width: canvasW,height:canvasH}"></canvas></view><!-- 海报遮罩 -->
<view v-if="showPoster" class="mask" @click="() => showPoster = false"></view>
样式部分:
.mask {position: fixed;top: 0;left: 0;width: 100%;height: 100%;background: #00000066;z-index: 120;
}.poster_box {position: absolute;top: 0;bottom: 0;left: 0;right: 0;margin: auto;display: flex;flex-direction: column;justify-content: center;align-items: center;text-align: center;z-index: 121;width: 606rpx;.poster_title_box {width: 100%;text-align: center;position: relative;font-family: PingFang SC;margin-bottom: 48rpx;.poster_title {font-size: 32rpx;font-weight: 500;line-height: 48rpx;color: #fff;}.poster_close {position: absolute;top: 0;bottom: 0;margin: auto;right: 0;width: 48rpx;height: 48rpx;}}.poster_save_box {margin-top: 40rpx;.poster_save {width: 96rpx;height: 96rpx;margin-bottom: 8rpx;}.poster_save_text {font-family: PingFang SC;font-size: 28rpx;font-weight: 500;line-height: 44rpx;text-align: center;color: #fff;}}.canvas_image {width: 606rpx;height: 924rpx;}.canvas {visibility: hidden;z-index: -999;position: absolute;}
}
vue部分:
function fillBg(ctx, height, color1, color2 = color1) {const gradient = ctx.createLinearGradient(0, height, 0, 0); // 从下往上渐变gradient.addColorStop(0, color1); // 起点颜色gradient.addColorStop(1, color2); // 终点颜色ctx.fillStyle = gradient;
}
function useCanvas() {const showPoster = ref(false);const canvas_finished = ref(true);const lastGeneratedImage = ref(null);const showPosterContent = ref(false);// 获取屏幕宽度和设备像素比const dpr = uni.getWindowInfo().pixelRatio; // 设备像素比const logicalWidth = toPx(303); // 逻辑宽度const logicalHeight = toPx(462); // 逻辑高度const canvasWidth = logicalWidth * dpr; // 实际宽度const canvasHeight = logicalHeight * dpr; // 实际高度// const canvasWidth = logicalWidth; // 实际宽度// const canvasHeight = logicalHeight; // 实际高度//绘制海报async function createPoster(options) {canvas_finished.value = true;showPosterContent.value = false;const { originData, houseData, rmb_price, price } = options;const width = toPx(303);const height = toPx(462);// 获取屏幕宽度(单位为 px)const screenWidth = uni.getWindowInfo().screenWidth;const screenHeight = uni.getWindowInfo().screenHeight;// 检查是否已经生成过图像if (lastGeneratedImage.value) {// 如果已经生成过图像,直接使用上次的图像数据const ctx = uni.createCanvasContext("positionPoster");ctx.clearRect(0, 0, width, height); // 清除画布ctx.drawImage(lastGeneratedImage.value, 0, 0); // 将上次的图像绘制回canvasctx.draw();showPosterContent.value = true;uni.hideLoading();return; // 结束,不再重新生成}//初始化画布const ctx = uni.createCanvasContext("positionPoster");// ctx.scale(dpr, dpr);// 提取圆角值const bgRadius = [toPx(8), toPx(8), toPx(48), toPx(8)];/* 背景 */// 创建线性渐变(垂直方向,模拟 360deg)fillBg(ctx, height, "#669CFF", "#1F7CFF");/* 外层-圆角矩形开始 */drawRoundedRect(ctx, 0, 0, width, height, toPx(8));/* 外层-圆角矩形结束 *///画logo和背景图await drawImageWithCache(ctx,posterLogo,toPx(14),toPx(16),toPx(130),toPx(32));await drawImageWithCache(ctx,posterBg,toPx(229),toPx(7),toPx(56),toPx(56));//主要内容-content// /* content-圆角矩形开始 */ctx.setFillStyle("#fff");drawRoundedRect(ctx, toPx(14), toPx(60), toPx(275), toPx(316), toPx(8));/* content-圆角矩形结束 */// banner/* banner-圆角矩形开始 */ctx.fillStyle = "#fff";ctx.save(); // 保存当前绘制状态drawRoundedRect(ctx, toPx(26), toPx(72), toPx(251), toPx(154), toPx(4));ctx.clip(); // 限制绘制区域为圆角矩形/* banner-圆角矩形结束 *//* banner图绘制开始*/const firstImg =originData.thumbnail + "?x-oss-process=image/resize,w_251/quality,q_85";await drawImageWithCache(ctx,firstImg,toPx(26),toPx(72),toPx(251),toPx(154));// 恢复ctx.restore();/* banner图绘制结束*///titlectx.fillStyle = "#000";ctx.font = "18px PingFang SC";ctx.setFontSize(toPx(18));//多行显示toFormateStr(ctx,originData.title,toPx(26),toPx(250),toPx(26),toPx(250));//两室两厅一卫 |90㎡| 芭提雅ctx.fillStyle = "#555";ctx.font = "10px PingFang SC";ctx.setFontSize(toPx(10));const room =houseData.bedroom === 0? "开间": `${houseData.bedroom || "-"}卧${houseData.toilet || "-"}卫`;const area = houseData.building || "-";const location = houseData.area === 168 ? "芭提雅" : "曼谷";const info = `${room} | ${area}㎡ | ${location} `;ctx.fillText(info, toPx(26), toPx(302), toPx(250));//tag标签await drawImagesInRow(ctx, houseData);//价格drawPriceText(ctx, houseData, rmb_price, price);//画图二维码/* 二维码-圆角矩形开始 */ctx.fillStyle = "#fff";ctx.save(); // 保存当前绘制状态drawRoundedRect(ctx, toPx(233), toPx(390), toPx(56), toPx(56), toPx(4));ctx.clip();await drawImageWithCache(ctx,originData.wx_qr_code,toPx(237),toPx(394),toPx(48),toPx(48));// // 恢复ctx.restore();/* 二维码-圆角矩形结束 *//* 右侧-文字部分 */ctx.fillStyle = "#fff";ctx.font = "14px PingFang SC";ctx.setFontSize(toPx(14));ctx.fillText("找大管家做省心业主", toPx(14), toPx(414), toPx(420));ctx.fillStyle = "#e3eeff";ctx.font = "8px PingFang SC";ctx.setFontSize(toPx(8));ctx.fillText("长按扫描二维码,查看详情", toPx(14), toPx(430), toPx(432));// 渲染// 保存本次生成的海报图为缓存ctx.draw(false, () => {uni.canvasToTempFilePath({canvasId: "positionPoster",width: canvasWidth,height: canvasHeight,destWidth: canvasWidth,destHeight: canvasHeight,success: function (res) {lastGeneratedImage.value = res.tempFilePath; // 缓存图片canvas_finished.value = false;showPosterContent.value = true;uni.showToast({title: "绘制成功",});},fail: function (error) {uni.showToast({title: "绘制失败",});},complete: function complete() {uni.hideLoading();uni.hideToast();},});});}//保存海报let isSaving = false; // 用于标记当前操作是否正在进行function savePosterByQR() {// 如果正在保存,直接返回,不执行后续操作if (isSaving) {return;}isSaving = true; // 设置标记,表示正在保存操作// 如果已缓存海报,直接返回if (lastGeneratedImage.value) {saveToUser(lastGeneratedImage.value);} else {isSaving = false; // 结束操作,重置标记}function saveToUser(tempFilePath) {// 画板路径保存成功后,调用方法把图片保存到用户相册uni.saveImageToPhotosAlbum({filePath: tempFilePath,success: (res) => {showPoster.value = false;uni.showToast({title: "保存成功",icon: "success",});isSaving = false; // 操作完成,重置标记},fail: (err) => {uni.showToast({title: "保存失败",icon: "fail",});showPoster.value = false;isSaving = false; // 操作完成,重置标记},});}}//隐藏海报function cancelPosterContent() {showPoster.value = false;showPosterContent.value = false;}return {showPoster,canvas_finished,showPosterContent,dpr,lastGeneratedImage,savePosterByQR,createPoster,cancelPosterContent,};
}
//多行文字绘制
/*** 将字符串格式化为适合在画布上显示的格式** @param ctx 画布上下文* @param str 需要格式化的字符串* @param axisX 文本在画布上的起始x坐标* @param axisY 文本在画布上的起始y坐标* @param titleHeight 每行文本的高度* @param maxWidth 每行文本的最大宽度*/
//多行文本
export function toFormateStr(ctx, str, axisX, axisY, titleHeight, maxWidth) {// 文本处理let strArr = str.split("");let row = [];let temp = "";for (let i = 0; i < strArr.length; i++) {if (ctx.measureText(temp).width < maxWidth) {temp += strArr[i];} else {i--; //这里添加了i-- 是为了防止字符丢失,效果图中有对比row.push(temp);temp = "";}}row.push(temp); // row有多少项则就有多少行//如果数组长度大于2,现在只需要显示两行则只截取前两项,把第二行结尾设置成'...'if (row.length > 2) {let rowCut = row.slice(0, 2);let rowPart = rowCut[1];let test = "";let empty = [];for (let i = 0; i < rowPart.length; i++) {if (ctx.measureText(test).width < maxWidth) {test += rowPart[i];} else {break;}}empty.push(test);let group = empty[0] + "..."; //这里只显示两行,超出的用...表示rowCut.splice(1, 1, group);row = rowCut;}// 把文本绘制到画布中for (let i = 0; i < row.length; i++) {// 一次渲染一行ctx.fillText(row[i], axisX, axisY + i * titleHeight, maxWidth);}// // 保存当前画布状态// ctx.save();// // 将之前在绘图上下文中的描述(路径、变形、样式)画到 canvas 中。// ctx.draw();
}
//绘制图片
export function drawImageWithCache(context, imgUrl, x, y, width, height) {return new Promise((resolve, reject) => {uni.getImageInfo({src: imgUrl,success: function (res) {context.drawImage(res.path, x, y, width, height);resolve();},fail: function (err) {console.error("图片加载失败:", err);reject(err);},});});
}
//绘制圆角矩形
export function drawRoundedRect(ctx,x,y,width,height,r1,r2 = r1,r3 = r1,r4 = r1
) {ctx.beginPath();// 左上角ctx.arc(x + r1, y + r1, r1, Math.PI, Math.PI * 1.5);// 上边线ctx.lineTo(x + width - r2, y);ctx.arc(x + width - r2, y + r2, r2, Math.PI * 1.5, Math.PI * 2);// 右边线ctx.lineTo(x + width, y + height - r3);ctx.arc(x + width - r3, y + height - r3, r3, 0, Math.PI * 0.5);// 下边线ctx.lineTo(x + r4, y + height);ctx.arc(x + r4, y + height - r4, r4, Math.PI * 0.5, Math.PI);// 左边线ctx.lineTo(x, y + r1);ctx.arc(x + r1, y + r1, r1, Math.PI, Math.PI * 1.5);ctx.closePath(); // 闭合路径ctx.fill(); // 填充路径
}
//多行tag
export async function drawImagesInRow(ctx, houseData) {// 设置起始位置和间距let currentX = toPx(26); // 起始位置,x 坐标const yPosition = toPx(312); // 图片绘制的 y 坐标const spacing = toPx(4); // 图片之间的间距// 遍历每个图像 URL,依次绘制图片for (let i = 0; i < imageUrls.length; i++) {const image = imageUrls[i];// 异步加载并绘制图片await drawImageWithCache(ctx,image.src,currentX,yPosition,image.width,image.height);// 更新当前的 x 坐标,图像绘制完成后将 x 坐标向右移动,考虑到间距currentX += image.width + spacing;}
}
//单位转换
export function toPx(px) {const devicePi = uni.getWindowInfo().pixelRatio;const screenWidth = uni.getWindowInfo().screenWidth;return (px / 375) * screenWidth;
}
海报展示:
相关文章:
uniapp canvas 生成海报并保存到相册
前言: 之前写过一篇canvas小程序画图只要是canvas各种方法的实际应用,有兴趣的小伙伴也可以看看 微信小程序:使用canvas 生成图片 并分享_小程序canvas生成图片-CSDN博客 上一篇文章是小试牛刀,这次是更加全面的记录生成海报的…...
无人机不等同轴旋翼架构设计应用探究
“结果显示,对于不等组合,用户应将较小的螺旋桨置于上游以提高能效,但若追求最大推力,则两个相等的螺旋桨更为理想。” 在近期的研究《不等同轴旋翼性能特性探究》中,Max Miles和Stephen D. Prior博士深入探讨了不同螺…...
C语言中隐式类型转换 截断和整型提升
C的整形算数总是至少以缺省整形类型的精度来进行的 为了获得这个精度 表达式中的字符和短整形操作数在使用之前被转换为普通整形 这种类型转换成为整型提升 给出代码实例↓ #include<stdio.h> int main() {//char signed charchar a 3;char b 127;char c a b;pri…...
R语言学习计划启动
R语言入门课 生信基地已然落地,我们希望能够给大家提供系统性、形成性、规范性的生信教学。前面几次活动中同学们表示希望能够有线下集中学习以及针对性的指导、答疑。所以,此次我们计划于2025年02月22日~23日(周六周日)推出"生信R语言入门课"…...
AI写代码工具时代:前端开发技能迭代的挑战与应对
近年来,人工智能(AI)技术飞速发展,深刻地改变着各个行业,前端开发领域也不例外。AI技术不仅带来了新的开发模式,也显著加快了前端开发技能的迭代速度,给前端工程师带来了巨大的挑战。本文将深入…...
消息队列之-springcloud-mq-stream 学习
背景: 开发中我们往往需要用到mq中间件进行消息处理,但是市面上的mq中间件实在太多了,导致我们在集成过程中困难重重,尤其在微服务当中,比如我们有一个订单模块、物流模块 他们都用到了mq,订单用的是rabbitmq 物流用的是kafka 导致当我们需要向这两个模块推送mq消息时,需…...
数据结构(考研)
线性表 顺序表 顺序表的静态分配 //线性表的元素类型为 ElemType//顺序表的静态分配 #define MaxSize10 typedef int ElemType; typedef struct{ElemType data[MaxSize];int length; }SqList;顺序表的动态分配 //顺序表的动态分配 #define InitSize 10 typedef struct{El…...
【16届蓝桥杯寒假刷题营】第1期DAY4
5.倍数区间 - 蓝桥云课 5. 倍数区间 问题描述 给定一个长度为 n 的数组 a,定义 f(i) 表示包含 ai 的最长区间长度,要求该区间中的所有数都是 ai 的倍数。请计算不同的 f(i) 的个数,其中 1≤i≤n。 输入格式 第一行包含一个正整数 n …...
「软件设计模式」适配器模式(Adapter)
软件设计模式深度解析:适配器模式(Adapter)(C实现) 一、模式概述 适配器模式(Adapter Pattern)是结构型设计模式中的"接口转换器",它像现实世界中的电源适配器一样&#…...
进阶版MATLAB 3D柱状图
%% 1. 数据准备 % 假设数据是一个任意形式的矩阵 % 例如:5行 x 7列的矩阵 data [3 5 2 6 8 4 7;7 2 6 9 3 5 8;4 8 3 7 2 6 9;6 1 5 8 4 7 2;9 4 7 3 6 2 5];% 定义行和列的标签(可选) rowLabels {Row1, Row2, Row3, Row4, Row5}; % 行标签…...
【Elasticsearch】token filter分词过滤器
以下是Elasticsearch中常见的分词过滤器(Token Filter)的详细说明,基于搜索结果中的信息整理: 1.Apostrophe • 功能:处理文本中的撇号(apostrophe),例如将“OReilly”转换为“ore…...
一天急速通关SpringMVC
一天急速通关SpringMVC 0 文章介绍1 介绍1.1 MVC架构与三层架构1.2 Spring MVC介绍1.3 入门程序 2 请求的映射3 请求数据的接收3.1 RequestParam接收3.2 POJO/JavaBean接收3.3 RequestHeader和CookieValue接收 4 请求数据的传递5 视图5.1 视图的理解5.2 请求转发和响应重定向的…...
MongoDB 7 分片副本集升级方案详解(下)
#作者:任少近 文章目录 1.4 分片升级1.5 升级shard11.6 升级shard2,shard31.7 升级mongos1.8重新启用负载均衡器1.9 推荐MongoDB Compass来验证数据 2 注意事项: 1.4 分片升级 使用“滚动”升级从 MongoDB 7.0 升级到 8.0,即在其他成员可用…...
如何在 MySQL 5.6 中实现按季度分组并找到销量最高的书籍
如何在 MySQL 5.6 中实现按季度分组并找到销量最高的书籍 引言问题描述实现步骤1. 计算每本书在每个季度的累计销量2. 找到每个季度的最高累计销量3. 匹配最高销量的书籍 总结扩展练习 引言 在数据分析和业务报表中,经常需要对数据进行分组统计,并找到每…...
JAVA生产环境(IDEA)排查死锁
使用 IntelliJ IDEA 排查死锁 IntelliJ IDEA 提供了强大的工具来帮助开发者排查死锁问题。以下是具体的排查步骤: 1. 编写并运行代码 首先,我们编写一个可能导致死锁的示例代码: public class DeadlockExample {private static final Obj…...
群体智能优化:粒子群算法(PSO)详解与实战
一、引言:从鸟群行为到优化算法 1995年,社会心理学家James Kennedy和电气工程师Russell Eberhart通过观察鸟群觅食行为,提出了著名的粒子群优化算法(Particle Swarm Optimization, PSO)。这一算法仅用不到30年时间&am…...
k8s集群搭建参考(by lqw)
文章目录 声明配置yum源安装docker安装 kubeadm,kubelet 和 kubectl部署主节点其他节点加入集群安装网络插件 声明 由于看了几个k8s的教程,都存在各种问题,自己搭建的时候,踩了不少坑,最后还是靠百度csdnchatGPT才搭建…...
vue3+vite项目引入electron运行为桌面项目
一、安装electron npm install --save-dev electron二、项目根目录添加electron文件 在此文件夹中添加两个js文件:main.js、preload.js main.js: // Modules to control application life and create native browser window const { app, BrowserWindow } requ…...
教育小程序+AI出题:如何通过自然语言处理技术提升题目质量
随着教育科技的飞速发展,教育小程序已经成为学生与教师之间互动的重要平台之一。与此同时,人工智能(AI)和自然语言处理(NLP)技术的应用正在不断推动教育内容的智能化。特别是在AI出题系统中,如何…...
使用 Flask 构建流式返回服务
使用 Flask 构建流式返回服务是一个很常见的应用场景,特别是在需要逐步传输大数据或进行长时间操作的场景下(比如下载大文件、实时日志等)。Flask 中可以通过 Response 对象来实现流式响应。以下是一个简单的例子,展示了如何在 Fl…...
Redis 集群相关知识介绍
Redis 集群详解:从入门到实战 Redis 是一个高性能的开源数据库,支持多种数据结构,广泛应用于缓存、消息队列、实时分析等领域。随着业务规模的增长,单机 Redis 的性能和容量往往无法满足需求,因此 Redis 集群…...
宏基传奇swift edge偶尔开机BIOS重置
电脑是acer swift edge, SFA16-41,出厂是Win11系统, BIOS版本出厂1.04,更新到了目前最新1.10。 问题是 会偶尔开机ACER图标变小跑到屏幕左上方,下次开机BIOS就会被重置,开机等待很长时间。 因为是偶尔现象的…...
DeepSeek是如何通过“蒸馏”技术打造自己的AI模型
1 引言: 最近,外媒对中国公司——DeepSeek进行了猛烈抨击,指控其采用了所谓的“蒸馏”(Distillation)技术,涉嫌抄袭甚至作弊。那么,什么是“蒸馏”技术? 在人工智能领域,…...
你如何利用SIMD(如SSE/AVX)优化图像处理的性能?
SIMD优化问题 1. SIMD 在图像处理中的优化方式2. 典型应用场景3. SIMD 的常见优化技巧4. 总结 利用 SIMD(Single Instruction, Multiple Data) 指令集(如 SSE/AVX/AVX2/AVX-512)优化图像处理的性能,可以极大地提升计算…...
支付宝 IoT 设备入门宝典(上)设备管理篇
相信不少朋友最近都被支付宝“碰一下”广告刷屏,“不用打开 APP 支付就碰一下”几个字一出简直自带BGM……其实“碰一下”就是支付宝 IoT 设备的一种,趁着热度还在,我会分为设备管理和设备经营上下两篇,简单介绍一下支付宝 IoT&am…...
Go语言 Web框架Gin
Go语言 Web框架Gin 参考 https://docs.fengfengzhidao.com https://www.liwenzhou.com/posts/Go/gin/#c-0-7-2 返回各种值 返回字符串 package mainimport ("net/http""github.com/gin-gonic/gin")func main() {router : gin.Default()router.GET("…...
蓝桥杯-洛谷刷题-day5(C++)(为未完成)
1.P1328 [NOIP2014 提高组] 生活大爆炸版石头剪刀布 i.题目 ii.代码 #include <iostream> #include <string> using namespace std;int N, Na, Nb; //0-"剪刀", 1-"石头", 2-"布", 3-"蜥", 4-"斯"࿱…...
【Unity3D优化】使用ASTC压缩格式优化内存
在Unity3D手游开发中,合理选择纹理压缩格式对于优化内存占用、提高渲染效率至关重要。本文将记录近期在项目内进行的图片压缩格式优化过程,重点介绍从ETC2到ASTC 5x5的优化方案及其带来的收益。 1. 现状分析:从ETC2到ASTC 6x6 block 在项目…...
NO.13十六届蓝桥杯备战|条件操作符|三目操作符|逻辑操作符|!||||(C++)
条件操作符 条件操作符介绍 条件操作符也叫三⽬操作符,需要接受三个操作数的,形式如下: exp1 ? exp2 : exp3条件操作符的计算逻辑是:如果 exp1 为真, exp2 计算, exp2 计算的结果是整个表达式的结果&am…...
【uniapp-小程序】实现方法调用的全局tips弹窗
【uniapp-小程序】实现方法调用的全局tips弹窗 开发背景弹窗组件全局调用封装配置项入参全局注入使用 附带:如何在uniapp-H5项目中实现全局自定义弹窗组件定义定义vue插件引入 笑死,只有在想找工作的时候才会想更新博客。 开发背景 本来是个uniapp开发…...
springboot如何将lib和jar分离
遇到一个问题,就是每次maven package或者maven install后target中的jar很大,少的50几MB,大的100多兆 优化前: 优化后: 优化前 优化后压缩率77.2MB4.65MB93% 具体方案: pom.xml中 <build><…...
深入探索C语言中的字符串处理函数:strstr与strtok
在C语言的字符串处理领域, strstr 和 strtok 是两个非常重要的函数,它们各自承担着独特的功能,为开发者处理字符串提供了强大的支持。 一、strstr函数:字符串查找的利器 strstr 函数用于在一个字符串中查找另一个字符串的首次出现…...
Django学习笔记(第一天:Django基本知识简介与启动)
博主毕业已经工作一年多了,最基本的测试工作已经完全掌握。一方面为了解决当前公司没有自动化测试平台的痛点,另一方面为了向更高级的测试架构师转型,于是重温Django的知识,用于后期搭建测试自动化平台。 为什么不选择Java&#x…...
npm版本号标记
在 npm 中,版本号的标记遵循 语义化版本控制(Semantic Versioning, SemVer) 的规则,版本号通常由 主版本号(major)、次版本号(minor) 和 修订版本号(patch) 组成,格式为: <major>.<minor>.<patch>1. 版本号格式 主版本号(major):当你做了不兼…...
无人机雨季应急救灾技术详解
无人机在雨季应急救灾中发挥着至关重要的作用,其凭借机动灵活、反应迅速、高效安全等特点,为救灾工作提供了强有力的技术支撑。以下是对无人机雨季应急救灾技术的详细解析: 一、无人机在雨季应急救灾中的应用场景 1. 灾情侦查与监测 无人机…...
算法与数据结构(多数元素)
题目 思路 方法一:哈希表 因为要求出现次数最多的元素,所以我们可以使用哈希映射存储每个元素及其出现的次数。每次记录出现的次数若比最大次数大,则替换。 方法二:摩尔算法 摩尔的核心算法就是对抗,因为存在次数多…...
详解如何使用Pytest内置Fixture tmp_path 管理临时文件
关注开源优测不迷路 大数据测试过程、策略及挑战 测试框架原理,构建成功的基石 在自动化测试工作之前,你应该知道的10条建议 在自动化测试中,重要的不是工具 临时目录在测试中起着至关重要的作用,它为执行和验证代码提供了一个可控…...
量子计算的五大优势
量子计算的优势有哪些? 量子计算是一个快速发展的领域,有望彻底改变我们处理复杂计算问题的方式。那么,量子计算的优势是什么?与经典计算相比,量子计算又有哪些优势呢?当我们探索量子力学的世界以及量子系…...
行内元素和块级元素
行内元素和块级元素 1.行内元素1.1什么是行内元素1.2行内元素的特点1.3常见的行内元素 2.块级元素2.1什么是块级元素2.2块级元素的特点2.3常见的块级元素 3.行内元素和块级元素的区别 1.行内元素 1.1什么是行内元素 行内元素是指在网页中不会独占一行,而是与其他行内元素在同…...
java面试题-集合篇
Collection 1.Collection有哪些类? Java集合框架中的Collection接口是所有集合类的基础接口,定义了一些基本的集合操作,如添加元素、删除元素、判断是否包含某个元素等。常见的集合类包括List、Set和Queue。 List List接口定义了按照索引…...
二十九、vite项目集成webpack+vue2项目
一、开发 基座应用: 1、安装依赖 npm i @micro-zoe/micro-app@0.8.6 --save 2、在入口处引入(main.ts) import microApp from @micro-zoe/micro-appmicroApp.start()...
小程序之间实现互相跳转的逻辑
1:小程序之间可以实现互相跳转吗 可以实现互相跳转! 2:小程序跳转是否有限制 有限制!限制如下 2.1:需要用户触发跳转 从 2.3.0 版本开始,若用户未点击小程序页面任意位置,则开发者将无法调用此接口自动跳转至其他小程序。 2.2:需要用户确认跳转 从 2.3.0 版本开始…...
算法——数学建模的十大常用算法
数学建模的十大常用算法在数学建模竞赛和实际问题解决中起着至关重要的作用。以下是这些算法的具体信息、应用场景以及部分算法的C语言代码示例(由于篇幅限制,这里只给出部分算法的简要代码或思路,实际应用中可能需要根据具体问题进行调整和扩…...
cookie、session、jwt、Oauth2.0、sso 分别有什么用
cookie、session、jwt都是 web 应用中的认证方式,最早只有 cookie,后面觉得所有数据存储在客户端不安全,就出现了 cookie-session,再后面有了 jwt。 cookie工作原理 cookie 数据存储在用户的本地。服务器完全根据 cookie 确定访…...
maven使用默认settings.xml配置时,Idea基于pom.xml更新依赖时报错,有些组件下载时连接超时
1、问题背景:maven使用默认settings.xml配置时,Idea基于pom.xml更新依赖时报错,有些组件下载时连接超时, 通过日志发下,去连接maven.org网站下载依赖,有时候肯定会超时。 2、解决办法:使用国外…...
信息收集-Web应用搭建架构指纹识别WAF判断蜜罐排除开发框架组件应用
知识点: 1、信息收集-Web应用-架构分析&指纹识别 2、信息收集-Web应用-架构分析&WAF&蜜罐 3、信息收集-Web应用-架构分析&框架组件识别 指纹识别 EHole_magic https://github.com/lemonlove7/EHole_magic 指纹识别 Wappalyzer https://github.com…...
蓝桥杯之图
图: 对于图来说,重点在于之后的最短路径算法,这边简单做一下了解即可...
ProxySQL构建PolarDB-X标准版高可用路由服务三节点集群
ProxySQL构建PolarDB-X标准版高可用路由服务三节点集群 一、PolarDB-X标准版主备集群搭建 三台机器上传 polardbx 包,包可以从官网https://openpolardb.com/download获取,这里提供离线rpm。 1、上传 polardbx 安装包 到 /opt目录下 rpm -ivh t-pol…...
【leetcode】双指针:移动零 and 复写零
文章目录 1.移动零2.复写零 1.移动零 class Solution { public:void moveZeroes(vector<int>& nums) {for (int cur 0, dest -1; cur < nums.size(); cur)if (nums[cur] ! 0)swap(nums[dest], nums[cur]);} };class Solution { public:void moveZeroes(vector&l…...
正则化(Regularization)和正则表达式(Regular Expression)区别
文章目录 1. **正则化(Regularization)**2. **正则表达式(Regular Expression)**关键区别为什么名字相近? 正则化(Regularization)和正则表达式(Regular Expression)不是…...