uniapp微信小程序图片生成水印
整体思路:
- 用户通过uni.chooseImage选择图片后,获得图片文件的path和size。
- 通过path调用uni.getImageInfo获取图片信息,也就是图片宽高。
- 图片宽高等比缩放至指定大小,不然手机处理起来非常久,因为手机随便拍拍就很大。
- 界面定义canvas组件,组件的宽高就是图片缩放后的宽高。
- uni.createCanvasContext创建画布上下文,然后画入图片,再画水印。
- 调用uni.canvasToTempFilePath把画布转成图片。
- 读取生成后的图片信息,获取其大小。
- 压缩图片。
水印后的结果,水印方法不是通用的,只是提供一个思路
1:定义canvas组件
<canvas :style="{ width: watermarkCanvasOption.width + 'px', height: watermarkCanvasOption.height + 'px' }" canvas-id="watermarkCanvas" id="watermarkCanvas" style="position: absolute; top: -10000000rpx;" />
里面定义有样式,让它飞出外太空。
data里面定义画布配置
data () {return {watermarkCanvasOption: {width: 0,height: 0,canvasContext: void (0)}}
}
2:定义添加水印方法
addWatermark (currentTempFile) {return new Promise((resolve, reject) => {uni.showLoading({mask: true,title: '图片生成水印中...'})// 读取选择后的图片信息uni.getImageInfo({src: currentTempFile.path,success: ({ width, height }) => {// 宽度缩放至768附近(具体缩放到多少可以自己在getScaleRatio方法第二个参数定义),高度等比缩放const scaleRatio = this.getScaleRatio(width)const scaleWidth = Math.ceil(width * scaleRatio)const scaleHeight = Math.ceil(height * scaleRatio)// 定义页面画布组件宽高this.watermarkCanvasOption.width = scaleWidththis.watermarkCanvasOption.height = scaleHeightif (!this.watermarkCanvasOption.canvasContext) {// 创建画布上下文this.watermarkCanvasOption.canvasContext = uni.createCanvasContext('watermarkCanvas', this)}const watermarkCanvasContext = this.watermarkCanvasOption.canvasContext// 定义水印信息const watermarkInfo = {mainText: '10:30',secondaryText: `2025-04-09 星期三 福园-谭建林`}// 清空画布watermarkCanvasContext.clearRect(0, 0, scaleWidth, scaleHeight)watermarkCanvasContext.draw()// 画布写入图片watermarkCanvasContext.drawImage(currentTempFile.path, 0, 0, scaleWidth, scaleHeight)// 图片宽高的一半const halfX = Math.ceil(scaleWidth * 0.5)const halfY = Math.ceil(scaleHeight * 0.5)// 字体颜色,方向配置watermarkCanvasContext.setTextAlign('left')watermarkCanvasContext.setFillStyle('#FFF')/*** 字体大小配置,由于每张图片大小不一,这里定一个初始大小,和每次递增值* 其实上面缩放指定后,这里不太需要了,当初没有做缩放的时候,图片大小不一,写入的水印文字大小就得动态变* 所以指定了缩放后,下面的作用只剩处理文字横向居中*/const fontSizeOption = { main: 50, mainIncr: 10, secondary: 17, secondaryIncr: 4 }// 写入时分水印let mainInitSize = fontSizeOption.main// 规定时分信息占据图片宽度大概五分之一let widthPart = Math.ceil(scaleWidth / 4.7)while(true) {watermarkCanvasContext.setFontSize(mainInitSize)// 获取当前指定的文字大小后,此文本的宽度const textWidth = watermarkCanvasContext.measureText(watermarkInfo.mainText).widthif (textWidth >= widthPart) {// 文本宽度超过将近五分之一后,写入水印// 第二个参数是写入x轴,要居中的话就是图片宽度的一半,加上文字宽度的一半// 第三个参数是写入y轴,这边要求是中间靠下,所以就是图片高度的一半,再加一半的一半多一点watermarkCanvasContext.fillText(watermarkInfo.mainText, halfX - Math.ceil(textWidth * 0.5), halfY + Math.ceil(halfY * 0.35))break}mainInitSize += fontSizeOption.mainIncr}// 写入日期 + 人员信息水印let secondaryInitSize = fontSizeOption.secondary// 规定文本占据图片宽度的70%widthPart = Math.ceil(scaleWidth * 0.7)while(true) {watermarkCanvasContext.setFontSize(secondaryInitSize)const textWidth = watermarkCanvasContext.measureText(watermarkInfo.secondaryText).widthif (textWidth >= widthPart) {// 第三个参数是写入y轴,这边要求是在上一个水印的下面,那就是上一个水印写入y轴位置 + 上一个水印的字体大小,避免靠太近,粘一起了watermarkCanvasContext.fillText(watermarkInfo.secondaryText, halfX - Math.ceil(textWidth * 0.5), halfY + Math.ceil(halfY * 0.35) + mainInitSize)break}secondaryInitSize += fontSizeOption.secondaryIncr}// 绘制步骤watermarkCanvasContext.draw(true, () => {setTimeout(() => {uni.canvasToTempFilePath({canvasId: 'watermarkCanvas',quality: 0.1,destWidth: scaleWidth,destHeight: scaleHeight,success: ({ tempFilePath }) => {// 画布转成图片,读取图片信息uni.getFileSystemManager().readFile({filePath: tempFilePath,success: ({ data }) => {const compressImageInfo = { size: data.byteLength, filePath: tempFilePath }// 压缩图片 compressAfterSizeFlag 参数意思是返回压缩后的图片大小,看个人需要,我这边需要再次判断压缩后是否还是超过指定大小this.compressImage(compressImageInfo, { compressAfterSizeFlag: true }).then(cRes => {uni.hideLoading()const imageInfo = Object.assign({ ...currentTempFile },{ path: cRes.compressPath || cRes.filePath, size: cRes.compressSize || cRes.size })resolve(imageInfo)})},fail: _ => {// toast('获取图片大小失败')uni.hideLoading()resolve(Object.assign({ ...currentTempFile }, { path: tempFilePath }))}})},fail: _err => {// toast('生成水印图片失败')uni.hideLoading()resolve(currentTempFile)}}, this)}, 500)})},fail: _ => {// toast('获取图片信息失败')uni.hideLoading()resolve(currentTempFile)}})})
}
其他用到的方法
// 获取到达指定宽度的缩放比率
getScaleRatio (width = 0, targetWidth = 768) {if (width <= targetWidth) {return 1}return (targetWidth / width).toFixed(2)
},// 压缩图片
compressImage (image = {}, options = {}) {return new Promise((resolve, reject) => {const { width = 0 } = image// compressAfterSizeFlag 返回压缩后的大小。scaleFlag 是否缩放图片,scaleTargetWidth 缩放后的指定宽度,高度会等比缩放const { compressAfterSizeFlag = false, scaleFlag = false, scaleTargetWidth = 768 } = options// 超过100k压缩const maxFileSizeLimit = 100 * 1024if (image.size > maxFileSizeLimit) {const fileSize = image.size / 1024// 初始压缩率80let quality = 80if (fileSize > 200 && fileSize <= 500) {// 200 以上,500k以内的图片,压缩70quality = 60} else if (fileSize > 500 && fileSize <= 1024) {// 500 以上,1M以内的图片,压缩50quality = 40} else if (fileSize > 1024 && fileSize <= 2048) {// 1M 以上,2M以内的图片,压缩30quality = 30} else if (fileSize > 2048 && fileSize <= 5012) {// 2M 以上,5M以内的图片,压缩20quality = 20} else if (fileSize > 5012) {// 5M以上的图片,压缩10quality = 10}// 开始压缩const option = {src: image.filePath,quality: quality,success: res => {image.compressPath = res.tempFilePathif (compressAfterSizeFlag) {// 获取压缩后的大小uni.getFileSystemManager().readFile({filePath: res.tempFilePath,success: ({ data }) => {image.compressSize = data.byteLengthresolve(image)},fail: _ => resolve(image)})} else {resolve(image)}},fail: _ => {resolve(image)}}// 缩放图片if (scaleFlag && width > scaleTargetWidth) {option.compressedWidth = scaleTargetWidth}uni.compressImage(option)} else {resolve(image)}})
}
3:调用水印方法
uni.chooseImage({count: 3,sizeType: ['original', 'compressed'],sourceType: ['album', 'camera'],success: async ({ tempFiles = [] }) => {for (const tempFile of tempFiles) {this.addWatermark(tempFile).then(imageInfo => {console.log('水印后的图片', imageInfo)})}}
})
本次没有用到的方法,纯粹做个记录,与上面的画水印无关,画布动态换行写入文本
/*** 画布文本换行绘制* canvasContext 画布实例* text 要写入的文本* x 初始x轴位置* y 初始y轴位置* ySpacing 换行后,每行直接的间隔* maxWidth 此文本写入画布的最大宽度,超过此宽度就换行* color 文本颜色* size 文本字体大小* align 文本方向 left rigt center 额一直搞不清楚这个方向是怎么个原理* @returns { textY 绘制最后一行文本的Y轴结束位置,drawNum 画布本次绘制了几次 }*/
canvasTextNewlinedraw (options) {const { canvasContext, text = '', x = 0, y = 0, ySpacing = 0, maxWidth = 0, color, size, align } = optionsreturn new Promise((resolve, reject) => {size && canvasContext.setFontSize(size)align && canvasContext.setTextAlign(align)color && canvasContext.setFillStyle(color)const textList = text.split('')let currText = '', textY = 0, drawNum = 0for (let i = 0; i < textList.length; i++) {if (canvasContext.measureText(currText + textList[i]).width + x > maxWidth - 10) {textY += textY === 0 ? y : ySpacingcanvasContext.fillText(currText, x, textY)currText = textList[i]drawNum++} else {currText += textList[i]}}textY = textY === 0 ? y : textY + ySpacingcanvasContext.fillText(currText, x, textY)drawNum++canvasContext.draw(true, _ => {setTimeout(() => {resolve({ y: textY, res: _, drawNum })}, 100)})})
}
码字不易,于你有利,勿忘点赞
相关文章:
uniapp微信小程序图片生成水印
整体思路: 用户通过uni.chooseImage选择图片后,获得图片文件的path和size。通过path调用uni.getImageInfo获取图片信息,也就是图片宽高。图片宽高等比缩放至指定大小,不然手机处理起来非常久,因为手机随便拍拍就很大。…...
【MySQL】001.MySQL安装
文章目录 一. MySQL在Ubuntu 20.04 环境安装1.1 更新软件包列表1.2 安装MySQL服务器1.3 配置安全设置1.4 检查mysql server是否正在运行1.5 进行连接1.6 查询自带的数据库 二. 配置文件的修改三. MySQL连接TCP/IP时的登陆问题四. MySQL中的命令 一. MySQL在Ubuntu 20.04 环境安…...
《深度剖析 Linux 权限管理:从基础到进阶,解锁系统安全密钥》
一、权限管理 1.1 普通权限(普通文件和目录) [rootmd ~]# ll total 124 drwxr-xr-x. 2 root root 28 Feb 16 15:48 : drwxr-xr-x. 3 root root 64 Mar 9 00:22 111 -rw-r--r--. 1 root root 43 Feb 17 22:44 1.txt 1 2 …...
2025年4月9日-华为暑期实习-第一题-100分
📌 点击直达笔试专栏 👉《大厂笔试突围》 💻 春秋招笔试突围在线OJ 👉 笔试突围OJ 01. 软件依赖链分析系统 问题描述 LYA 是某软件公司的工程师,负责管理公司的软件依赖关系。每个软件组件都有可能依赖于其他组件,形成一个依赖链。为了确保系统的稳定性,LYA 需要…...
leetcode 377. Combination Sum IV
这道题也是完全背包问题。这道题和第518题几乎一摸一样,所不同的是,第518题要求的是组合数,而第377题要求的是排列数。虽然本题题目描述中说求的是组合数,但从例子1中(1,1,2)和&…...
【TS学习】(22)什么是混入
在 TypeScript 中,混入(Mixins) 是一种设计模式,用于将多个类的功能组合到一个类中。它是一种实现代码复用的方式,尤其适用于需要从多个来源继承功能的场景。TypeScript 不直接支持多继承,但可以通过混入模…...
Firebase Studio,谷歌推出的云端AI 开发环境
Firebase Studio 是谷歌推出的一款基于云的全栈应用开发环境,旨在帮助开发者高效构建和交付集成 AI 功能的高质量应用。该平台结合了 Project IDX 和专用的 Firebase AI 代理,提供从后端到前端、移动应用等多维度的开发支持。 Firebase Studio是什么 F…...
电能质量在线监测分析装置支持实时监测、数据存储及远程传输,适用于电网、工业等场景
电能质量在线监测分析装置主要技术指标 2.1工作电源 交流:220V10% ;50Hz0.5Hz;谐波畸变率不大于15% 直流:220V10%,纹波系数不大于5% 2.2电流信号输入 输入方式:电流互感器输入; …...
线代[13]|线性代数题37道以及数学分析题3道(多图预警)
博主首次发布于CSDN,禁止转载!(CSDN:汉密士2025) 文章目录 一、缘起|《俗说矩阵》课程目录照片存档|线性代数学习脉络|线代习题集封面存档|未来——我与线性代数的纠缠 二…...
gitlab内置pgsql数据库迁移
gitlab内置pgsql数据库迁移 创建gitlab备份方法一,使用pg_dump备份方法二 使用gitlab工具 gitlab-backup 备份 运行sql文件注意事项ERROR: extension "btree_gist" has no installation script nor update path for version "1.7"btree_gist 找…...
IDEA、Webstorm使用账号密码登录Gitlab
在开发过程中,为了保证代码安全,更改了gitlab司库的密码,当更新项目时,发现更新失败了。让填入access_token,gitlab网页设置中虽然generate了token,也填入了它,但是还是报错401unauthorized&…...
水利水电安全员ABC适合哪些人考?
水利水电安全员证是水利工程建设领域的重要职业资格证书,主要涉及水利水电工程施工安全管理、风险防控和应急处理等工作。那么,哪些人适合考取? 哪些人适合考水利水电安全员? 1. 水利水电工程从业人员 ✅ 施工管理人员…...
Service Mesh 深度解析与 Istio+Envoy 实现方案
Service Mesh 深度解析与 IstioEnvoy 实现方案 一、Service Mesh 技术全景 核心架构演进 第一代架构:以库形式集成(如 Netflix OSS)第二代架构:Sidecar 代理模式(如 Linkerd)第三代架构:全功…...
使用uv管理python项目环境
安装uv 使用默认python环境安装uv(把uv安装到默认python环境):pip install uv 创建python项目虚拟环境 如果是已有项目并且项目中有uv.lock文件,直接运行 uv run main.py,这会默认使用uv.lock文件创建虚拟环境如果是新…...
【Code】《代码整洁之道》笔记-Chapter9-单元测试
第9章 单元测试 过去十年以来,编程专业领域进步很大。1997年时,没人听说过测试驱动开发。对于我们之中的大多数人来说,单元测试是那种用来确保程序“可运行”的用过即扔的短代码。我们辛勤地编写类和方法,再弄出一些特殊代码来测…...
数据结构-顺序表
目录 基本概念 什么是数据结构? 数据 结构 线性结构 树形结构 网状结构 第一章绪论 了解概念 几个概念 数据存储方式: 算法的五个重要特性: 算法设计的要求: 总结 线性表 线性表的定义: 顺序表的设计思想 定长顺序表 不定…...
端到端语音识别服务重构方案
以下是重构ASR服务架构,集成Whisper V3Conformer混合模型的端到端实现方案,经过技术增强与流程优化: 端到端语音识别服务重构方案 基于Whisper V3Conformer混合架构 系统架构设计 采用四层微服务架构,支持水平扩展与模块化部署…...
耳根圆通与禅定的交融与分野
引言 在浩瀚的修行体系中,耳根圆通与禅定的关系犹如月映千江——本质同一而显相各异。本文以《楞严经》为经教依据,结合禅宗心法与现代实证视角,系统解析二者在修行原理、实践路径与终极旨归中的深刻关联与微妙差异,揭示这一古老智…...
python基础语法:缩进规则
Python 的缩进规则是其语法的重要组成部分,它通过缩进来表示代码块的层次结构,而不是像其他语言(如 C 或 Java)那样使用大括号 {}。以下是 Python 缩进规则的详细说明: 1. 缩进的基本规则 代码块的标识:Pyt…...
从0到1的Python接口自动化学习路线
Python 是一门非常适合初学者且功能强大的编程语言,它在接口自动化测试领域具有广泛应用。 以下是一份针对 Python 与接口自动化测试的详细学习路线,帮助你从零开始学习并逐步掌握相关知识。 第一阶段:Python基础 目标:掌握 Python 基本语法和编程能力。 一、学习内容 1.…...
大数据(7.3)Kafka量子安全加密实践指南:构建抗量子计算攻击的消息系统
目录 一、量子计算带来的加密革命1.1 量子计算机的威胁时间表1.2 Kafka现有加密机制脆弱性分析 二、后量子加密算法选型2.1 NIST标准化算法矩阵2.2 混合加密最佳实践 三、Kafka量子安全改造方案3.1 Bouncy Castle量子安全Provider3.2 Kafka服务端配置 四、实战案例:…...
【11408学习记录】英语语法精讲:主从复合句之状语从句全解析——以时间状语从句为例
时间 英语语法总结—— 主从复合句状语从句从句位置从句的分类 每日一句词汇第一步:找谓语第二步:断开第三步:简化第一句第二句第三句第四句 英语 语法总结—— 主从复合句 状语从句 状语从句指的是一个句子作状语,表达“描述性…...
深度分页及优化建议
深度分页的定义 深度分页是指在分页查询中,当用户请求非常靠后的页面时,数据库需要处理大量数据,导致查询性能显著下降的情况。例如,一个查询结果有 100 万条记录,而用户要查询第 999 页(每页 10 条记录&a…...
阿里云kafka集成boot在docker启动找不到kafka.client.truststore.jks文件问题
此问题困扰了我好久,看阿里云官方文档,建议配置绝对路径,但项目部署在docker没有绝对路径,开始以为配置在docker的/root下即可,但报找不到文件,后来改相对路径 ./kafka.client.truststore.jks,…/…/还是找…...
kafka 集群搭建,开启sasl认证
Kafka提供了多种认证方式来保护集群的安全性,包括以下几种常见的认证方式: SSL/TLS认证:Kafka支持使用SSL/TLS协议对网络通信进行加密和认证。通过使用SSL/TLS证书对客户端和服务器进行身份验证,可以确保通信的机密性和完整性。SASL/PLAIN认证:SASL/PLAIN是一种基于用户名…...
在 iOS 项目中,Info.plist文件用于配置应用的基本信息和权限
在 iOS 项目中,Info.plist 文件用于配置应用的基本信息和权限。以下是常见的需要添加的权限及其说明: 常见权限及说明 NSCameraUsageDescription 说明: 说明应用为何需要访问相机。示例: “我们需要访问您的相机以便您可以拍摄照片。”NSPhotoLibraryUsageDescription 说明:…...
【完整可用】使用openhtmltopdf生成PDF(带SVG)
文章目录 前言OpenHTMLToPDF 简介maven配置依赖字体文件demo代码其他资源放置截图防止maven编译字体文件 前言 AI和网上都是跑不起来或者版本过低的,还有各种BUG的。本文都是查阅官方文档得出的。如果你能跑起来请给个大大的赞! OpenHTMLToPDF 简介 Ope…...
仿照管理系统布局配置
1.vue仿照snowy 配置,如下图: 2.代码实现 <template><div class"theme-settings"><!-- 导航栏 --><div class"nav-bar"><el-breadcrumb separator"/"><el-breadcrumb-item>导航设置…...
RLAgent note
OpenManus github LlamaGym github GRPO 实践 知乎:Deepseek R1 Zero成功复现 BabyAGI 0,环境 CUDA版本12.X:nvcc -V python 3.10:python -V gcc 11:gcc -V 1,安装llama-cpp-python [git | docs]…...
Python设计模式-工厂模式
一、模式定义与核心思想 工厂模式(Factory Pattern)属于创建型设计模式,其核心思想是通过一个"工厂类"来创建对象,而不是直接调用类的构造函数。这种模式将对象的实例化过程封装起来,使系统在实例化对象时能…...
Vue环境搭建:vue+idea
目录 第一章、Vue环境搭建:安装node2.1)node的下载2.2)配置node的环境变量2.3)常见的npm命令 第二章、使用idea创建vue工程2.1)在IDEA中设置国内镜像2.2)在IDEA中进行脚手架安装2.3)在IDEA中创建…...
庙算兵推:使用Streamlit框架构建了一个智能作战推演系统。
这段代码是一个完整的军事模拟应用,使用Streamlit框架构建了一个智能作战推演系统。该系统包括了三维地图显示、作战单位管理、应急事件处理等功能。用户可以通过界面控制推演的开始和暂停,调整时间加速倍率,并查看实时的战斗情况和系统状态。…...
APIGen-MT:高效生成多轮人机交互Agent数据的两阶段框架
APIGen-MT:高效生成多轮人机交互数据的两阶段框架 引言 随着人工智能技术的飞速发展,AI代理(Agent)已从简单的聊天机器人发展为能够执行复杂现实任务的系统,例如管理金融交易、安排预约和处理客户服务等。然而&#x…...
02-redis-数据结构实现原理
1、redis整体涉及的结构 在redis中整体是KV键值对的方式进行访问的,redis的查询的时间复杂度O(1),底层的数据结构其实跟java中的HashMap底层实现类似,整体采用的是数组链表的实现方式,哈希冲突的时候使用的是链表法解决࿱…...
京华幻梦:科技自然共生诗篇
故事摘要 故事发生在现代中国北京,展现了未来城市的奇幻景象与科技变革。在这个充满想象的未来世界里,科技与自然不再对立,而是达成了和谐共生的美妙平衡。故宫、鸟巢、798艺术区等标志性地点,在科技的赋能下焕发新的生机&#x…...
python:面向对象之包
1.包的定义: 包就是把有联系的模块组织在一起,即放在同一文件夹下,并且在这个文件夹下创建一个__init__.py文件,这个文件就叫做包。 2.包的创建: 创建好好会自动生成一个__init__.py文件。 3.包的调用: …...
spring boot整合redis
spring boot整合redis 步骤: ① 引入redis依赖 <dependency><groupId>org.springframework.boot</group><artifactId>spring-boot-starter-data-redis</artifactId> </dependency>②在application.yml配置文件中,…...
DIA——边缘检测
1.边缘 边缘是像素的突变位置。 2.常见边缘检测算法 通过找到一阶导数的极值点或者二阶导数的过零点来确定边缘像素的位置。边缘检测通常使用算子,即特定的卷积核。通过差分对离散的像素点求导,然后转化成卷积核进行卷积。使用卷积统一涵盖求导&…...
redis 免安装版本 启动方法 windows 安装包
redis 免安装版本 启动方法 windows 安装包 下载解压直接使用 百度网盘连接如下 链接:https://pan.baidu.com/s/1W4ICvdUUxkWPhK93GtdG0Q 提取码:vzw3 下载解压后会用32位和64位两种,根据自己的电脑选择 cmd命令 cd /d D:\yaochengwei\so…...
C语言练习二 进制转换
#include <stdio.h>// 强制类型转换int main(){int i 5;float j i / 2; // 只是把整形先除了 再赋值float k (float)i / 2; //先强制改成float 再赋值printf("%f\n",j);printf("%f\n",k);return 0; } #include <stdio.h> int main(){int…...
AlDente Pro for Mac电脑 充电限制保护工具
AlDente Pro for Mac电脑 充电限制保护工具 一、介绍 AlDente Pro for Mac,是一款充电限制保护工具,是可以限制最大充电百分比来保护电池的工具。锂离子和聚合物电池(如 MacBook 中的电池)在40% 至 80% 之…...
物联网卡(NB-IoT/4G)技术详解
物联网卡(IoT SIM卡)是专为物联网设备设计的流量卡,支持NB-IoT、4G Cat.1等低功耗广域网络(LPWAN),广泛应用于智能烟感、共享设备、车联网等领域。以下是NB-IoT和4G物联网卡的对比与选型指南。 1. NB-IoT v…...
HTML5 Video (视频) 深入解析
一、引言 在当今的互联网时代,视频已经成为网站内容中不可或缺的一部分。从产品介绍、教程演示到娱乐内容,视频以其生动直观的特点吸引着大量用户。HTML5 的出现,为在网页上展示视频提供了一个标准且强大的解决方案,改变了过去依赖插件(如 Flash)来显示视频的局面。 二…...
NO.87十六届蓝桥杯备战|动态规划-完全背包|疯狂的采药|Buying Hay|纪念品(C++)
完全背包 先解决第⼀问 状态表⽰: dp[i][j]表⽰:从前i个物品中挑选,总体积不超过j,所有的选法中,能挑选出来的最⼤价 值。(这⾥是和01背包⼀样哒) 那我们的最终结果就是dp[n][V] 。状态转移⽅…...
Win11企业版安装wsl遇到的坑
起因是windows11上安装了docker desktop,但是启动以后显示Docker Engine stopped,一顿搜索。 可以参考:windows 11系统下打开docker 提示 docker engine stopped - DbWong_0918 - 博客园 我这边主要是检查了第2点,开启windows h…...
C++手撕单链表及逆序打印
在学习数据结构的过程中,链表是一个非常重要的基础数据结构。今天,我们将通过C手动实现一个单链表,并添加一个逆序打印的功能,帮助大家更好地理解链表的实现和操作。 一、链表简介 链表是一种线性数据结构,其中每个元…...
Kubernetes外部etcd集群的快速Docker Compose 部署
一、背景 在高可用 Kubernetes 部署中,需要单独部署外部 etcd 集群,而不是使用 kubeadm 默认在 master 节点上部署的 etcd。以下是关于这一配置场景的详细记录。 二、etcd简介 etcd 是一个高可用的分布式键值存储系统,主要用于存储和管理配…...
docker的目录挂载与卷映射
文章目录 一、目录挂载背景定义使用 二、卷映射背景定义区别使用docker对卷的操作 一、目录挂载 背景 上一文,我们提了docker exec进入容器修改页面很麻烦,所以在这里,我们学习一个新的容器使用方法,叫“目录挂载” 定义 长话…...
十三种物联网/通信模块综合对比——《数据手册--物联网/通信模块》
物联网/通信模块 名称 功能 应用场景 USB转换模块 用于将USB接口转换为其他类型的接口,如串口、并口等,实现不同设备之间的通信。 常用于计算机与外部设备(如打印机、扫描仪等)的连接,以及数据传输和设…...
IntelliJ IDEA 中安装和使用通义灵码 AI 编程助手教程
随着人工智能技术的发展,AI 编程助手逐渐成为提升开发效率的强大工具。通义灵码是阿里云推出的一款 AI 编程助手,它能够帮助开发者实现智能代码补全、代码解释、生成单元测试等功能,极大地提升了编程效率和代码质量。 IntelliJ IDEA 是一款广…...