小程序canvas2d实现横版全屏和竖版逐字的签名组件(字帖式米字格签名组件)

文章标题

  • 01 功能说明
  • 02 效果预览
    • 2.1 横版
    • 2.2 竖版
  • 03 使用方式
  • 04 横向签名组件源码
    • 4.1 html 代码
    • 4.2 业务 Js
    • 4.3 样式 Css
  • 05 竖向签名组件源码
    • 5.1 布局 Html
    • 5.2 业务 Js
    • 5.3 样式 Css

01 功能说明

技术栈:uniapp、vue、canvas 2d

需求

  • 实现横版的全名字帖式米字格签名组件,竖版逐字的字帖式米字格签名组件;
  • 支持配置文字描述、画笔颜色、画笔大小等;
  • 提供 submit 事件,当点击提交按钮时触发,回调参数是canvas转化为图片的地址;

02 效果预览

2.1 横版

横版截图
在这里插入图片描述

2.2 竖版

竖版截图
在这里插入图片描述

03 使用方式

// 使用横向签名------------------------
<template><HorizontalSign signText="赵钱孙" @submit="handleSubmit" /> 
</template><script>
import HorizontalSign from '@/components/HorizontalSign.vue';export default {components: { HorizontalSign },methods: {handleSubmit(imagePath) {console.log('--image--', imagePath);},},
} 
<script> // 使用竖向签名------------------------
<template><VerticalSign signText="赵钱孙"  @submit="handleSubmit" />
</template><script>
import VerticalSign from '@/components/VerticalSign.vue';export default {components: { VerticalSign },methods: {handleSubmit(imagePath) {console.log('--image--', imagePath);},},
}  
<script> 

04 横向签名组件源码

4.1 html 代码

<template><view class="wrapping"><!-- header 定位后以左上角顺时针旋转 90° --><view class="header-title flex col-center"><!-- <text> 签名:</text> --><!-- 预览图片(图片本身是正向的,但由于父元素旋转了90°所以正好能横向观看) --><!-- <image :src="previewImage" mode="aspectFit" class="small-preview" /> --><text class="desc-text">{{ description }}</text></view><!-- 实际保持直立正向 canvas 容器 --><view class="canvas-wrapper"><!-- 只展示限制数量文字的米字格,超过配置数量文字则不展示 --><view class="char-group flex-col flex-center" v-if="signText && signText.length <= riceGridLimit"><view class="char-box" v-for="(item, index) in signText" :key="index">{{ item }}</view></view><canvasid="signatureCanvas"type="2d"class="signature-canvas"@touchstart="handleTouchStart"@touchmove="handleTouchMove"@touchend="handleTouchEnd"@touchcancel="handleTouchEnd"disable-scroll></canvas></view><!-- footer 定位后以右下角顺时针旋转 90° --><view class="footer-btn flex"><view class="action-btn" @click="resetCanvas">重签</view><view class="action-btn submit-btn" @click="handleSubmit">{{ submitText }}</view></view><!--用于绘制并生成旋转为正向签名图片的 canvas 容器--><canvas id="previewCanvas" type="2d" class="preview-canvas"></canvas></view>
</template>

4.2 业务 Js

<script>
export default {props: {description: {type: String,default: '请使用正楷字体,逐字签写', //  文字描述},submitText: {type: String,default: '提交', // 提交按钮文字},dotSize: {type: Number,default: 4, // 签名笔大小},penColor: {type: String,default: '#000000', // 签名笔颜色},signText: {type: String,default: '', // 签名文字},riceGridLimit: {type: Number,default: 3, // 米字格展示字数最大限制},},data() {return {mainCtx: null,mainCanvas: null,isDrawing: false,touchPoints: [],signIsMove: false,previewImage: '',canvasRatio: 1,};},mounted() {this.canvasRatio = uni.getWindowInfo().pixelRatio ?? 1;this.initCanvas();},methods: {initCanvas() {const domItem = uni.createSelectorQuery().in(this).select('#signatureCanvas');domItem.fields({ node: true, size: true }).exec((res) => {// Canvas 对象this.mainCanvas = res[0]?.node;// 渲染上下文this.mainCtx = this.mainCanvas.getContext('2d');// Canvas 画布的实际绘制宽高const width = res[0].width;const height = res[0].height;// 初始化画布大小this.mainCanvas.width = width * this.canvasRatio;this.mainCanvas.height = height * this.canvasRatio;this.mainCtx.scale(this.canvasRatio, this.canvasRatio);this.setPen();});},setPen() {this.mainCtx.strokeStyle = this.penColor;this.mainCtx.lineWidth = this.dotSize;this.mainCtx.lineCap = 'round';this.mainCtx.lineJoin = 'round';},handleTouchStart(e) {const point = {x: e.changedTouches[0].x,y: e.changedTouches[0].y,};this.touchPoints.push(point);this.isDrawing = true;},handleTouchMove(e) {if (!this.isDrawing) return;const point = {x: e.touches[0].x,y: e.touches[0].y,};this.touchPoints.push(point);const len = this.touchPoints.length;if (len >= 2) {const prevPoint = this.touchPoints[len - 2];const currentPoint = this.touchPoints[len - 1];this.mainCtx.beginPath();this.mainCtx.moveTo(prevPoint.x, prevPoint.y);this.mainCtx.lineTo(currentPoint.x, currentPoint.y);this.mainCtx.stroke();this.signIsMove = true;}},handleTouchEnd() {this.isDrawing = false;this.touchPoints = [];},resetCanvas() {if (!this.signIsMove) {return;}this.mainCtx.clearRect(0, 0, 1000, 1000);this.setPen();this.touchPoints = [];this.previewImage = '';this.signIsMove = false;},async handleSubmit() {if (!this.signIsMove) {uni.showToast({ title: '请先完成签名', icon: 'none' });return;}try {const _this = this;uni.canvasToTempFilePath({canvas: this.mainCanvas,quality: 1,fileType: 'png',success: (res) => {let path = res.tempFilePath;_this.handlePreviewImage(path);},fail: (res) => {uni.showToast({ title: '提交失败,请重新尝试', icon: 'none' });},});} catch (err) {uni.showToast({ title: '签名失败,请重试', icon: 'none' });} finally {uni.hideLoading();}},handlePreviewImage(imagePath) {const _this = this;const previewDom = uni.createSelectorQuery().in(_this).select('#previewCanvas');previewDom.fields({ node: true, size: true }).exec((res) => {// Canvas 对象const canvas = res[0]?.node;// 渲染上下文const previewCtx = canvas.getContext('2d');const image = canvas.createImage();image.src = imagePath;image.onload = () => {let { width, height } = image;// 获取图片的宽高初始画布,canvas交换宽高canvas.width = height;canvas.height = width;// 设置白色背景previewCtx.fillStyle = '#FFFFFF';previewCtx.fillRect(0, 0, height, width);// 图片逆时针旋转90度,且换为弧度previewCtx.rotate((-90 * Math.PI) / 180);// 旋转后调整绘制的位置下移一个宽度的距离previewCtx.drawImage(image, -width, 0);};// 最终导出setTimeout(() => {uni.canvasToTempFilePath({canvas,fileType: 'png', // 指定文件类型quality: 1, // 最高质量success: (res) => {_this.previewImage = res.tempFilePath;uni.previewImage({ urls: [res.tempFilePath], current: 0 });_this.$emit('submit', res.tempFilePath);},fail: (err) => {uni.showToast({ title: '合成失败,请重试', icon: 'none' });},},_this);}, 300); // 增加最终导出前的延迟});},},
};
</script>

4.3 样式 Css

<style scoped>
.wrapping {position: relative;padding: 20rpx;margin: 20rpx;background-color: #fff;box-sizing: border-box;
}.header-title {position: absolute;right: 20rpx;top: 20rpx;height: 50rpx;z-index: 1000;transform-origin: top left;transform: translateX(100%) rotate(90deg);font-size: 32rpx;color: #333;
}.desc-text {color: #969799;
}.small-preview {width: 100rpx;height: 50rpx;border-bottom: 1px solid #333;
}.canvas-wrapper {position: relative;margin: auto;width: 60%;height: 80vh;background: #f7f8fa;
}.char-group {position: absolute;top: 0px;left: 0px;width: 100%;height: 100%;pointer-events: none;user-select: none;z-index: 1;gap: 20rpx;
}.char-box {padding: 36rpx;width: 30vw;height: 30vw;transform: rotate(90deg);font-size: 30vw;line-height: 30vw;text-align: center;color: #eeeeee;/* 使用虚线边框框住字体 *//* border: 1px dashed #ccc; *//* 使用米字格照片当背景图 */background: url('https://img1.baidu.com/it/u=2622499137,3527900847&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500') no-repeat;background-size: 100%;text-shadow: 1px 1px black, -1px -1px black, 1px -1px black, -1px 1px black;
}.signature-canvas {position: relative;width: 100%;height: 100%;z-index: 2;
}.footer-btn {position: absolute;left: 20rpx;bottom: 20rpx;transform-origin: bottom right;transform: translateX(-100%) rotate(90deg);z-index: 1000;gap: 32rpx;
}.action-btn {text-align: center;width: 200rpx;height: 96rpx;border-radius: 100rpx;font-size: 32rpx;line-height: 96rpx;color: #3874f6;border: 2rpx solid #3874f6;background: #fff;
}.submit-btn {color: #fff;border: 2rpx solid #3874f6;background: #3874f6;
}.preview-canvas {visibility: hidden;position: fixed;/* 将画布移出展示区域 */top: 100vh;left: 100vw;opacity: 0;z-index: 0;
}
</style>

05 竖向签名组件源码

5.1 布局 Html

<template><view class="signature-container"><view class="desc-text">{{ description }}</view><view class="signature-area"><view class="canvas-wrapper"><!-- 逐字展示文字 --><view class="char-box" v-if="signText && currentCharIndex < signText.length">{{ signText[currentCharIndex] }}</view><canvasid="signatureCanvas"class="signature-canvas"type="2d"@touchstart="handleTouchStart"@touchmove="handleTouchMove"@touchend="handleTouchEnd"@touchcancel="handleTouchEnd"disable-scroll></canvas></view><view class="action-box"><view class="action-btn" v-if="currentCharIndex > 0" @click="prevChar">上一字</view><view class="action-btn" @click="resetCanvas">清空画板</view><view class="action-btn" v-if="currentCharIndex < signText.length" @click="nextChar">{{ currentCharIndex < signText.length - 1 ? '下一字' : '确认' }}</view></view></view><view class="preview-title">逐字预览</view><view class="preview-content"><image v-for="(img, index) in previewImages" :key="index" :src="img" mode="aspectFit" class="preview-char" /></view><view class="action-box"><view class="action-btn submit-btn" @click="resetAllRecord">全部重签</view><view class="action-btn submit-btn" @click="handleSubmit">{{ submitText }}</view></view><!--用于拼接合并为完整签名图片的 canvas 容器--><canvas id="previewCanvas" type="2d" class="preview-canvas"></canvas></view>
</template>

5.2 业务 Js

<script>
export default {props: {description: {type: String,default: '请使用正楷字体,逐字签写', // 文字描述},submitText: {type: String,default: '提交', // 提交按钮文字},dotSize: {type: Number,default: 4, // 签名笔大小},penColor: {type: String,default: '#000000', // 签名笔颜色},signText: {type: String,default: '', // 签名文字},},data() {return {mainCtx: null,mainCanvas: null,isDrawing: false,touchPoints: [],allTouchPoints: [],signIsMove: false,currentCharIndex: 0,canvasRatio: 1,previewImages: [],};},mounted() {this.canvasRatio = uni.getWindowInfo().pixelRatio ?? 1;this.initCanvas();},methods: {initCanvas() {const domItem = uni.createSelectorQuery().in(this).select('#signatureCanvas');domItem.fields({ node: true, size: true }).exec((res) => {// Canvas 对象this.mainCanvas = res[0]?.node;// 渲染上下文this.mainCtx = this.mainCanvas.getContext('2d');// Canvas 画布的实际绘制宽高const width = res[0].width;const height = res[0].height;// 初始化画布大小this.mainCanvas.width = width * this.canvasRatio;this.mainCanvas.height = height * this.canvasRatio;this.mainCtx.scale(this.canvasRatio, this.canvasRatio);this.setPen();});},setPen() {this.mainCtx.strokeStyle = this.penColor;this.mainCtx.lineWidth = this.dotSize;this.mainCtx.lineCap = 'round';this.mainCtx.lineJoin = 'round';},handleTouchStart(e) {const point = {x: e.changedTouches[0].x,y: e.changedTouches[0].y,};this.touchPoints.push(point);this.allTouchPoints.push(point);this.isDrawing = true;},handleTouchMove(e) {if (!this.isDrawing) return;const point = {x: e.touches[0].x,y: e.touches[0].y,};this.touchPoints.push(point);this.allTouchPoints.push(point);const len = this.touchPoints.length;if (len >= 2) {const prevPoint = this.touchPoints[len - 2];const currentPoint = this.touchPoints[len - 1];this.mainCtx.beginPath();this.mainCtx.moveTo(prevPoint.x, prevPoint.y);this.mainCtx.lineTo(currentPoint.x, currentPoint.y);this.mainCtx.stroke();this.signIsMove = true;}},handleTouchEnd() {this.isDrawing = false;this.touchPoints = [];},getRectangle(points) {// 计算每个字符的实际大小let minX = Number.POSITIVE_INFINITY;let minY = Number.POSITIVE_INFINITY;let maxX = Number.NEGATIVE_INFINITY;let maxY = Number.NEGATIVE_INFINITY;for (let point of points) {minX = Math.min(minX, point.x);minY = Math.min(minY, point.y);maxX = Math.max(maxX, point.x);maxY = Math.max(maxY, point.y);}return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };},prevChar() {if (this.previewImages.length > 0) {this.previewImages.pop();this.currentCharIndex--;this.resetCanvas();}},nextChar() {if (!this.signIsMove) {uni.showToast({ title: '请先完成签名', icon: 'none' });return;}try {const { x, y, width, height } = this.getRectangle(this.allTouchPoints);const offset = 10;const _this = this;uni.canvasToTempFilePath({canvas: this.mainCanvas,x: x - offset,y: y - offset,width: width + offset * 2,height: height + offset * 2,success: (res) => {_this.previewImages.push(res.tempFilePath);_this.currentCharIndex++;_this.resetCanvas();},fail: () => {uni.showToast({ title: '提交失败,请重新尝试', icon: 'none' });},},_this);} catch (err) {uni.showToast({ title: '保存失败,请重试', icon: 'none' });}},resetCanvas() {this.mainCtx.clearRect(0, 0, 1000, 1000);this.setPen();this.touchPoints = [];this.allTouchPoints = [];this.signIsMove = false;},resetAllRecord() {this.previewImages = [];this.currentCharIndex = 0;this.resetCanvas();},async handleSubmit() {if (this.previewImages.length <= 0) {uni.showToast({ title: '请至少签写一个字', icon: 'none' });return;}try {this.handlePreviewImage();} catch (err) {uni.showToast({ title: '合成失败,请重试', icon: 'none' });}},handlePreviewImage() {const _this = this;const previewDom = uni.createSelectorQuery().in(_this).select('#previewCanvas');previewDom.fields({ node: true, size: true }).exec((res) => {// Canvas 对象const canvas = res[0]?.node;// 渲染上下文const previewCtx = canvas.getContext('2d');// 计算总宽度和单个字的尺寸const charWidth = 300 / this.previewImages.length;const charHeight = 300 / this.previewImages.length;const totalWidth = charWidth * this.previewImages.length;// 设置白色背景previewCtx.fillStyle = '#FFFFFF';previewCtx.fillRect(0, 0, totalWidth, charHeight);// 按顺序绘制每个图片for (let i = 0; i < this.previewImages.length; i++) {const image = canvas.createImage();image.src = this.previewImages[i];image.onload = () => {const x = i * charWidth;// 绘制当前图片previewCtx.drawImage(image, x, 0, charWidth, charHeight);};}// 最终导出setTimeout(() => {uni.canvasToTempFilePath({canvas,x: 0,y: 0,width: totalWidth,height: charHeight,fileType: 'png', // 指定文件类型quality: 1, // 最高质量success: (res) => {uni.previewImage({ urls: [res.tempFilePath], current: 0 });_this.$emit('submit', res.tempFilePath);},fail: (err) => {uni.showToast({ title: '合成失败,请重试', icon: 'none' });},},_this);}, 300); // 增加最终导出前的延迟});},},
};
</script>

5.3 样式 Css

<style scoped>
.signature-container {padding: 0 20rpx 40rpx 20rpx;background-color: #f5f5f5;box-sizing: border-box;
}.signature-area {padding: 50rpx;background-color: #fff;box-sizing: border-box;
}.desc-text {padding: 20rpx 0;font-size: 32rpx;color: #333;text-align: center;box-sizing: border-box;
}.canvas-wrapper {position: relative;width: 100%;/* 保持宽高比 */aspect-ratio: 1;/* height: 600rpx; */background: #fff;/* 使用虚线边框框住字体 *//* border: 1px dashed #ccc; *//* 使用米字格照片当背景图 */background: url('https://img1.baidu.com/it/u=2622499137,3527900847&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=500') no-repeat;background-size: 100%;
}.char-box {position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);font-size: 400rpx;text-shadow: 1px 1px black, -1px -1px black, 1px -1px black, -1px 1px black;color: #eeeeee;pointer-events: none;user-select: none;z-index: 1;
}.signature-canvas {position: relative;width: 100%;height: 100%;z-index: 2;
}.action-box {display: flex;margin-top: 32rpx;gap: 20rpx;
}.action-btn {flex: 1;text-align: center;padding: 16rpx 30rpx;font-size: 28rpx;color: #3874f6;border: 2rpx solid #3874f6;border-radius: 80rpx;box-sizing: border-box;
}.submit-btn {background: #3874f6;color: #fff;
}.preview-title {margin-top: 32rpx;width: 100%;text-align: center;font-size: 28rpx;color: #666;
}.preview-content {display: flex;flex-wrap: wrap;margin-top: 20rpx;background-color: #fff;padding: 20rpx 20rpx 0 20rpx;min-height: 190rpx;box-sizing: border-box;
}.preview-char {width: 150rpx;height: 150rpx;margin-right: 19rpx;margin-bottom: 20rpx;
}.preview-canvas {position: fixed;left: -2000px;width: 300px;height: 300px;
}
</style>

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

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

相关文章

stm32 lwip tcp服务端频繁接收连接失效问题解决(tcp_recved)

一、问题描述 最近用stmf429单片机作为TCP服务端遇到一个问题&#xff0c;就是客户端特别频繁的发送消息&#xff0c;过一段时间以后&#xff0c;客户端的请求不再被客户端接收到&#xff0c;而且服务器端监控的掉线回调函数也不会被调用&#xff0c;好像这个连接就凭空的消失…

让 DeepSeek R1 锐评一下自己

让 DeepSeek R1 锐评一下自己 1. 技术领域覆盖广泛&#xff0c;内容实用性突出2. 内容系统性强&#xff0c;适合阶段性学习3. 持续更新与技术敏锐度4. 潜在改进方向总结 突发奇想&#xff0c;让 AI 锐评一下自己~ Gorit 是一名活跃于技术领域的 CSDN 博主&#xff0c;其内容主…

19.4.9 数据库方式操作Excel

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 本节所说的操作Excel操作是讲如何把Excel作为数据库来操作。 通过COM来操作Excel操作&#xff0c;请参看第21.2节 在第19.3.4节【…

Android原生的HighCPU使用率查杀机制

摘要 原生的HighCPU使用率查杀机制是基于读取/proc/pid/stat中的utime stime后&#xff0c;根据CPU使用率 (utime stime / totalTime)*100%进行实现&#xff0c;当检测后台进程的CPU使用率超过阈值时&#xff0c;执行查杀和统计到电池数据中。 细节点&#xff1a; 1. 原生根…

Linux学习笔记之进程

进程 进程的定义 进程是计算机中的程序关于某数据集合上的一次运行活动&#xff0c;是系统进行资源分配的基本单位&#xff0c;也是操作系统结构的基础。   例如当QQ程序运行的时候&#xff0c;计算机会先从磁盘读取QQ程序到内存&#xff0c;然后OS管理这个程序&#xff0c;…

深入理解 MyBatis 框架的核心对象:SqlSession

Mybatis框架中的SqlSession对象详解 引言 MyBatis 是一个优秀的持久层框架&#xff0c;它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集的工作。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息&#xff0…

Tcp_socket

Tcp不保证报文完整性&#xff08;面向字节流&#xff09; 所以我们需要在应用层指定协议&#xff0c;确保报文完整性 // {json} -> len\r\n{json}\r\n bool Encode(std::string &message) {if(message.size() 0) return false;std::string package std::to_string(m…

【运维心得】Centos7安装Redis7.4.2并处理相关告警

概述 单机版的redis安装比较简单&#xff0c;这里重点记录下告警的处理。 安装步骤 1. 确认版本 可以通过官方仓库或者知名的网站获取最新安装包&#xff0c;截止20250213&#xff0c;未找到官方安装包。 rpmfind: RPM resource redis(x86-64)https://rpmfind.net/linux/rpm2h…

社区版IDEA中配置TomCat(详细版)

文章目录 1、下载Smart TomCat2、配置TomCat3、运行代码 1、下载Smart TomCat 由于小编的是社区版&#xff0c;没有自带的tomcat server&#xff0c;所以在设置的插件里面搜索&#xff0c;安装第一个&#xff08;注意&#xff1a;安装时一定要关闭外网&#xff0c;小编因为这个…

K8s之存储卷

一、容忍、crodon和drain 1.容忍 即使节点上有污点&#xff0c;依然可以部署pod。 字段&#xff1a;tolerations 实例 当node01上有标签test11&#xff0c;污点类型为NoSchedule&#xff0c;而node02没有标签和污点&#xff0c;此时pod可以在node01 node02上都部署&#xff0c…

【MySQL — 数据库基础】深入解析 MySQL 的联合查询

1. 插入查询结果 语法 insert into table_name1 select* from table_name2 where restrictions ;注意&#xff1a;查询的结果集合&#xff0c;列数 / 类型 / 顺序 要和 insert into 后面的表相匹配&#xff1b;列的名字不要求相同&#xff1b; create table student1(id int , …

spring cloud 使用 webSocket

1.引入依赖,(在微服务模块中) <!-- Spring WebSocket --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency> 2.新建文件 package com.ruoyi.founda…

《aarch64汇编从入门到精通》-204页PPT+实验

&#x1f534;【课程特色】 ✅1、依照官方文档总结制作&#xff0c;体系更完整&#xff0c;不遗漏知识&#xff1b; ✅2、基于Armv8/Armv9架构讲解汇编。真正的ARM汇编&#xff1b; ✅3、资料更全。200多页PPT资料&#xff0c;其它参考资料; ✅4、学完ARM架构&#xff0c;再学汇…

企业使用统一终端管理(UEM)工具提高端点安全性

什么是统一终端管理(UEM) 统一终端管理(UEM)是一种从单个控制台管理和保护企业中所有端点的方法&#xff0c;包括智能手机、平板电脑、笔记本电脑、台式机和 IoT设备。UEM 解决方案为 IT 管理员提供了一个集中式平台&#xff0c;用于跨所有作系统和设备类型部署、配置、管理和…

20250213 隨筆 雪花算法

雪花算法&#xff08;Snowflake Algorithm&#xff09; 雪花算法&#xff08;Snowflake&#xff09; 是 Twitter 在 2010 年開發的一種 分布式唯一 ID 生成算法&#xff0c;它可以在 高併發場景下快速生成全局唯一的 64-bit 長整型 ID&#xff0c;且不依賴資料庫&#xff0c;具…

QT 异步编程之多线程

一、概述 1、在进行桌面应用程序开发的时候&#xff0c;假设应用程序在某些情况下需要处理比较复制的逻辑&#xff0c;如果只有一个线程去处理&#xff0c;就会导致窗口卡顿&#xff0c;无法处理用户的相关操作。这种情况下就需要使用多线程&#xff0c;其中一个线程处理窗口事…

leetcode 543. 二叉树的直径

题目如下 数据范围 示例 显然直径等于左右子树高之和的最大值。通过代码 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* Tr…

IP 路由基础 | 路由条目生成 / 路由表内信息获取

注&#xff1a;本文为 “IP 路由” 相关文章合辑。 未整理去重。 IP 路由基础 秦同学学学已于 2022-04-09 18:44:20 修改 一. IP 路由产生背景 我们都知道 IP 地址可以标识网络中的一个节点&#xff0c;并且每个 IP 地址都有自己的网段&#xff0c;各个网段并不相同&#xf…

sql:时间盲注和boolen盲注

关于时间盲注&#xff0c;boolen盲注的后面几个获取表、列、具体数据的函数补全 时间盲注方法 import time import requests# 获取数据库名 def inject_database(url):dataname for i in range(1, 20):low 32high 128mid (low high) // 2while low < high:payload &q…

zyNo.22

常见Web漏洞解析 命令执行漏洞 1.Bash与CMD常用命令 &#xff08;1&#xff09;Bash 读取文件&#xff1a;最常见的命令cat flag 在 Bash 中&#xff0c;cat 以及的tac、nl、more、head、less、tail、od、pr 均为文件读取相关命令&#xff0c;它们的区别如下&#xff1a; …