[HTML5]快速掌握canvas
背景
canvas 是 html5 标准中提供的一个标签, 顾名思义是定义在浏览器上的画布
- 通过其强大的绘图接口,我们可以实现各种各样的图形,炫酷的动画,
- 甚至可以利用他开发小游戏,包括市面上很流行的数据可视化框架底层都用到了Canvas。
- 既然他这么强大,那我们还有什么理由不去学习它呢?
基础
渲染上下文
<canvas>是一个HTML元素,我们可以将它简单理解为一个画板,通过Canvas提供的绘制api我们就可以绘制出各种图形。
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.canvas {background-color: pink;}</style>
</head><body><canvas id="canvas" width="600" height="600" class="canvas" /><script>// 获取画布const c = document.getElementById("canvas")/*** 获取画笔* 可选参数: * 2d: 获取平面画笔, 绘制2d图形* webgl: 获取3d画笔, 绘制3d图形 * */const ctx = c.getContext("2d")</script>
</body></html>
canvas中的坐标系和html中的坐标系一样
- 坐标: 控制图形画在什么位置
- 尺寸: 控制图形画多大
绘制图形
1.1. 线(线, 三角形, 矩形)
重要的API
- 绘制: moveTo, lineTo,stroke
- 设置样式: lineWidth,strokeStyle
- 路径: beginPath,closePath
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.canvas {background-color: pink;}</style>
</head><body><canvas id="canvas" width="600" height="600" class="canvas" /><script>// 获取画布const c = document.getElementById("canvas")/*** 获取画笔*/const ctx = c.getContext("2d")/*** 绘制线条 */ctx.moveTo(0, 10) // 确定画笔位置ctx.lineTo(200, 10) // 线的终点ctx.lineWidth = 50 // 设置线的宽度ctx.strokeStyle = 'red' // 设置画笔的颜色 (画笔是全局唯一实例)ctx.stroke() // 完成绘制/*** 绘制线条 */ctx.beginPath() // 新建路径, 不影响其他路径ctx.moveTo(0, 50)ctx.lineTo(200, 50)ctx.lineWidth = 10ctx.strokeStyle = 'blue'ctx.stroke() // stroke的绘制以beginPath为界/*** 绘制三角形*/ctx.beginPath()ctx.moveTo(0, 70)ctx.lineTo(200, 70)ctx.lineTo(50, 200)// ctx.lineTo(0, 70) // 手动画线完成路径闭合ctx.closePath() // 让路径自动闭合ctx.lineWidth = 1ctx.fillStyle = 'green' // 设置填充颜色ctx.fill() // 完成填充ctx.strokeStyle = 'red' // 设置画笔颜色ctx.stroke() // 完成绘制/*** 绘制矩形1*/ctx.beginPath()// 上定义矩形: 四个参数分别表示矩形左上角的 x 坐标、y 坐标,以及矩形的宽度和高度。ctx.rect(0, 220, 200, 100)ctx.strokeStyle = 'green'ctx.stroke()/*** 绘制矩形2*/ctx.beginPath()// 绘制矩形并设置填充色ctx.fillStyle = 'red'ctx.fillRect(10, 350, 150 ,100)// 绘制矩形并设置边框颜色ctx.strokeStyle = 'green'ctx.strokeRect(50, 460, 150, 100)</script>
</body></html>
1.2. 弧线(弧, 圆弧, 圆)
arcTo(x1, y1, x2, y2, radius);
- x1和y1: 画笔的坐标
- x2和y2: 两个辅助点
- radius: 控制内切圆的半径, 半径越大弧越大
- 三个点相连组成角, 根据半径计算内切圆, 圆和三角相交的地方叫切点
- 切点相连就画出了一个弧, 弧与起点相连, 就是最终得到的弧线
- 示例
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.canvas {background-color: pink;}</style>
</head><body><canvas id="canvas" width="600" height="600" class="canvas" /><script>// 获取画布const c = document.getElementById("canvas")// 获取画笔const ctx = c.getContext("2d")// 画弧线ctx.beginPath()ctx.moveTo(200, 10) // 画笔位置就是起点ctx.arcTo(200, 300, 0, 10, 80) // 画弧ctx.lineWidth = 5ctx.strokeStyle = 'green'ctx.stroke()// 画辅助线帮助理解ctx.strokeStyle = 'red'ctx.lineWidth = 1ctx.beginPath()ctx.moveTo(200, 10)ctx.lineTo(200, 300)ctx.lineTo(200, 300)ctx.lineTo(0, 10)ctx.closePath()ctx.stroke()</script>
</body></html>
arc(x, y,radius, startAngle, endAngle, anticlockwise);
- 参数x, y: 圆心的坐标
- 参数radius: 圆的半径
- 参数startAngle, endAngle: 起始角度和终止角度
- 参数anticlockwise: 顺时针还是逆时针, 默认顺时针
- 示例代码
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.canvas {background-color: pink;}</style>
</head><body><canvas id="canvas" width="600" height="600" class="canvas" /><script>// 获取画布const c = document.getElementById("canvas")// 获取画笔const ctx = c.getContext("2d")// 画弧ctx.beginPath()ctx.arc(400, 400, 100, 0, Math.PI / 6, true)ctx.strokeStyle = "red"ctx.stroke()</script>
</body></html>
1.3. 贝塞尔曲线
贝塞尔曲线二阶
quadraticCurveTo(cpx, cpy, x, y);
- 参数说明
- cpx, cpy 是控制点的坐标
- x,y 是结束点的坐标
- 通过调整控制点, 就可以生成各种曲线
- 二次贝塞尔曲线调试工具:
Canvas Quadratic Curve Example
- 示例代码
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.canvas {background-color: pink;}</style>
</head><body><canvas id="canvas" width="600" height="600" class="canvas" /><script>// 获取画布const c = document.getElementById("canvas")// 获取画笔const ctx = c.getContext("2d")// ==================================// 画二阶ctx.beginPath()ctx.moveTo(100, 100) // 起始点坐标ctx.quadraticCurveTo(200, 500, 400, 400)ctx.stroke()// 辅助点ctx.fillStyle = 'red'ctx.fillRect(100, 100, 10, 10)ctx.fillRect(200, 500, 10, 10)ctx.fillRect(400, 400, 10, 10)// ==================================</script>
</body></html>
贝塞尔曲线三阶
bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
- 参数说明
- 三阶就是比二阶多了一个控制点
- cpx1, cpy1 是控制点1的坐标
- cpx2, cpy2 是控制点2的坐标
- x,y 是结束点的坐标
- 通过调整控制点, 就可以生成各种曲线
- 三次贝塞尔调试工具:
Canvas Bézier Curve Example
- 示例代码
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.canvas {background-color: pink;}</style>
</head><body><canvas id="canvas" width="600" height="600" class="canvas" /><script>// 获取画布const c = document.getElementById("canvas")// 获取画笔const ctx = c.getContext("2d")// ==================================// 画三阶ctx.beginPath()ctx.moveTo(20, 20)ctx.bezierCurveTo(20, 700, 200, 100, 700, 500)ctx.stroke()// ==================================</script>
</body></html>
绘图样式
a. 线条样式
- lineWidth: 设置线条的宽度
- lineCap: 设置线条两端的形状
- setLineDash: 设置线条为虚线
- 代码示例
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.canvas {background-color: pink;}</style>
</head><body><canvas id="canvas" width="600" height="600" class="canvas" /><script>// 获取画布const c = document.getElementById("canvas")// 获取画笔const ctx = c.getContext("2d")// 线段样式ctx.lineWidth = 15ctx.lineCap = 'round'ctx.beginPath()ctx.moveTo(50, 50)ctx.lineTo(300, 50)ctx.stroke()// 绘制虚线ctx.beginPath()ctx.moveTo(50, 150)// 参数的是数组, 控制一组线段// 20是第一个线段长度,40是间隔距离, 50是第二个线段长度 ctx.setLineDash([20, 40, 50])ctx.lineWidth = 1;ctx.lineTo(500, 150)ctx.stroke()</script>
</body></html>
b. 渐变
- 线性渐变 ctx.createLinearGradient(x0,y0,x1, y1);
- 参数说明
- x0,y0是渐变的起点坐标
- x1, y1是渐变的终点坐标
- 有了起点和终点就确定了渐变的方向
- 径向渐变 ctx.createRadialGradient(x0,y0,r0, x1, y1, r1)
- 参数说明
- x0, y0是第一个圆的坐标(圆心), r0是半径
- x1, y1是第二个圆的坐标(圆心), r1是半径
- 示例代码
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.canvas {background-color: pink;}</style>
</head><body><canvas id="canvas" width="600" height="600" class="canvas" /><script>// 获取画布const c = document.getElementById("canvas")// 获取画笔const ctx = c.getContext("2d")// 线性渐变let gradient = ctx.createLinearGradient(0, 0, 200, 0) // 设置渐变gradient.addColorStop(0, 'green') // 设置渐变点和颜色值gradient.addColorStop(1, 'blue') // 设置渐变点和颜色值ctx.fillStyle = gradientctx.fillRect(50, 200, 200, 100) // 绘制矩形// 径向渐变let gradient2 = ctx.createRadialGradient(150, 450, 150, 150, 450, 0) // 设置渐变gradient2.addColorStop(0, 'white')gradient2.addColorStop(1, 'green')ctx.fillStyle = gradient2ctx.fillRect(50, 350, 200, 200)</script>
</body></html>
c. 纹理样式
- ctx.createPattern(image, repetition);
参数说明
- image: 把图片作为纹理进行填充
- repetition: 是否重复
代码示例
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.canvas {background-color: pink;}</style>
</head><body><canvas id="canvas" width="600" height="600" class="canvas" /><script>// 获取画布const c = document.getElementById("canvas")// 获取画笔const ctx = c.getContext("2d")// 纹理样式let img = new Image()img.src = 'images/DE.jpg'img.onload = function () {let pattern = ctx.createPattern(img, 'repeat')ctx.fillStyle = patternctx.fillRect(50, 200, 300, 100)}</script>
</body></html>
绘制文本
绘制方式
- 轮廓文本 stokeText()
- 填充文本 fillText()
绘制样式
- font、textAlign(设置水平对齐方式)、direction(设置文字方向)、textBaseline(设置垂直对齐方式)
- 阴影: shadowOffsetX和shadowOffsetY、shadowBlur、shadowColor
示例代码
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.canvas {background-color: pink;}</style>
</head><body><canvas id="canvas" width="600" height="600" class="canvas" /><script>// 获取画布const c = document.getElementById("canvas")// 获取画笔const ctx = c.getContext("2d")// 设置文字样式 (字号: 88px 字体: 罗马字体)ctx.font = "88px Times New Roman"// 设置阴影ctx.shadowOffsetX = 2 //偏移ctx.shadowOffsetY = 2 //偏移ctx.shadowBlur = 2 //模糊度ctx.shadowColor = "rgba(255,0,0,0.5)"// 绘制文本ctx.fillText('hello canvas', 100, 100)// 纹理背景文字let img = new Image()img.src = 'images/DE.jpg'img.onload = function () {let pattern = ctx.createPattern(img, 'repeat')ctx.fillStyle = patternctx.fillText('hello canvas2', 100, 400)}</script>
</body></html>
绘制图片
drawimage用法
- drawlmage(image, dx, dy);
- drawlmage(image, dx, dy, dWidth, dHeight);
- drawlmage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.canvas {background-color: pink;}</style>
</head><body><canvas id="canvas" width="600" height="600" class="canvas" /><script>// 获取画布const c = document.getElementById("canvas")// 获取画笔const ctx = c.getContext("2d")// 绘制图片let img = new Image()img.src = 'images/DE.jpg'img.onload = function () {// 1. 在指定位置画一张图// drawlmage(image, dx, dy); ctx.drawImage(img, 0, 0)// 2.在指定位置画一张图, 并设置图的尺寸// drawlmage(image, dx, dy, dWidth, dHeight);ctx.drawImage(img, 0, 120, 50, 50)// 3.指定一张图(image), 选择抠图的位置(sx, sy), 设置抠取的尺寸(sWidth, sHeight), 把抠出来的图放在哪(dx, dy), 放多大(dWidth, dHeight)// drawlmage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight);ctx.drawImage(img, 0, 0, 80, 80, 100, 200, 50, 50)}</script>
</body></html>
进阶
变形
- 平移, 旋转, 缩放
平移(translate)、旋转(rotate)、缩放(scale)
平移改变的是画布的坐标系位置
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.canvas {background-color: pink;}</style>
</head><body><canvas id="canvas" width="600" height="600" class="canvas" /><script>// 获取画布const c = document.getElementById("canvas")// 获取画笔const ctx = c.getContext("2d")//==================================// 测试平移的效果// 画个矩形ctx.fillStyle = 'red'ctx.fillRect(0, 0, 100, 100)// 平移坐标后再画一个矩形ctx.translate(400, 400)ctx.fillRect(0, 0, 100, 100)// 把坐标平移回原点, 再画一个矩形ctx.translate(-400, -400)ctx.fillStyle = 'black'ctx.fillRect(0, 0, 50, 50)</script>
</body></html>
旋转和缩放是对图形的操作
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.canvas {background-color: pink;}</style>
</head><body><canvas id="canvas" width="600" height="600" class="canvas" /><script>// 获取画布const c = document.getElementById("canvas")// 获取画笔const ctx = c.getContext("2d")// 旋转图形ctx.fillStyle = 'yellow'ctx.rotate(Math.PI / 6) // 旋转60度ctx.fillRect(100, 0, 100, 100)ctx.restore()// 缩放图形ctx.fillStyle = 'blue'ctx.scale(0.5, 0.5)ctx.fillRect(400, 400, 100, 100)ctx.restore()</script>
</body></html>
- 状态的保存和恢复 (栈结构)
画布的状态是可以保存和恢复的
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.canvas {background-color: pink;}</style>
</head><body><canvas id="canvas" width="600" height="600" class="canvas" /><script>// 获取画布const c = document.getElementById("canvas")// 获取画笔const ctx = c.getContext("2d")// 上案例的写法需要不断平移坐标, 比较麻烦// 通过保存和恢复画布状态, 简化对画布的操作// 画个矩形ctx.fillStyle = 'red'ctx.fillRect(0, 0, 100, 100)// 平移前先保存画布的状态信息ctx.save()// 平移坐标后再画一个矩形ctx.translate(400, 400)ctx.fillRect(0, 0, 100, 100)// 绘制完平移的图形后,恢复之前的状态信息ctx.restore()// 再绘制图形就不受平移的影响了ctx.fillStyle = 'black'ctx.fillRect(0, 0, 50, 50)</script>
</body></html>
- transform, setTransform
矩阵变换
语法: transform(a, b, c, d, e, f);
参数:
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.canvas {background-color: pink;}</style>
</head><body><canvas id="canvas" width="600" height="600" class="canvas" /><script>// 获取画布const c = document.getElementById("canvas")// 获取画笔const ctx = c.getContext("2d")// 矩阵变换-平移ctx.transform(1, 0, 0, 1, 400, 400)ctx.fillStyle = 'red'ctx.fillRect(0, 0, 100, 100)ctx.restore()// 矩阵变换-缩放ctx.transform(0.5, 0, 0, 0.5, 10, 10)ctx.fillStyle = 'green'ctx.fillRect(0, 0, 100, 100)ctx.restore()// 矩阵变换-倾斜ctx.transform(1, 0.2, 0.2, 1, 10, 10)ctx.fillStyle = 'blue'ctx.fillRect(0, 0, 100, 100)ctx.restore()</script>
</body></html>
合成
Canvas 提供了26 种图片混排模式
- 语法: ctx.globalCompositeOperation = type;
- 重点参数: destination-out, 可以实现镂空效果
- 其他的合成模式
- 示例代码
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.canvas {background-color: pink;}</style>
</head><body><canvas id="canvas" width="600" height="600" class="canvas" /><script>// 获取画布const c = document.getElementById("canvas")// 获取画笔const ctx = c.getContext("2d")ctx.fillStyle = 'blue'ctx.fillRect(10, 10, 100, 100)// source-over: 默认值, 后绘制的图形覆盖先绘制的图形// ctx.globalCompositeOperation = 'source-over'// destination-over: 先绘制的图形覆盖后绘制的图形// ctx.globalCompositeOperation = 'destination-over'// destination-out: 图形相交的部分镂空ctx.globalCompositeOperation = 'destination-out'ctx.fillStyle = 'red'ctx.fillRect(50, 50, 100, 100)</script>
</body></html>
裁剪
clip() 需要配置路径使用
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.canvas {background-color: pink;}</style>
</head><body><canvas id="canvas" width="600" height="600" class="canvas" /><script>// 获取画布const c = document.getElementById("canvas")// 获取画笔const ctx = c.getContext("2d")ctx.rect(0, 0, 200, 100) // 矩形区域ctx.clip() // 超出矩形区域的文字会被裁剪ctx.fillStyle = 'red'ctx.font = '44px Times New Roman'ctx.fillText('hello canvas', 50, 50)</script>
</body></html>
实战
1. 放大镜效果
技术点: 离屏渲染
将一个canvas对象绘制到另一个canvas对象上 (离开用户可视范围内进行染)
2. 刮刮乐效果
技术点: 图像合成
利用图像合成让绘制的内容与原矩形重合部分清空
3. 滤镜效果
技术点: 单位像素处理
这里我们主要借用 getlmageData 函数,他返回每个像素的 RGBA 值。借助图像处理公式,操作像素进行相应的、数学运算即可。
- getlmageData()
- putlmageData()
相关文章:

[HTML5]快速掌握canvas
背景 canvas 是 html5 标准中提供的一个标签, 顾名思义是定义在浏览器上的画布 通过其强大的绘图接口,我们可以实现各种各样的图形,炫酷的动画,甚至可以利用他开发小游戏,包括市面上很流行的数据可视化框架底层都用到了Canvas。…...

Gartner《Emerging Patterns for Building LLM-Based AIAgents》学习心得
一、AI代理概述 2024年,AI代理成为市场热点,它们能自主规划和行动以实现用户目标,与仅能感知、决策、行动和达成目标的AI助手及聊天机器人有本质区别。Gartner定义的AI代理是使用AI技术在数字或物理环境中自主或半自主运行的软件实体。 二、LLM基础AI代理的特性和挑战 优势…...
Hive SQL优化实践:提升大数据处理效率的关键策略
在大数据生态中,Hive作为基于Hadoop的数据仓库工具,广泛应用于海量数据的离线分析场景。然而,随着数据量的指数级增长和业务复杂度的提升,低效的Hive SQL可能导致资源浪费和查询性能瓶颈。本文将从存储优化、计算优化、资源配置三…...
vue中父子参数传递双向的方式不同
在面试中被问到。平时也有用到,但是缺少总结 父传子。父页面会给子页面中定义的props属性传参,子页面接收子传父。父页面需要监听事件来接收子页面通过$emit发送的消息其实说的以上两种都是组件之间传递。还可以通过路由传参, 状态管理器的方式传递 下面…...
LLM 使用 MCP 协议及其原理详解
LLM 使用 MCP 协议及其原理详解 🧠 一、MCP 协议概述 1. MCP 是什么? MCP(Modular Communication Protocol)是一种面向语言模型设计的通用通信协议,其设计目标是: 模块化(Modular࿰…...
DAY 36神经网络加速器easy
仔细回顾一下神经网络到目前的内容,没跟上进度的同学补一下进度。 ●作业:对之前的信贷项目,利用神经网络训练下,尝试用到目前的知识点让代码更加规范和美观。 ●探索性作业(随意完成):尝试进入…...

STM32 单片机启动过程全解析:从上电到主函数的旅程
一、为什么要理解启动过程? STM32 的启动过程就像一台精密仪器的开机自检,它确保所有系统部件按既定方式初始化,才能顺利运行我们的应用代码。对初学者而言,理解启动过程能帮助解决常见“程序跑飞”“不进 main”“下载后无反应”…...

4.RV1126-OPENCV 图像轮廓识别
一.图像识别API 1.图像识别作用 它常用于视觉任务、目标检测、图像分割等等。在 OPENCV 中通常使用 Canny 函数、findContours 函数、drawContours 函数结合在一起去做轮廓的形检测。 2.常用的API findContours 函数:用于寻找图片的轮廓,并把所有的数…...

WEB3——开发者怎么查看自己的合约日志记录
在区块链中查看合约的日志信息(也叫事件 logs),主要有以下几种方式,具体方法依赖于你使用的区块链平台(如 Ethereum、BSC、Polygon 等)和工具(如 Etherscan、web3.js、ethers.js、Hardhat 等&am…...

TDengine 集群容错与灾备
简介 为了防止数据丢失、误删操作,TDengine 提供全面的数据备份、恢复、容错、异地数据实时同步等功能,以保证数据存储的安全。本节简要说明 TDengine 中的容错与灾备。 容错 TDengine 支持 WAL 机制,实现数据的容错能力,保证数…...

MG影视登录解锁永久VIP会员 v8.0 支持手机电视TV版影视直播软件
MG影视登录解锁永久VIP会员 v8.0 支持手机电视TV版影视直播软件 MG影视App电视版是一款资源丰富、免费便捷、且专为大屏优化的影视聚合应用,聚合海量资源,畅享电视直播,是您电视盒子和…...
如何成为一名优秀的产品经理(自动驾驶)
一、 夯实核心基础 深入理解智能驾驶技术栈: 感知: 摄像头、雷达(毫米波、激光雷达)、超声波传感器的工作原理、优缺点、融合策略。了解目标检测、跟踪、SLAM等基础算法概念。 定位: GNSS、IMU、高精地图、轮速计等定…...
BAT脚本编写详细教程
目录 第一部分:BAT脚本简介第二部分:创建和运行BAT脚本第三部分:基本命令和语法第四部分:变量使用第五部分:流程控制第六部分:函数和子程序第七部分:高级技巧第八部分:实用示例第一部分:BAT脚本简介 BAT脚本(批处理脚本)是Windows操作系统中的一种脚本文件,扩展名…...
快速了解 GO之接口解耦
更多个人笔记见: (注意点击“继续”,而不是“发现新项目”) github个人笔记仓库 https://github.com/ZHLOVEYY/IT_note gitee 个人笔记仓库 https://gitee.com/harryhack/it_note 个人学习,学习过程中还会不断补充&…...

【多线程初阶】内存可见性问题 volatile
文章目录 再谈线程安全问题内存可见性问题可见性问题案例编译器优化 volatileJava内存模型(JMM) 再谈线程安全问题 如果多线程环境下代码运行的结果是符合我们预期的,即在单线程环境应该有的结果,则说这个程序是线程安全的,反之,多线程环境中,并发执行后,产生bug就是线程不安全…...

C++ 类模板三参数深度解析:从链表迭代器看类型推导与实例化(为什么迭代器类模版使用三参数?实例化又会是怎样?)
本篇主要续上一篇的list模拟实现遇到的问题详细讲解:<传送门> 一、引言:模板参数的 "三角锁钥" 在 C 双向链表实现中,__list_iterator类模板的三个参数(T、Ref、Ptr)如同精密仪器的调节旋钮&#x…...

MySQL强化关键_018_MySQL 优化手段及性能分析工具
目 录 一、优化手段 二、SQL 性能分析工具 1.查看数据库整体情况 (1)语法格式 (2)说明 2.慢查询日志 (1)说明 (2)开启慢查询日志功能 (3)实例 3.s…...

ASP.NET MVC添加模型示例
ASP.NET MVC高效构建Web应用ASP.NET MVC 我们总在谈“模型”,那到底什么是模型?简单说来,模型就是当我们使用软件去解决真实世界中各种实际问题的时候,对那些我们关心的实际事物的抽象和简化。比如,我们在软件系统中设…...

【Part 3 Unity VR眼镜端播放器开发与优化】第二节|VR眼镜端的开发适配与交互设计
文章目录 《VR 360全景视频开发》专栏Part 3|Unity VR眼镜端播放器开发与优化第一节|基于Unity的360全景视频播放实现方案第二节|VR眼镜端的开发适配与交互设计一、Unity XR开发环境与设备适配1.1 启用XR Plugin Management1.2 配置OpenXR与平…...

第1天:认识RNN及RNN初步实验(预测下一个数字)
RNN(循环神经网络) 是一种专门设计用来处理序列数据的人工神经网络。它的核心思想是能够“记住”之前处理过的信息,并将其用于当前的计算,这使得它非常适合处理具有时间顺序或上下文依赖关系的数据。 核心概念:循环连…...
全文索引详解及适用场景分析
全文索引详解及适用场景分析 1. 全文索引基本概念 1.1 定义与核心原理 全文索引(Full-Text Index)是一种特殊的数据库索引类型,专门设计用于高效处理文本数据的搜索需求。与传统的B树索引不同,全文索引不是基于精确匹配,而是通过建立倒排索引(Inverted Index)结构来实现对…...
利用DeepSeek编写能在DuckDB中读PostgreSQL表的表函数
前文实现了UDF和UDAF,还有一类函数是表函数,它放在From 子句中,返回一个集合。DuckDB中已有PostgreSQL插件,但我们可以用pqxx库实现一个简易的只读read_pg()表函数。 提示词如下: 请将libpqxx库集成到我们的程序&#…...

树莓派安装openwrt搭建软路由(ImmortalWrt固件方案)
🤣👉我这里准备了两个版本的openwrt安装方案给大家参考使用,分别是原版的OpenWrt固件以及在原版基础上进行改进的ImmortalWrt固件。推荐使用ImmortalWrt固件,当然如果想直接在原版上进行开发也可以,看个人选择。 &…...
排序算法——详解
排序算法 (冒泡、选择、插入、快排、归并、堆排、计数、桶、基数) 稳定性 (Stability): 如果排序算法能保证,当待排序序列中存在值相等的元素时,排序后这些元素的相对次序保持不变,那么该算法就是稳定的。 例如&#…...
Go整合Redis2.0发布订阅
Go整合Redis2.0发布订阅 Redis goredis-cli --version redis-cli 5.0.14.1 (git:ec77f72d)Go go get github.com/go-redis/redis/v8package redisimport ("MyKindom-Server-v2.0/com/xzm/core/config/yaml""MyKindom-Server-v2.0/com/xzm/core/config/yaml/po…...

电子电气架构 --- 如何应对未来区域式电子电气(E/E)架构的挑战?
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…...
鸿蒙OS基于UniApp的区块链钱包开发实践:打造支持鸿蒙生态的Web3应用#三方框架 #Uniapp
基于UniApp的区块链钱包开发实践:打造支持鸿蒙生态的Web3应用 前言 最近在带领团队开发一个支持多链的区块链钱包项目时,我们选择了UniApp作为开发框架。这个选择让我们不仅实现了传统移动平台的覆盖,还成功将应用引入了快速发展的鸿蒙生态…...

易学探索助手-个人记录(十二)
近期我完成了古籍处理板块页面升级,补充完成原文、句读、翻译的清空、保存和编辑(其中句读仅可修改标点)功能,新增原文和句读的繁简体切换功能 一、古籍处理板块整体页面升级 将原来一整个页面呈现的布局改为分栏呈现࿰…...
Windows 账号管理与安全指南
Windows 账号管理与安全指南 概述 Windows 账号管理是系统安全的基础,了解如何正确创建、管理和保护用户账户对于系统管理员和安全专业人员至关重要。本文详细介绍 Windows 系统中的账户管理命令、隐藏账户创建方法以及安全防护措施。 基础账户管理命令 net use…...

Python窗体编程技术详解
文章目录 1. Tkinter简介示例代码优势劣势 2. PyQt/PySide简介示例代码(PyQt5)优势劣势 3. wxPython简介示例代码优势劣势 4. Kivy简介示例代码优势劣势 5. PySimpleGUI简介示例代码优势劣势 技术对比总结选择建议 Python提供了多种实现图形用户界面(GUI)编程的技术,…...