微信小程序使用canvas制作海报并保存到本地相册(超级详细)

案例图 在这里插入图片描述

分析案例图都有哪些元素 1.渐变背景 2.圆形头像 3.文字 4.文字超出换行 5.图片居中 6.文字居中 7.单位适配 8.弹窗保存图片。因为一个个绘制图形太麻烦所以这里都采用了方法封装。
canvas api介绍 最后有全部代码,复制即用。
data数据

        data() {return {myObj: {headImg: 'https://img.cncentre.cn/bf29eabe47edba2e6ae7249d76759247.png',name: '张三', //微信昵称introduce: '我叫张三今年18岁',introduction: '计算UI设计稿和你手机的屏幕宽度比例(例如UI设计稿是750宽度 你手机是3',bgImg: 'https://img.cncentre.cn/bf29eabe47edba2e6ae7249d76759247.png', //背景图rwmImg: 'https://img.cncentre.cn/bf29eabe47edba2e6ae7249d76759247.png',smText: '二维码介绍' //个性签名},canvasWidth: 375, //画布宽度canvasHeight: 800, //画布高度ratio: 0, //计算UI设计稿和你手机的屏幕宽度比例(例如UI设计稿是750宽度 你手机是350宽度 比例就是2  那么你画布画图时候 所有的尺寸大小、宽高、位置、定位左右上下都需要除以 / 比例2 )widths: '',heights: '',imgs:'' //最后生成的图片}}

1.单位适配

		onLoad() {let that = thisuni.getSystemInfo({success: res => {console.log(res);// res.screenWidth 设备宽度that.canvasWidth = res.screenWidth + 'px'that.widths = res.screenWidththat.ratio = 750 / res.screenWidththat.canvasHeight = (that.widths / 375) * 800 + 'px'that.heights = (that.widths / 375) * 800}})uni.showLoading({title: '海报生成中...'});that.downImgUrl()},

拿到当前设备宽度用来做整个canvas的单位适配。这里根据要求高度是不变的,因为高度适配的话不同设备下最后生成的canvas 图片会被压缩

2.渐变背景

				let _this = this// 生成画布const ctx = uni.createCanvasContext('myCanvas')// 绘制背景const bcg = ctx.createLinearGradient(0, 0, 0, _this.heights)bcg.addColorStop(0.4, '#D9EBE6')bcg.addColorStop(1, '#fff')_this.ctxRectangle(ctx, 0, 0, (_this.widths), (_this.heights), 0, bcg)//画一个矩形也就是整个海报的背景ctxRectangle(ctx, x, y, width, height, r, gnt) {ctx.beginPath() //开始绘制ctx.save() //保存状态ctx.moveTo(x + r, y)ctx.lineTo(x + width - r, y)ctx.arc(x + width - r, y + r, r, Math.PI * 1.5, Math.PI * 2)ctx.lineTo(x + width, y + height - r)ctx.arc(x + width - r, y + height - r, r, 0, Math.PI * 0.5)ctx.lineTo(x + r, y + height)ctx.arc(x + r, y + height - r, r, Math.PI * 0.5, Math.PI)ctx.lineTo(x, y + r)ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5)ctx.fillStyle = gntctx.fill() //对当前路径中的内容进行填充ctx.closePath()},

3.圆形头像

             //绘制头像_this.ctxCircular(ctx, _this.myObj.headImg, (40 / _this.ratio), (100 / _this.ratio), (160 / _this.ratio), (160 / _this.ratio), 80 / _this.ratio, 1)//画一个带圆角矩形//ctx 创建的canvas img填充的图片路径 x轴距离 y轴距离 width宽度 height高度 r圆角大小 shadow是否增加阴影ctxCircular(ctx, img, x, y, width, height, r, shadow) {ctx.beginPath() //开始绘制ctx.save() //保存(canvas)状态ctx.moveTo(x + r, y)ctx.lineTo(x + width - r, y)ctx.arc(x + width - r, y + r, r, Math.PI * 1.5, Math.PI * 2)ctx.lineTo(x + width, y + height - r)ctx.arc(x + width - r, y + height - r, r, 0, Math.PI * 0.5)ctx.lineTo(x + r, y + height)ctx.arc(x + r, y + height - r, r, Math.PI * 0.5, Math.PI)ctx.lineTo(x, y + r)ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5)if (shadow == 1) {ctx.shadowBlur = 20; // 阴影模糊程度ctx.shadowColor = '#fff'; // 阴影颜色}ctx.fill() //对当前路径中的内容进行填充ctx.clip() //从原始画布中剪切任意形状和尺寸ctx.closePath() //关闭一个路径ctx.drawImage(img, x, y, width, height);ctx.restore() //恢复(canvas)状态},	

增加了阴影的效果在这里插入图片描述

4.绘制文字

				//名字_this.ctxText(ctx,'normal bold 18px Arial,PingFang SC','left','#00663A',_this.myObj.name, 220 / _this.ratio, 128 / _this.ratio)//文字方法// textFont 字体样式大小 ctxText(ctx, textFont, textAlign, textFillStyle, textName, x, y) {ctx.beginPath()ctx.save() //保存状态//字体样式大小ctx.font = textFont,//文字对齐方式ctx.textAlign = textAlign//字体颜色ctx.fillStyle = textFillStyle//填充字体  x轴 y轴ctx.fillText(textName, x, y)},

5.文字超出换行

             //介绍_this.ctxTextWrap(ctx, _this.myObj.introduction, 220 / _this.ratio, 170 / _this.ratio, 460 / _this.ratio)//文字超出换行方法ctxTextWrap(ctx, text, x, y, w) {//自动换行介绍var temp = ""var row = []let gxqm = ''if (text) {gxqm = text} else {gxqm = '未设置个性签名'}let gexingqianming = gxqm.split("")for (var a = 0; a < gexingqianming.length; a++) {if (ctx.measureText(temp).width < w) {} else {row.push(temp)temp = ""}temp += gexingqianming[a]}row.push(temp)ctx.font = "13px arail"ctx.textAlign = 'left';ctx.fillStyle = "#000000"for (var b = 0; b < row.length; b++) {ctx.fillText(row[b], x, y + (b + 1) * 20)}},

6.图片居中

这里是中间的背景图比较简单就没有封装方法

	            // 背景图ctx.drawImage(_this.myObj.bgImg, //图像资源(48 / _this.ratio),//图像的左上角在目标canvas上 X 轴的位置(290 / _this.ratio),//图像的左上角在目标canvas上 Y 轴的位置(654 / _this.ratio),//在目标画布上绘制图像的宽度(1064 / _this.ratio)//在目标画布上绘制图像的高度)

7.文字居中

                // 文字居中_this.ctxText(ctx,'13px Arial,PingFang SC','center','#242424',_this.myObj.smText, 375 / _this.ratio, 1562 / _this.ratio)//封装方法 textAlign传入 center就可以ctxText(ctx, textFont, textAlign, textFillStyle, textName, x, y) {ctx.beginPath()ctx.save() //保存状态//字体ctx.font = textFont,//字体样式ctx.textAlign = textAlign//字体颜色ctx.fillStyle = textFillStyle//填充字体ctx.fillText(textName, x, y)},

8.渲染画布,保存图片

8.1 渲染画布

				// 渲染画布ctx.draw(false, (() => {setTimeout(() => {uni.canvasToTempFilePath({canvasId: 'myCanvas',destWidth: _this.canvasWidth * 2, //展示图片尺寸=画布尺寸1*像素比2destHeight: _this.canvasHeight * 2,quality: 1,fileType: 'jpg',success: (res) => {uni.hideLoading()console.log('通过画布绘制出的图片--保存的就是这个图', res.tempFilePath)_this.imgs = res.tempFilePath//点击保存方法 打开弹窗_this.$refs.popup.open()},fail: function(error) {uni.hideLoading()uni.showToast({icon: 'none',position: 'bottom',title: "绘制图片失败", // res.tempFilePath})}}, _this)}, 100)})())

到这里绘图就结束了最后借助 uni.canvasToTempFilePath()把当前画布指定区域的内容导出生成指定大小的图片,并返回文件路径,也就是我们 data定义的imgs

8.2 点击保存图片

			saveImage() {uni.saveImageToPhotosAlbum({filePath: this.imgs,success: function() {uni.showToast({icon: 'none',position: 'bottom',title: "已保存到系统相册",})},fail: function(error) {uni.showModal({title: '提示',content: '若点击不授权,将无法使用保存图片功能',cancelText: '不授权',cancelColor: '#999',confirmText: '授权',confirmColor: '#f94218',success(res) {console.log(res)if (res.confirm) {// 选择弹框内授权uni.openSetting({success(res) {console.log(res.authSetting)}})} else if (res.cancel) {// 选择弹框内 不授权console.log('用户点击不授权')}}})}})},

8.3 长按保存图片

如果要实现这个功能需要用到image带的longtap方法,也就是 长按事件。还需要一个值来隐藏显示image这里用的data里面的 isshow,然后监听imgs是否为空打开弹窗。

	<view class="percard"><canvas v-show='isshow' canvas-id="myCanvas" :style="{ width: canvasWidth, height: canvasHeight }"></canvas><image v-show='!isshow' @longtap="saveImage()" :src="imgs" mode="":style="{ width: canvasWidth, height: canvasHeight }"></image><uni-popup ref="popup" type="center"><view class="pop1"><view class="tit">//点击下面按钮下载到相册请长按下载到相册</view><view class="btns" @click="closer()">知道了</view><view class="btns" @click="goindex()">回到首页</view></view></uni-popup></view>watch: {imgs(newlue) {if (newlue) {this.isshow = falsethis.$refs.popup.open()}}},//关闭弹窗closer() {this.$refs.popup.close()},

全部代码

需要注意点canvas的绘制时不能直接使用网络路径图片,需要使用 uni.getImageInfo 返回图片本地路径再使用。本页面使用了uni-popup组件,自己的项目记得引入。

<template><view class="percard"><canvas v-show='isshow' canvas-id="myCanvas" :style="{ width: canvasWidth, height: canvasHeight }"></canvas><image v-show='!isshow' @longtap="saveImage()" :src="imgs" mode="":style="{ width: canvasWidth, height: canvasHeight }"></image><uni-popup ref="popup" type="center"><view class="pop1"><view class="tit"><!-- 点击下面按钮下载到相册 -->请长按下载图片</view><!-- <view class="btns" @click="saveImage()">点击保存</view> --><view class="btns" @click="closer()">知道了</view><view class="btns" @click="goindex()">回到首页</view></view></uni-popup></view>
</template><script>export default {data() {return {isshow: true,myObj: {headImg: 'https://img.cncentre.cn/bf29eabe47edba2e6ae7249d76759247.png',name: '张三', //微信昵称introduce: '我叫张三今年18岁',introduction: '计算UI设计稿和你手机的屏幕宽度比例(例如UI设计稿是750宽度 你手机是3',bgImg: 'https://img.cncentre.cn/bf29eabe47edba2e6ae7249d76759247.png', //背景图rwmImg: 'https://img.cncentre.cn/bf29eabe47edba2e6ae7249d76759247.png',smText: '二维码介绍' //个性签名},canvasWidth: 375, //画布宽度canvasHeight: 800, //画布高度ratio: 0, //计算UI设计稿和你手机的屏幕宽度比例(例如UI设计稿是750宽度 你手机是350宽度 比例就是2  那么你画布画图时候 所有的尺寸大小、宽高、位置、定位左右上下都需要除以 / 比例2 )widths: '',heights: '',imgs: ''}},watch: {imgs(newlue) {if (newlue) {this.isshow = falsethis.$refs.popup.open()}}},onLoad() {let that = thisuni.getSystemInfo({success: res => {console.log(res);// res.screenWidth 设备宽度that.canvasWidth = res.screenWidth + 'px'that.widths = res.screenWidththat.ratio = 750 / res.screenWidththat.canvasHeight = (that.widths / 375) * 800 + 'px'that.heights = (that.widths / 375) * 800}})uni.showLoading({title: '海报生成中...'});that.downImgUrl()},methods: {downImgUrl() {let that = thisuni.getImageInfo({src: that.myObj.headImg,success: function(res) {that.myObj.headImg = res.pathuni.getImageInfo({src: that.myObj.bgImg,success: function(res) {that.myObj.bgImg = res.pathuni.getImageInfo({src: that.myObj.rwmImg,success: function(res) {that.myObj.rwmImg = res.paththat.drawPageImg()}});}});}});},closer() {this.$refs.popup.close()},goindex() {uni.reLaunch({url: '/pages/index/index'})},saveImage() {uni.saveImageToPhotosAlbum({filePath: this.imgs,success: function() {uni.showToast({icon: 'none',position: 'bottom',title: "已保存到系统相册",})},fail: function(error) {uni.showModal({title: '提示',content: '若点击不授权,将无法使用保存图片功能',cancelText: '不授权',cancelColor: '#999',confirmText: '授权',confirmColor: '#f94218',success(res) {console.log(res)if (res.confirm) {// 选择弹框内授权uni.openSetting({success(res) {console.log(res.authSetting)}})} else if (res.cancel) {// 选择弹框内 不授权console.log('用户点击不授权')}}})}})},//画一个带圆角矩形ctxCircular(ctx, img, x, y, width, height, r, shadow) {ctx.beginPath() //开始绘制ctx.save() //保存(canvas)状态ctx.moveTo(x + r, y)ctx.lineTo(x + width - r, y)ctx.arc(x + width - r, y + r, r, Math.PI * 1.5, Math.PI * 2)ctx.lineTo(x + width, y + height - r)ctx.arc(x + width - r, y + height - r, r, 0, Math.PI * 0.5)ctx.lineTo(x + r, y + height)ctx.arc(x + r, y + height - r, r, Math.PI * 0.5, Math.PI)ctx.lineTo(x, y + r)ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5)if (shadow == 1) {ctx.shadowBlur = 20; // 模糊效果程度的ctx.shadowColor = 'red'; // 阴影颜色}ctx.fill() //对当前路径中的内容进行填充ctx.clip() //从原始画布中剪切任意形状和尺寸ctx.closePath() //关闭一个路径ctx.drawImage(img, x, y, width, height);ctx.restore() //恢复(canvas)状态},//画一个矩形也就是整个海报的背景ctxRectangle(ctx, x, y, width, height, r, gnt) {ctx.beginPath()ctx.save() //保存状态ctx.moveTo(x + r, y)ctx.lineTo(x + width - r, y)ctx.arc(x + width - r, y + r, r, Math.PI * 1.5, Math.PI * 2)ctx.lineTo(x + width, y + height - r)ctx.arc(x + width - r, y + height - r, r, 0, Math.PI * 0.5)ctx.lineTo(x + r, y + height)ctx.arc(x + r, y + height - r, r, Math.PI * 0.5, Math.PI)ctx.lineTo(x, y + r)ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5)ctx.fillStyle = gntctx.fill() //对当前路径中的内容进行填充ctx.closePath() //关闭一个路径},ctxText(ctx, textFont, textAlign, textFillStyle, textName, x, y) {ctx.beginPath()ctx.save() //保存状态//字体ctx.font = textFont,//字体样式ctx.textAlign = textAlign//字体颜色ctx.fillStyle = textFillStyle//填充字体ctx.fillText(textName, x, y)},ctxTextWrap(ctx, text, x, y, w) {//自动换行介绍var temp = ""var row = []let gxqm = ''if (text) {gxqm = text} else {gxqm = '未设置个性签名'}let gexingqianming = gxqm.split("")for (var a = 0; a < gexingqianming.length; a++) {if (ctx.measureText(temp).width < w) {} else {row.push(temp)temp = ""}temp += gexingqianming[a]}row.push(temp)ctx.font = "13px arail"ctx.textAlign = 'left';ctx.fillStyle = "#000000"for (var b = 0; b < row.length; b++) {ctx.fillText(row[b], x, y + (b + 1) * 20)}},// 使用画布绘制页面drawPageImg() {let _this = this// 生成画布const ctx = uni.createCanvasContext('myCanvas')// 绘制背景const bcg = ctx.createLinearGradient(0, 0, 0, _this.heights)bcg.addColorStop(0.4, '#D9EBE6')bcg.addColorStop(1, '#fff')_this.ctxRectangle(ctx, 0, 0, (_this.widths), (_this.heights), 0, bcg)//名字_this.ctxText(ctx,'normal bold 18px Arial,PingFang SC','left','#00663A',_this.myObj.name, 220 / _this.ratio, 128 / _this.ratio)//名称_this.ctxText(ctx,'13px Arial,PingFang SC','left','#242424',_this.myObj.introduce, 220 / _this.ratio, 170 / _this.ratio)//介绍_this.ctxTextWrap(ctx, _this.myObj.introduction, 220 / _this.ratio, 170 / _this.ratio, 460 / _this.ratio)// // 背景图ctx.drawImage(_this.myObj.bgImg, //图像资源(48 / _this.ratio),//图像的左上角在目标canvas上 X 轴的位置(290 / _this.ratio),//图像的左上角在目标canvas上 Y 轴的位置(654 / _this.ratio),//在目标画布上绘制图像的宽度(1064 / _this.ratio)//在目标画布上绘制图像的高度)_this.ctxText(ctx,'13px Arial,PingFang SC','center','#242424',_this.myObj.smText, 375 / _this.ratio, 1562 / _this.ratio)// // 绘制头像_this.ctxCircular(ctx, _this.myObj.headImg, (40 / _this.ratio), (100 / _this.ratio), (160 / _this.ratio), (160 / _this.ratio), 80 / _this.ratio)//矩形二维码_this.ctxCircular(ctx, _this.myObj.rwmImg, (305 / _this.ratio), (1382 / _this.ratio), (140 / _this.ratio),(140 / _this.ratio), 6)// 渲染画布ctx.draw(false, (() => {setTimeout(() => {uni.canvasToTempFilePath({canvasId: 'myCanvas',destWidth: _this.canvasWidth * 2, //展示图片尺寸=画布尺寸1*像素比2destHeight: _this.canvasHeight * 2,quality: 1,fileType: 'jpg',success: (res) => {uni.hideLoading()console.log('通过画布绘制出的图片--保存的就是这个图', res.tempFilePath)_this.imgs = res.tempFilePath// _this.$refs.popup.open()},fail: function(error) {uni.hideLoading()uni.showToast({icon: 'none',position: 'bottom',title: "绘制图片失败", // res.tempFilePath})}}, _this)}, 100)})())},}}
</script>
<style lang="scss">.pop1 {background-color: #fff;width: 520rpx;padding: 68rpx 120rpx;box-sizing: border-box;border-radius: 20rpx;background: linear-gradient(#E6F5EB 45%, #FEFFFE 100%);.tit {font-size: 32rpx;color: #000000;margin: 20px 0px;}.btns {font-size: 32rpx;color: #fff;background-color: #00663A;border-radius: 14rpx;padding: 14rpx 30rpx;margin-top: 40rpx;text-align: center;}}
</style>

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

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

相关文章

【Linux--信号】

目录 一、信号的概念1.1查看系统的信号1.2信号的处理方式 二、信号的产生方式2.1通过终端按键2.2kill命令2.3系统调用2.4软条件产生信号2.5硬件异常产生信号 三、信号的保存3.1概念的认识3.2sigset_t3.3信号集操作函数3.4sigprocmask && sigpending3.4.1sigprocmask3.4…

【工具使用-A2B】使用A2B配置16通道车载音频系统

一&#xff0c;简介 工作中需要使用A2B搭建车载16通道演示系统&#xff0c;故本文记录一下&#xff0c;16通道车载音频系统中A2B工程相关配置&#xff0c;供参考。 使用FPGA输出双TDM8的信号给到A2B Master节点&#xff0c;音频数据经过A2B双绞线&#xff0c;传输到A2B Slave…

【开源】基于JAVA语言的企业项目合同信息系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 合同审批模块2.3 合同签订模块2.4 合同预警模块2.5 数据可视化模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 合同审批表3.2.2 合同签订表3.2.3 合同预警表 四、系统展示五、核心代码5.1 查询合同…

大师计划1.0 - log2 CRTO笔记

CRTOⅠ笔记 log2 这个笔记是我在2023年11月23日-12月22日中&#xff0c;学习CRTO所做的一些笔记。 事实上TryHackMe的路径和htb学院包含了许多CRTO的知识并且甚至还超出了CRTO&#xff08;CS除外&#xff09;&#xff0c;所以很多东西在THM和htb学院学过&#xff0c;这次CRTO等…

【NI-RIO入门】如何格式化实时控制器

1.当使用CompactRIO时有时会出现硬盘已满或出现IO错误&#xff0c;如下如图 2.出现上下位机软件版本不匹配 3.rt组件损坏 4.实时控制器意外进入安全模式 5.设备非正常断电 6.访问被拒绝&#xff1a;目标被另一个进程&#xff08;例如 VI 或 NI 分布式系统管理器&#xff09;锁定…

中间继电器的文字符号和图形符号

中间继电器的文字符号和图形符号 中间继电器主要用途是当其他继电器触头数量或容量不够时&#xff0c;可借助中间继电器扩充触头数目或增大触头容量&#xff0c;起中间转换作用。将多个中间继电器相组合&#xff0c;还能构成各种逻辑运算电器或计数电器。 中间继电器文字符号…

Kafka、RocketMQ、RabbitMQ消息丢失可能存在的地方,以及解决方案

这里主要对比&#xff1a;Kafka、RocketMQ、RabbitMQ 介绍一下消息生产、存储、消费三者的架构形式。 消息丢失可能存在的场景&#xff1a; 情况一&#xff1a; 生产者发送给MQ的过程消息丢失 在写消息的过程中因为网络的原因&#xff0c;还没到mq消息就丢失了&#xff1b;或…

【AI故事】灵感的源泉还是知识的盗窃?

灵感的源泉还是知识的盗窃&#xff1f; ——ChatGPT Robot在一个漆黑的夜晚&#xff0c;年轻的作家艾米丽坐在书桌前&#xff0c;手里紧握着一支笔&#xff0c;思绪万千。她一直在寻找创作的灵感&#xff0c;但却毫无头绪。 突然&#xff0c;她听到了一声巨响&#xff0c;仿佛…

C# 初识System.IO.Pipelines

写在前面 在进一步了解Socket粘包分包的过程中&#xff0c;了解到了.NET 中的 System.IO.Pipelines&#xff0c;可以更优雅高效的解决这个问题&#xff1b;先跟随官方的示例做个初步的认识。 System.IO.Pipelines 是一个库&#xff0c;旨在使在 .NET 中执行高性能 I/O 更加容…

DeskPins | 将窗口钉在面前

前言 DeskPins | 将窗口钉在面前 有的人&#xff0c;一边看番&#xff0c;一边却在刷题&#xff1b; 有的人&#xff0c;一边网课&#xff0c;一边却在摸鱼。 有的人&#xff0c;一边某xuexi通上考试&#xff0c;一边。。 众所周知&#xff0c;窗口置顶是很常见的一个需求&…

智慧零售技术探秘:关键技术与开源资源,助力智能化零售革新

智慧零售是一种基于先进技术的零售业态&#xff0c;通过整合物联网、大数据分析、人工智能等技术&#xff0c;实现零售过程的智能化管理并提升消费者体验。 实现智慧零售的关键技术包括商品的自动识别与分类、商品的自动结算等等。 为了实现商品的自动识别与分类&#xff0c;…

vue3+ts 代理的使用

简单封装request.ts import axios from "axios";// 1.创建axios对象 const serviceaxios.create();// 2.请求拦截器 service.interceptors.request.use(config>{return config; },error>{Promise.reject(error); })// 3.响应拦截器 service.interceptors…

走进数字金融峰会,为金融科技数字化赋能

12月20—21日&#xff0c;FSIDigital数字金融峰会在上海圆满召开。本次峰会包含InsurDigital数字保险峰会和B&SDigital数字银行与证券峰会2场平行峰会&#xff1b;吸引了近600位来自保险、银行、证券以及金融科技等行业的领导者和专家齐聚一堂&#xff0c;共同探讨金融业数…

docker 私有仓库

Docker 私有仓库 一、私有仓库搭建 # 1、拉取私有仓库镜像 docker pull registry # 2、启动私有仓库容器 docker run -id --nameregistry -p 5000:5000 registry # 3、打开浏览器 输入地址http://私有仓库服务器ip:5000/v2/_catalog&#xff0c;看到{"repositories&quo…

瑞熙贝通助力实验室原始记录无纸化管理

一、系统概述 随着互联网时代的发展&#xff0c;实验室管理信息化功能日趋完善&#xff0c;涉及维度也不断扩大&#xff0c;实现实验室原始记录的电子化和数字化&#xff0c;提高实验室工作质量和效率&#xff0c;是实验室发展大势所趋。在实验室信息管理系统得到日益广泛应用…

云计算:现代技术的基本要素

众所周知&#xff0c;在儿童教育的早期阶段&#xff0c;幼儿园都会传授塑造未来行为的一些基本准则。 今天&#xff0c;我们可以以类似的方式思考云计算&#xff1a;它已成为现代技术架构中的基本元素。云现在在数字交互、安全和基础设施开发中发挥着关键作用。云不仅仅是另一…

nodejs+vue+微信小程序+python+PHP的热带野生动物园景点预约订票系统的设计与实现-计算机毕业设计推荐

管理员是系统的管理者&#xff0c;拥有系统的所有权限&#xff0c;通过系统设定的账号和密码登录后对系统进行管理&#xff0c;包括密码修改、用户管理。新闻公告的管理、景点管理、订单管理。管理员登录中&#xff0c;通过用户的登录名和密码到热带野生动物园景点预约订票系统…

【数据结构】LRU缓存的简单模拟实现(leetcode力扣146LRU缓存)

文章目录 一、定义二、LRU模拟实现二、代码实现 一、定义 LRU是Least Recently Used的缩写&#xff0c;意思是最近最少使用&#xff0c;它是一种Cache替换算法。 Cache的容量有限&#xff0c;因此当Cache的容量用完后&#xff0c;而又有新的内容需要添加进来时&#xff0c; 就…

几种串口扩展电路

一、IIC串口扩展电路 LCT200 是一款可以通过 I2C 接口通讯&#xff0c;拓展 2 路独立串口的通讯芯片&#xff0c;同时也支持通过 2 路串口读写 I2C 接口的数据。LCT200 的封装为 TSSOP-20。 主要功能&#xff1a;⚫ 通过对 I2C 接口读写实现拓展 2 路独立串口功能 ⚫ 通过读写…

【Python3】\u字符与中文字串互转

小水。 encode和decode&#xff1a; str没有decode函数&#xff0c;但对应的有encode函数&#xff0c;该函数作用是转码为bytes对象bytes通过decode函数转换回对应的str对于一些偏激的(可以用过分来形容)的字符串&#xff0c;例如一二三\\u56db\\u4e94\\u516d&#xff0c;是有…