当前位置: 首页 > article >正文

[HTML5]快速掌握canvas

背景

canvas 是 html5 标准中提供的一个标签, 顾名思义是定义在浏览器上的画布

  1. 通过其强大的绘图接口,我们可以实现各种各样的图形,炫酷的动画,
  2. 甚至可以利用他开发小游戏,包括市面上很流行的数据可视化框架底层都用到了Canvas。
  3. 既然他这么强大,那我们还有什么理由不去学习它呢?

基础

渲染上下文

<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. 坐标: 控制图形画在什么位置
  2. 尺寸: 控制图形画多大

绘制图形

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);

  1. x1和y1: 画笔的坐标
  2. x2和y2: 两个辅助点
  3. radius: 控制内切圆的半径, 半径越大弧越大
  4. 三个点相连组成角, 根据半径计算内切圆, 圆和三角相交的地方叫切点
  5. 切点相连就画出了一个弧, 弧与起点相连, 就是最终得到的弧线
  6. 示例
<!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);

  1. 参数x, y: 圆心的坐标
  2. 参数radius: 圆的半径
  3. 参数startAngle, endAngle: 起始角度和终止角度
  4. 参数anticlockwise: 顺时针还是逆时针, 默认顺时针
  5. 示例代码
<!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);

  1. 参数说明
  • cpx, cpy 是控制点的坐标
  • x,y 是结束点的坐标
  • 通过调整控制点, 就可以生成各种曲线
  1. 二次贝塞尔曲线调试工具:

Canvas Quadratic Curve Example

  1. 示例代码
<!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)

  1. 参数说明
  • 三阶就是比二阶多了一个控制点
  • cpx1, cpy1 是控制点1的坐标
  • cpx2, cpy2 是控制点2的坐标
  • x,y 是结束点的坐标
  • 通过调整控制点, 就可以生成各种曲线
  1. 三次贝塞尔调试工具:

Canvas Bézier Curve Example

  1. 示例代码
<!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. 线条样式

  1. lineWidth: 设置线条的宽度
  2. lineCap: 设置线条两端的形状

  1. setLineDash: 设置线条为虚线
  2. 代码示例
<!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. 渐变

  1. 线性渐变 ctx.createLinearGradient(x0,y0,x1, y1);
  • 参数说明
  • x0,y0是渐变的起点坐标
  • x1, y1是渐变的终点坐标
  • 有了起点和终点就确定了渐变的方向
  1. 径向渐变 ctx.createRadialGradient(x0,y0,r0, x1, y1, r1)
  • 参数说明
  • x0, y0是第一个圆的坐标(圆心), r0是半径
  • x1, y1是第二个圆的坐标(圆心), r1是半径
  1. 示例代码
<!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. 纹理样式

  1. 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用法

  1. drawlmage(image, dx, dy);
  2. drawlmage(image, dx, dy, dWidth, dHeight);
  3. 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>

进阶

变形

  1. 平移, 旋转, 缩放

平移(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>

  1. 状态的保存和恢复 (栈结构)

画布的状态是可以保存和恢复的

<!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>

  1. 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 种图片混排模式

  1. 语法: ctx.globalCompositeOperation = type;
  2. 重点参数: destination-out, 可以实现镂空效果

  1. 其他的合成模式

  1. 示例代码
<!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 标准中提供的一个标签, 顾名思义是定义在浏览器上的画布 通过其强大的绘图接口&#xff0c;我们可以实现各种各样的图形&#xff0c;炫酷的动画&#xff0c;甚至可以利用他开发小游戏&#xff0c;包括市面上很流行的数据可视化框架底层都用到了Canvas。…...

Gartner《Emerging Patterns for Building LLM-Based AIAgents》学习心得

一、AI代理概述 2024年,AI代理成为市场热点,它们能自主规划和行动以实现用户目标,与仅能感知、决策、行动和达成目标的AI助手及聊天机器人有本质区别。Gartner定义的AI代理是使用AI技术在数字或物理环境中自主或半自主运行的软件实体。 二、LLM基础AI代理的特性和挑战 优势…...

Hive SQL优化实践:提升大数据处理效率的关键策略

在大数据生态中&#xff0c;Hive作为基于Hadoop的数据仓库工具&#xff0c;广泛应用于海量数据的离线分析场景。然而&#xff0c;随着数据量的指数级增长和业务复杂度的提升&#xff0c;低效的Hive SQL可能导致资源浪费和查询性能瓶颈。本文将从存储优化、计算优化、资源配置三…...

vue中父子参数传递双向的方式不同

在面试中被问到。平时也有用到&#xff0c;但是缺少总结 父传子。父页面会给子页面中定义的props属性传参&#xff0c;子页面接收子传父。父页面需要监听事件来接收子页面通过$emit发送的消息其实说的以上两种都是组件之间传递。还可以通过路由传参, 状态管理器的方式传递 下面…...

LLM 使用 MCP 协议及其原理详解

LLM 使用 MCP 协议及其原理详解 &#x1f9e0; 一、MCP 协议概述 1. MCP 是什么&#xff1f; MCP&#xff08;Modular Communication Protocol&#xff09;是一种面向语言模型设计的通用通信协议&#xff0c;其设计目标是&#xff1a; 模块化&#xff08;Modular&#xff0…...

DAY 36神经网络加速器easy

仔细回顾一下神经网络到目前的内容&#xff0c;没跟上进度的同学补一下进度。 ●作业&#xff1a;对之前的信贷项目&#xff0c;利用神经网络训练下&#xff0c;尝试用到目前的知识点让代码更加规范和美观。 ●探索性作业&#xff08;随意完成&#xff09;&#xff1a;尝试进入…...

STM32 单片机启动过程全解析:从上电到主函数的旅程

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

4.RV1126-OPENCV 图像轮廓识别

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

WEB3——开发者怎么查看自己的合约日志记录

在区块链中查看合约的日志信息&#xff08;也叫事件 logs&#xff09;&#xff0c;主要有以下几种方式&#xff0c;具体方法依赖于你使用的区块链平台&#xff08;如 Ethereum、BSC、Polygon 等&#xff09;和工具&#xff08;如 Etherscan、web3.js、ethers.js、Hardhat 等&am…...

TDengine 集群容错与灾备

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

MG影视登录解锁永久VIP会员 v8.0 支持手机电视TV版影视直播软件

MG影视登录解锁永久VIP会员 v8.0 支持手机电视TV版影视直播软件 MG影视App电视版是一款资源丰富、免费便捷、且专为大屏优化的影视聚合应用&#xff0c;聚合海量资源&#xff0c;畅享电视直播&#xff0c;是您电视盒子和…...

如何成为一名优秀的产品经理(自动驾驶)

一、 夯实核心基础 深入理解智能驾驶技术栈&#xff1a; 感知&#xff1a; 摄像头、雷达&#xff08;毫米波、激光雷达&#xff09;、超声波传感器的工作原理、优缺点、融合策略。了解目标检测、跟踪、SLAM等基础算法概念。 定位&#xff1a; GNSS、IMU、高精地图、轮速计等定…...

BAT脚本编写详细教程

目录 第一部分:BAT脚本简介第二部分:创建和运行BAT脚本第三部分:基本命令和语法第四部分:变量使用第五部分:流程控制第六部分:函数和子程序第七部分:高级技巧第八部分:实用示例第一部分:BAT脚本简介 BAT脚本(批处理脚本)是Windows操作系统中的一种脚本文件,扩展名…...

快速了解 GO之接口解耦

更多个人笔记见&#xff1a; &#xff08;注意点击“继续”&#xff0c;而不是“发现新项目”&#xff09; github个人笔记仓库 https://github.com/ZHLOVEYY/IT_note gitee 个人笔记仓库 https://gitee.com/harryhack/it_note 个人学习&#xff0c;学习过程中还会不断补充&…...

【多线程初阶】内存可见性问题 volatile

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

C++ 类模板三参数深度解析:从链表迭代器看类型推导与实例化(为什么迭代器类模版使用三参数?实例化又会是怎样?)

本篇主要续上一篇的list模拟实现遇到的问题详细讲解&#xff1a;<传送门> 一、引言&#xff1a;模板参数的 "三角锁钥" 在 C 双向链表实现中&#xff0c;__list_iterator类模板的三个参数&#xff08;T、Ref、Ptr&#xff09;如同精密仪器的调节旋钮&#x…...

MySQL强化关键_018_MySQL 优化手段及性能分析工具

目 录 一、优化手段 二、SQL 性能分析工具 1.查看数据库整体情况 &#xff08;1&#xff09;语法格式 &#xff08;2&#xff09;说明 2.慢查询日志 &#xff08;1&#xff09;说明 &#xff08;2&#xff09;开启慢查询日志功能 &#xff08;3&#xff09;实例 3.s…...

ASP.NET MVC添加模型示例

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

【Part 3 Unity VR眼镜端播放器开发与优化】第二节|VR眼镜端的开发适配与交互设计

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

第1天:认识RNN及RNN初步实验(预测下一个数字)

RNN&#xff08;循环神经网络&#xff09; 是一种专门设计用来处理序列数据的人工神经网络。它的核心思想是能够“记住”之前处理过的信息&#xff0c;并将其用于当前的计算&#xff0c;这使得它非常适合处理具有时间顺序或上下文依赖关系的数据。 核心概念&#xff1a;循环连…...

全文索引详解及适用场景分析

全文索引详解及适用场景分析 1. 全文索引基本概念 1.1 定义与核心原理 全文索引(Full-Text Index)是一种特殊的数据库索引类型,专门设计用于高效处理文本数据的搜索需求。与传统的B树索引不同,全文索引不是基于精确匹配,而是通过建立倒排索引(Inverted Index)结构来实现对…...

利用DeepSeek编写能在DuckDB中读PostgreSQL表的表函数

前文实现了UDF和UDAF&#xff0c;还有一类函数是表函数&#xff0c;它放在From 子句中&#xff0c;返回一个集合。DuckDB中已有PostgreSQL插件&#xff0c;但我们可以用pqxx库实现一个简易的只读read_pg()表函数。 提示词如下&#xff1a; 请将libpqxx库集成到我们的程序&#…...

树莓派安装openwrt搭建软路由(ImmortalWrt固件方案)

&#x1f923;&#x1f449;我这里准备了两个版本的openwrt安装方案给大家参考使用&#xff0c;分别是原版的OpenWrt固件以及在原版基础上进行改进的ImmortalWrt固件。推荐使用ImmortalWrt固件&#xff0c;当然如果想直接在原版上进行开发也可以&#xff0c;看个人选择。 &…...

排序算法——详解

排序算法 &#xff08;冒泡、选择、插入、快排、归并、堆排、计数、桶、基数&#xff09; 稳定性 (Stability): 如果排序算法能保证&#xff0c;当待排序序列中存在值相等的元素时&#xff0c;排序后这些元素的相对次序保持不变&#xff0c;那么该算法就是稳定的。 例如&#…...

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的区块链钱包开发实践&#xff1a;打造支持鸿蒙生态的Web3应用 前言 最近在带领团队开发一个支持多链的区块链钱包项目时&#xff0c;我们选择了UniApp作为开发框架。这个选择让我们不仅实现了传统移动平台的覆盖&#xff0c;还成功将应用引入了快速发展的鸿蒙生态…...

易学探索助手-个人记录(十二)

近期我完成了古籍处理板块页面升级&#xff0c;补充完成原文、句读、翻译的清空、保存和编辑&#xff08;其中句读仅可修改标点&#xff09;功能&#xff0c;新增原文和句读的繁简体切换功能 一、古籍处理板块整体页面升级 将原来一整个页面呈现的布局改为分栏呈现&#xff0…...

Windows 账号管理与安全指南

Windows 账号管理与安全指南 概述 Windows 账号管理是系统安全的基础&#xff0c;了解如何正确创建、管理和保护用户账户对于系统管理员和安全专业人员至关重要。本文详细介绍 Windows 系统中的账户管理命令、隐藏账户创建方法以及安全防护措施。 基础账户管理命令 net use…...

Python窗体编程技术详解

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