canvas(填充描边,绘制矩形、路径、文本、图像,变换,阴影,渐变等)
一、 基本的画布功能
<canvas id="drawing" width="200" height="200">A drawing of something.</canvas>
let drawing = document.getElementById("drawing");
// 确保浏览器支持<canvas>
if (drawing.getContext) {let context = drawing.getContext("2d");// 其他代码
}
let drawing = document.getElementById("drawing");
// 确保浏览器支持<canvas>
if (drawing.getContext) {// 取得图像的数据 URIlet imgURI = drawing.toDataURL("image/png");// 显示图片let image = document.createElement("img");image.src = imgURI;document.body.appendChild(image);
}
浏览器默认将图像编码为 PNG 格式,除非另行指定。Firefox 和 Opera 还支持传入"image/jpeg"
二、2D 绘图上下文
1 填充和描边
let drawing = document.getElementById("drawing");
// 确保浏览器支持<canvas>
if (drawing.getContext) {let context = drawing.getContext("2d");context.strokeStyle = "red";context.fillStyle = "#0000ff";
}
这里把 strokeStyle 设置为"red"(CSS 颜色名称),把 fillStyle 设置为"#0000ff"(蓝色)。
2 绘制矩形
fillRect()方法
let drawing = document.getElementById("drawing");
// 确保浏览器支持<canvas>
if (drawing.getContext) {let context = drawing.getContext("2d");// 绘制红色矩形context.fillStyle = "#ff0000";context.fillRect(10, 10, 50, 50);// 绘制半透明蓝色矩形context.fillStyle = "rgba(0,0,255,0.5)";context.fillRect(30, 30, 50, 50);
}
以上代码先将 fillStyle 设置为红色并在坐标点(10, 10)绘制了一个宽高均为 50 像素的矩形。接
strokeRect()方法
使用通过 strokeStyle 属性指定的颜色绘制矩形轮廓。下面是一个例子:
let drawing = document.getElementById("drawing");
// 确保浏览器支持<canvas>
if (drawing.getContext) {let context = drawing.getContext("2d");// 绘制红色轮廓的矩形context.strokeStyle = "#ff0000";context.strokeRect(10, 10, 50, 50);// 绘制半透明蓝色轮廓的矩形context.strokeStyle = "rgba(0,0,255,0.5)";context.strokeRect(30, 30, 50, 50);
}
clearRect()方法
let drawing = document.getElementById("drawing");
// 确保浏览器支持<canvas>
if (drawing.getContext) {let context = drawing.getContext("2d");// 绘制红色矩形context.fillStyle = "#ff0000";context.fillRect(10, 10, 50, 50);// 绘制半透明蓝色矩形context.fillStyle = "rgba(0,0,255,0.5)";context.fillRect(30, 30, 50, 50);// 在前两个矩形重叠的区域擦除一个矩形区域context.clearRect(40, 40, 10, 10);
}
3 绘制路径
arc(x, y, radius, startAngle, endAngle, counterclockwise)
arcTo(x1, y1, x2, y2, radius)
bezierCurveTo(c1x, c1y, c2x, c2y, x, y)
lineTo(x, y)
moveTo(x, y)
quadraticCurveTo(cx, cy, x, y)
rect(x, y, width, height)
let drawing = document.getElementById("drawing");
// 确保浏览器支持<canvas>
if (drawing.getContext) {let context = drawing.getContext("2d");// 创建路径context.beginPath();// 绘制外圆context.arc(100, 100, 99, 0, 2 * Math.PI, false);// 绘制内圆context.moveTo(194, 100);context.arc(100, 100, 94, 0, 2 * Math.PI, false);// 绘制分针context.moveTo(100, 100);context.lineTo(100, 15);// 绘制时针context.moveTo(100, 100);context.lineTo(35, 100);// 描画路径context.stroke();
}
if (context.isPointInPath(100, 100)) {alert("Point (100, 100) is in the path.");
}
2D 上下文的路径 API 非常可靠,可用于创建涉及各种填充样式、描述样式等的复杂图像。
4 绘制文本
font
textAlign
textBaseLine
context.font = "bold 14px Arial";
context.textAlign = "center";
context.textBaseline = "middle";
context.fillText("12", 100, 20);
// 正常
context.font = "bold 14px Arial";
context.textAlign = "center";
context.textBaseline = "middle";
context.fillText("12", 100, 20);
// 与开头对齐
context.textAlign = "start";
context.fillText("12", 100, 40);
// 与末尾对齐
context.textAlign = "end";
context.fillText("12", 100, 60);
let fontSize = 100;
context.font = fontSize + "px Arial";
while(context.measureText("Hello world!").width > 140) {
fontSize--;
context.font = fontSize + "px Arial";
}
context.fillText("Hello world!", 10, 10);
context.fillText("Font size is " + fontSize + "px", 10, 50);
5 变换
rotate(angle)
scale(scaleX, scaleY)
translate(x, y)
setTransform(m1_1, m1_2, m2_1, m2_2, dx, dy)
let drawing = document.getElementById("drawing");
// 确保浏览器支持<canvas>
if (drawing.getContext) {let context = drawing.getContext("2d");// 创建路径context.beginPath();// 绘制外圆context.arc(100, 100, 99, 0, 2 * Math.PI, false);// 绘制内圆context.moveTo(194, 100);context.arc(100, 100, 94, 0, 2 * Math.PI, false);// 移动原点到表盘中心context.translate(100, 100);// 绘制分针context.moveTo(0, 0);context.lineTo(0, -85);// 绘制时针context.moveTo(0, 0);context.lineTo(-65, 0);// 描画路径context.stroke();
}
把原点移动到(100, 100),也就是表盘的中心后,要绘制表针只需简单的数学计算即可。这是因为所 有计算都是基于(0, 0),而不是(100, 100)了。当然,也可以使用 rotate()方法来转动表针
let drawing = document.getElementById("drawing");
// 确保浏览器支持<canvas>
if (drawing.getContext) {let context = drawing.getContext("2d");// 创建路径context.beginPath();// 绘制外圆context.arc(100, 100, 99, 0, 2 * Math.PI, false);// 绘制内圆context.moveTo(194, 100);context.arc(100, 100, 94, 0, 2 * Math.PI, false);// 移动原点到表盘中心context.translate(100, 100);// 旋转表针context.rotate(1);// 绘制分针context.moveTo(0, 0);context.lineTo(0, -85);// 绘制时针context.moveTo(0, 0);context.lineTo(-65, 0);// 描画路径context.stroke();
}
context.fillStyle = "#ff0000";
context.save();
context.fillStyle = "#00ff00";
context.translate(100, 100);
context.save();
context.fillStyle = "#0000ff";
context.fillRect(0, 0, 100, 200); // 在(100, 100)绘制蓝色矩形
context.restore();
context.fillRect(10, 10, 100, 200); // 在(100, 100)绘制绿色矩形
context.restore();
context.fillRect(0, 0, 100, 200); // 在(0, 0)绘制红色矩形
以上代码先将 fillStyle 设置为红色,然后调用 save()。接着,将 fillStyle 修改为绿色,坐
6 绘制图像(把现有图像绘制到画布上)
let image = document.images[0];
context.drawImage(image, 10, 10);
context.drawImage(image, 50, 10, 20, 30);
执行之后,图像会缩放到 20 像素宽、30 像素高。
context.drawImage(image, 0, 10, 50, 50, 0, 100, 40, 60);
最终,原始图像中只有一部分会绘制到画布上。这一部分从(0, 10)开始,50 像素宽、50 像素高。而 绘制到画布上时,会从(0, 100)开始,变成 40 像素宽、60 像素高。
7 阴影
shadowColor
shadowOffsetX
shadowOffsetY
shadowBlur
let context = drawing.getContext("2d");
// 设置阴影
context.shadowOffsetX = 5;
context.shadowOffsetY = 5;
context.shadowBlur = 4;
context.shadowColor = "rgba(0, 0, 0, 0.5)";
// 绘制红色矩形
context.fillStyle = "#ff0000";
context.fillRect(10, 10, 50, 50);
// 绘制蓝色矩形
context.fillStyle = "rgba(0,0,255,1)";
context.fillRect(30, 30, 50, 50);
8 渐变
createLinearGradient线性渐变
let gradient = context.createLinearGradient(30, 30, 70, 70);
gradient.addColorStop(0, "white");
gradient.addColorStop(1, "black");
这个 gradient 对象现在表示的就是在画布上从(30, 30)到(70, 70)绘制一个渐变。渐变的起点颜色
// 绘制红色矩形
context.fillStyle = "#ff0000";
context.fillRect(10, 10, 50, 50);
// 绘制渐变矩形
context.fillStyle = gradient;
context.fillRect(30, 30, 50, 50);
context.fillStyle = gradient;
context.fillRect(50, 50, 50, 50);
function createRectLinearGradient(context, x, y, width, height) {return context.createLinearGradient(x, y, x+width, y+height);
}
这个函数会基于起点的 x、y 坐标和传入的宽度、高度创建渐变对象,之后调用 fillRect()方法
let gradient = createRectLinearGradient(context, 30, 30, 50, 50);
gradient.addColorStop(0, "white");
gradient.addColorStop(1, "black");
// 绘制渐变矩形
context.fillStyle = gradient;
context.fillRect(30, 30, 50, 50);
计算坐标是使用画布时重要而复杂的问题。使用类似 createRectLinearGradient()这样的辅助
createRadialGradient径向渐变
let gradient = context.createRadialGradient(55, 55, 10, 55, 55, 30);
gradient.addColorStop(0, "white");
gradient.addColorStop(1, "black");
// 绘制红色矩形
context.fillStyle = "#ff0000";
context.fillRect(10, 10, 50, 50);
// 绘制渐变矩形
context.fillStyle = gradient;
context.fillRect(30, 30, 50, 50);
9 图案
<body><canvas id="drawing" width="200" height="200">A drawing of something.</canvas><img id="image" src="./img.png" alt="Pattern Image" style="display:none;">
</body>
<script>let drawing = document.getElementById("drawing");let image = document.getElementById("image");// 确保浏览器支持<canvas>if (drawing.getContext) {let context = drawing.getContext("2d");// 等待图片加载完成image.onload = function() {// 创建图案填充let pattern = context.createPattern(image, "repeat");// 绘制矩形context.fillStyle = pattern;context.fillRect(10, 10, 150, 150);};}
</script>

10 图像数据
let imageData = context.getImageData(10, 5, 50, 50);
返回的对象是一个 ImageData 的实例。每个 ImageData 对象都包含 3 个属性:width、height
let data = imageData.data,
red = data[0],
green = data[1],
blue = data[2],
alpha = data[3];
这个数组中的每个值都在 0~255 范围内(包括 0 和 255)。对原始图像数据进行访问可以更灵活地操 作图像。例如,通过更改图像数据可以创建一个简单的灰阶过滤器:
let drawing = document.getElementById("drawing");
// 确保浏览器支持<canvas>
if (drawing.getContext) {
let context = drawing.getContext("2d"),
image = document.images[0],
imageData, data,
i, len, average,
red, green, blue, alpha;
// 绘制图像
context.drawImage(image, 0, 0);
// 取得图像数据
imageData = context.getImageData(0, 0, image.width, image.height);
data = imageData.data;
for (i=0, len=data.length; i < len; i+=4) {
red = data[i];
green = data[i+1];
blue = data[i+2];
alpha = data[i+3];
// 取得 RGB 平均值
average = Math.floor((red + green + blue) / 3);
// 设置颜色,不管透明度
data[i] = average;
data[i+1] = average;
data[i+2] = average;
}
// 将修改后的数据写回 ImageData 并应用到画布上显示出来
imageData.data = data;
context.putImageData(imageData, 0, 0);
}
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Grayscale Image on Canvas</title>
</head><body><canvas id="drawing" width="450" height="450">A drawing of something.</canvas><img id="image" src="https://img0.baidu.com/it/u=2325089072,2338520041&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500" width="450" height="450" alt="Pattern Image">
</body>
<script>// 获取 canvas 元素和上下文const canvas = document.getElementById('drawing');const ctx = canvas.getContext('2d');// 创建一个图像对象const img = new Image();img.crossOrigin = "Anonymous"; // 允许跨域加载img.src = "https://img0.baidu.com/it/u=2325089072,2338520041&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500"; // 请替换为你自己的图片路径// 当图像加载完成后执行img.onload = function() {// 将图像绘制到画布上ctx.drawImage(img, 0, 0);// 获取图像数据const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);const data = imageData.data;// 遍历图像数据并应用灰阶过滤for (let i = 0; i < data.length; i += 4) {const r = data[i]; // 红色const g = data[i + 1]; // 绿色const b = data[i + 2]; // 蓝色// 计算灰阶值(平均值)const gray = (r + g + b) / 3;// 将RGB值设置为灰阶值data[i] = gray; // 红色data[i + 1] = gray; // 绿色data[i + 2] = gray; // 蓝色}// 将修改后的图像数据放回画布ctx.putImageData(imageData, 0, 0);};
</script></html>
这个例子首先在画布上绘制了一个图像,然后又取得了其图像数据。for 循环遍历了图像数据中的
11 合成
globalAlpha 属性
// 绘制红色矩形
context.fillStyle = "#ff0000";
context.fillRect(10, 10, 50, 50);
// 修改全局透明度
context.globalAlpha = 0.5;
// 绘制蓝色矩形
context.fillStyle = "rgba(0,0,255,1)";
context.fillRect(30, 30, 50, 50);
// 重置
context.globalAlpha = 0;
globalCompositionOperation 属性
source-over
source-in
新图形只绘制出与原有图形重叠的部分,画布上其余部分全部透明。
source-out
source-atop
destination-over
destination-in
destination-out
destination-atop
lighter
copy
xor
// 绘制红色矩形
context.fillStyle = "#ff0000";
context.fillRect(10, 10, 50, 50);
// 设置合成方式
context.globalCompositeOperation = "destination-over";
// 绘制蓝色矩形
context.fillStyle = "rgba(0,0,255,1)";
context.fillRect(30, 30, 50, 50);
三、 WebGL
1 WebGL 上下文
let drawing = document.getElementById("drawing");
// 确保浏览器支持<canvas>
if (drawing.getContext) {let gl = drawing.getContext("webgl");if (gl){// 使用 WebGL}
}
这里把 WebGL context 对象命名为 gl。大多数 WebGL 应用和例子遵循这个约定,因为 OpenGL ES 2.0 方法和值通常以"gl"开头。这样可以让 JavaScript 代码看起来更接近 OpenGL 程序。
2 WebGL 基础
let drawing = document.getElementById("drawing");
// 确保浏览器支持<canvas>
if (drawing.getContext) {let gl = drawing.getContext("webgl", { alpha: false });if (gl) {// 使用 WebGL}
}
这些上下文选项大部分适合开发高级功能。多数情况下,默认值就可以满足要求。
Insert IconMargin [download]
let drawing = document.getElementById("drawing"),gl;
// 确保浏览器支持<canvas>
if (drawing.getContext) {try {gl = drawing.getContext("webgl");} catch (ex) {// 什么也不做}if (gl) {// 使用 WebGL} else {alert("WebGL context could not be created.");}
}
1. 常量
2. 方法命名
3. 准备绘图
gl.clearColor(0, 0, 0, 1); // 黑色
gl.clear(gl.COLOR_BUFFER_BIT);
以上代码把清理颜色缓冲区的值设置为黑色,然后调用 clear()方法,这个方法相当于 OpenGL
4. 视口与坐标
gl.viewport(0, 0, drawing.width,
drawing.height);
这个视口的坐标系统与网页中通常的坐标系统不一样。视口的 x 和 y 坐标起点(0, 0)表示<canvas>
// 视口是<canvas> 左下角四分之一区域
gl.viewport(0, 0, drawing.width/2, drawing.height/2);
// 视口是<canvas> 左上角四分之一区域
gl.viewport(0, drawing.height/2, drawing.width/2, drawing.height/2);
// 视口是<canvas> 右下角四分之一区域
gl.viewport(drawing.width/2, 0, drawing.width/2, drawing.height/2);
5. 缓冲区
let buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0, 0.5, 1]), gl.STATIC_DRAW);
调用 gl.bindBuffer()将 buffer 设置为上下文的当前缓冲区。然后,所有缓冲区操作都在 buffer 上直接执行。因此,调用 gl.bufferData()虽然没有包含对 buffer 的直接引用,但仍然是 在它上面执行的。上面最后一行代码使用一个 Float32Array(通常把所有顶点信息保存在 Float32Array 中)初始化了 buffer。如果想输出缓冲区内容,那么可以调用 drawElements()方法 并传入 gl.ELEMENT_ARRAY_BUFFER。
6. 错误
7. 着色器
// OpenGL 着色器语言
// 着色器,摘自 Bartek Drozdz 的文章“Get started with WebGL—draw a square”
attribute vec2 aVertexPosition;
void main() {
gl_Position = vec4(aVertexPosition, 0.0, 1.0);
}
这个顶点着色器定义了一个名为 aVertexPosition 的 attribute。这个 attribute 是一个包含
// OpenGL 着色器语言
// 着色器,摘自 Bartek Drozdz 的文章“Get started with WebGL—draw a square”
uniform vec4 uColor;
void main() {
gl_FragColor = uColor;
}
<script type="x-webgl/x-vertex-shader" id="vertexShader">
attribute vec2 aVertexPosition;
void main() {
gl_Position = vec4(aVertexPosition, 0.0, 1.0);
}
</script>
<script type="x-webgl/x-fragment-shader" id="fragmentShader">
uniform vec4 uColor;
void main() {
gl_FragColor = uColor;
}
</script>
let vertexGlsl = document.getElementById("vertexShader").text,
fragmentGlsl = document.getElementById("fragmentShader").text;
let vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexGlsl);
gl.compileShader(vertexShader);
let fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentGlsl);
gl.compileShader(fragmentShader);
let program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
调用 gl.useProgram()之后,所有后续的绘制操作都会使用这个程序。
let uColor = gl.getUniformLocation(program, "uColor");
gl.uniform4fv(uColor, [0, 0, 0, 1]);
这个例子从 program 中找到 uniform 变量 uColor,然后返回了它的内存位置。第二行代码调用
let aVertexPosition = gl.getAttribLocation(program, "aVertexPosition");
gl.enableVertexAttribArray(aVertexPosition);
gl.vertexAttribPointer(aVertexPosition, itemSize, gl.FLOAT, false, 0, 0);
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(vertexShader));
}
8. 绘图
// 假设已经使用本节前面的着色器清除了视口
// 定义 3 个顶点的 x 坐标和 y 坐标
let vertices = new Float32Array([ 0, 1, 1, -1, -1, -1 ]),
buffer = gl.createBuffer(),
vertexSetSize = 2,
vertexSetCount = vertices.length/vertexSetSize,
uColor,
aVertexPosition;
// 将数据放入缓冲区
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
// 给片段着色器传入颜色
uColor = gl.getUniformLocation(program, "uColor");
gl.uniform4fv(uColor, [ 0, 0, 0, 1 ]);
// 把顶点信息传给着色器
aVertexPosition = gl.getAttribLocation(program, "aVertexPosition");
gl.enableVertexAttribArray(aVertexPosition);
gl.vertexAttribPointer(aVertexPosition, vertexSetSize, gl.FLOAT, false, 0, 0);
// 绘制三角形
gl.drawArrays(gl.TRIANGLES, 0, vertexSetCount);
9. 纹理
let image = new Image(),
texture;
image.src = "smile.gif"; 578 第 18 章 动画与 Canvas 图形
image.onload = function() {texture = gl.createTexture();gl.bindTexture(gl.TEXTURE_2D, texture);gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);// 除当前纹理gl.bindTexture(gl.TEXTURE_2D, null);
}
10. 读取像素
let pixels = new Uint8Array(25*25);
gl.readPixels(0, 0, 25, 25, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
let gl = drawing.getContext("webgl", { preserveDrawingBuffer: true; });
设置这个标志可以强制帧缓冲区在下一次绘制之前保持上一次绘制的状态。这个选项可能会影响性
3 WebGL1 与 WebGL2
let ext = gl.getExtension('WEBGL_draw_buffers');
if (!ext) {// 没有扩展的代码
} else {ext.drawBuffersWEBGL([...])
}
四、小结
相关文章:
canvas(填充描边,绘制矩形、路径、文本、图像,变换,阴影,渐变等)
一、 基本的画布功能 创建 <canvas> 元素时至少要设置其 width 和 height 属性,这样才能告诉浏览器在多大面积上绘 图。出现在开始和结束标签之间的内容是后备数据,会在浏览器不支持 <canvas> 元素时显示。比如: <canv…...
STM8单片机学习笔记·GPIO的片上外设寄存器
目录 前言 IC基本定义 三极管基础知识 单片机引脚电路作用 STM8GPIO工作模式 GPIO外设寄存器 寄存器含义用法 CR1:Control Register 1 CR2:Control Register 2 ODR:Output Data Register IDR:Input Data Register 赋值…...
2-2-18-16 QNX系统架构之自适应分区
阅读前言 本文以QNX系统官方的文档英文原版资料为参考,翻译和逐句校对后,对QNX操作系统的相关概念进行了深度整理,旨在帮助想要了解QNX的读者及开发者可以快速阅读,而不必查看晦涩难懂的英文原文,这些文章将会作为一个…...
【Python网络爬虫笔记】11- Xpath精准定位元素
目录 一、Xpath 在 Python 网络爬虫中的作用(一)精准定位元素(二)应对动态网页(三)数据结构化提取 二、Xpath 的常用方法(一)节点选取(二)谓词筛选࿰…...
Rustdesk 安装客户端以及自己搭建服务器跑通参考资料
Rustdesk 安装客户端以及自己搭建服务器跑通参考资料 下载客户端: rustdesk客户端-github下载地址 windows正常安装就行了,ubuntu安装参考下面: ubuntu安装rustdesk客户端 在centos中利用docker安装rustdesk-server,先进行cento…...
源码编译jdk7 超详细教程 openjdk7
关于源代码 当前的openJDK的源代码已经被发布到了github上了,所以我们可以直接从github上下载到。 OpenJDK7u源码托管地址:https://github.com/openjdk/jdk7u 带后缀U的地址,或者发行的jdk包,表示当前版本下的持续跟新版。而他…...
如何实现日期选择窗口
文章目录 1 概念介绍2 使用方法3 示例代码我们在上一章回中介绍了TimePicker Widget相关的内容,本章回中将介绍DatePickerDialog Widget.闲话休提,让我们一起Talk Flutter吧。 1 概念介绍 我们在这里说的DatePickerDialog是一种弹出窗口,只不过窗口的内容固定显示为日期,它…...
Spring Security 6 系列之一 - 开篇入门
之所以想写这一系列,是因为之前工作过程中使用Spring Security,但当时基于spring-boot 2.3.x,其默认的Spring Security是5.3.x。之后新项目升级到了spring-boot 3.3.0,结果一看Spring Security也升级为6.3.0,关键是其风…...
Spring Cloud概述
1. 认识微服务 1.1 单体架构 很多创业公司早期或者传统企业会把业务的所有功能实现都打包在⼀个项⽬, 这就是单体架构. 业务的所有功能实现都打包在⼀个war包或者Jar包中, 这种⽅式就称为单体架构. 举个例子: 电商系统包括: ⽤⼾管理, 商品管理, 订单管理, ⽀付管理, 库存…...
mvc如何给action传递参数
步骤(常规方法) 新建一个控制器--LarsController.cs using Microsoft.AspNetCore.Mvc; namespace Blog.Controller; public class LarsController:Controller -----继承 {public IActionResult Index(){return View();} }获取id // program.cs中默认值是idpublic IAction…...
【银河麒麟高级服务器操作系统】有关dd及cp测试差异的现象分析详解
了解更多银河麒麟操作系统全新产品,请点击访问 麒麟软件产品专区:https://product.kylinos.cn 开发者专区:https://developer.kylinos.cn 文档中心:https://documentkylinos.cn dd现象 使用银河麒麟高级服务器操作系统执行两次…...
视频智能分析平台LiteAIServer未戴安全帽检测算法助力矿山安全:精准监督矿工佩戴安全帽情况
矿山作业环境复杂多变,安全隐患层出不穷。其中,矿工未佩戴安全帽这一行为,看似微不足道,实则潜藏着巨大的安全风险。一旦发生事故,未佩戴安全帽的矿工将极易受到重创,甚至危及生命。因此,确保每…...
整数的四舍五入----->记录每一点进步
我们知道整数类型的变量对小数部分都不感冒,只要是小数都会舍去,都让他舍去了我们还讲个P,所以接下来就是告诉你怎么不让他全都舍去。 先来试想一下如果这个数字是3.4,存到整数型变量里面是不是直接变成了3,那么我要是…...
Linux栈帧
相关寄存器&指令 寄存器 rax(accumulator):return value rbx(base) rcx(count):4st argument rdx(data):3st argument rsi(sour…...
【代码随想录day59】【C++复健】 47. 参加科学大会(dijkstra(堆优化版)精讲 );94. 城市间货物运输 I
前几天有些事情耽搁了,不过好在图论我完全不会,所以偷看代码思路也没有任何的心理负担,做起来反而相对独立思考更快一点点。 47. 参加科学大会(dijkstra(堆优化版)精讲 ) 本来一开始以为这个堆…...
【网络安全】WIFI WPA/WPA2协议:深入解析与实践
WIFI WPA/WPA2协议:深入解析与实践 1. WPA/WPA2 协议 1.1 监听 Wi-Fi 流量 解析 WPA/WPA2 的第一步是监听 Wi-Fi 流量,捕获设备与接入点之间的 4 次握手数据。然而,设备通常不会频繁连接或重新连接,为了加速过程,攻…...
穷举vs暴搜vs深搜vs回溯vs剪枝专题一>子集
题目: 两个方法本质就是决策树的画法不同 方法一解析: 代码: class Solution {private List<List<Integer>> ret;//返回结果private List<Integer> path;//记录路径,注意返回现场public List<List<Int…...
试题转excel;word转excel;大风车excel
一、问题描述 一名教师朋友,偶尔会需要整理一些高质量的题目到excel中 以往都是手动复制搬运,几百道题几乎需要一个下午的时间 关键这些事,枯燥无聊费眼睛,实在是看起来就很蠢的工作 就想着做一个工具,可以自动处理…...
Unity NTPComponent应用, 实现一个无后端高效获取网络时间的组件
无后端高效获取网络时间的组件 废话不多说,直接上源码m_NowSerivceTime 一个基于你发行游戏地区的时间偏移, 比如北京时区就是 8, 巴西就是-3,美国就是-5using Newtonsoft.Json; 如果这里报错, 就说明项目没有 NewtonsoftJson插件…...
复合机器人为生产提供精准的建议和决策支持
在现代化生产的浪潮中,智能复合机器人以其卓越的性能和高度智能化特点,正成为保障生产安全与可靠性的重要力量。 智能复合机器人具备精确的感知、判断和决策能力,能够在复杂的生产环境中自主导航、精确操作,避免了人为因素可能导致…...
springboot/ssm二手儿童绘本交易系统Java代码编写web项目闲置书籍源码
springboot/ssm二手儿童绘本交易系统Java代码编写web项目闲置书籍源码 基于springboot(可改ssm)vue项目 开发语言:Java package com.controller;import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.Map;import javax.s…...
30. Three.js案例-绘制并渲染圆弧
30. Three.js案例-绘制并渲染圆弧 实现效果 知识点 WebGLRenderer WebGLRenderer 是 Three.js 中用于渲染 3D 场景的核心类。它利用 WebGL 技术在浏览器中渲染 3D 图形。 构造器 new THREE.WebGLRenderer(parameters) 参数类型描述parametersObject可选参数对象ÿ…...
类和对象(2)
大家好,今天我们继续来学习类和对象的知识,那么今天我们来看看类的概念和类的定义相关的知识,那么话不多说,我们直接开始。 2.类定义和使用 面向对象程序设计关注的是对象,而对象是现实生活中的实体,比如:洗衣机,但是…...
240004基于ssm+maven+mysql+Java的房屋租赁系统的设计与实现
基于ssmmavenmysql的房屋租赁系统的设计与实现 1.项目描述2.运行环境3.项目截图4.源码获取 1.项目描述 该项目在原有的基础上进行了优化,包括新增了注册功能,房屋模糊查询功能,管理员和用户信息管理等功能,以及对网站界面进行了优…...
HTTP、WebSocket、gRPC 或 WebRTC:各种协议的区别
在为您的应用程序选择通信协议时,有很多不同的选择。 本文将了解四种流行的解决方案:HTTP、WebSocket、gRPC 和 WebRTC。 我们将通过深入学习其背后原理、最佳用途及其优缺点来探索每个协议。 通信方式在不断改进:变得更快、更方便、更可靠&…...
FlowNex 中的两相建模基础知识
通过 FlowNex 中的两相建模解开高效流体动力学的秘密,彻底改变制造业。 挑战 两相流是指两个不同相(通常是液体和气体)同时流动,它们具有不同的特性和行为。在制造业中,了解两相流对于优化热交换器、化学反应器和流体…...
Mysql笔记
windows安装记录Windows中Mysql安装-CSDN博客 用到的库 通过网盘分享的文件:atguigudb.sql 链接: https://pan.baidu.com/s/1YfC20c2vK9odn-XRJJwUJw 提取码: utk7 --来自百度网盘超级会员v5的分享 Mysql4中表关联关系 1.1对1,比较少用,因为完全可以一张表,当有…...
docker拉取rabbitmq镜像安装延迟队列插件
我这里使用的是rabbitmq:3.12.0-management版本作为示例 1.拉取rabbitmq镜像 docker pull rabbitmq:3.12.0-management 2.启动rabbitmq docker run -d --namerabbitmq --restartalways -p 5672:5672 -p 15672:15672 rabbitmq:3.12.0-management 在咱们拉取时如果出现连接超时可…...
创建一个谷歌插件项目dome上线流程+源码
创建一个简单的 Chrome 扩展程序,其主要功能是 JSON 格式化。用户可以通过点击扩展图标打开一个弹出窗口,在弹出窗口中输入或粘贴 JSON 数据,然后点击格式化按钮来格式化 JSON 数据 谷歌插件(即 Chrome 扩展程序)主要设…...
举例说明如何在linux下检测摄像头设备具备的功能
假设摄像头设备文件为/dev/video1 ,下面是一个专门用于检测 /dev/video1 设备能力的简化程序。这个程序将打印出设备的所有能力、格式和其他相关信息,以帮助你了解设备支持的功能。 检测 /dev/video1 设备能力的程序 #include <fcntl.h> #includ…...
win10配置子系统Ubuntu子系统(无需通过Windows应用市场)实际操作记录
win10配置子系统Ubuntu子系统(无需通过Windows应用市场)实际操作记录 参考教程 : win10配置子系统Ubuntu子系统(无需通过Windows应用市场) - 一佳一 - 博客园 开启虚拟机服务的 以管理员方式运行PowerShell运行命令。 …...
东北大学《2024年839自动控制原理真题》 (完整版)
本文内容,全部选自自动化考研联盟的:《东北大学839自控考研资料》的真题篇。后续会持续更新更多学校,更多年份的真题,记得关注哦~ 目录 2024年真题 Part1:2024年完整版真题 2024年真题...
5G中的ATG Band
Air to Ground Networks for NR是R18 NR引入的。ATG很多部分和NTN类似中的内容类似。比较明显不同的是,NTN的RF内容有TS 38.101-5单独去讲,而ATG则会和地面网络共用某些band,这部分在38.101-1中有描述。 所以会存在ATG与地面网络之间的相邻信…...
nginx负载均衡配置
目录 一、简介 二、nginx下载 二、nginx配置 四、注意点 (1)/api与/api/的区别 (2)http://gatewayserver与http://gatewayserver/的区别 一、简介 Nginx(发音为 "engine-x")是一个高性能的HTTP和反向代理服务器,也是一个IMA…...
【教学类-83-02】20241214立体书三角嘴2.0——青蛙(扁菱形嘴)
背景需求: 制作小鸡立体贺卡三角嘴,它的嘴是正菱形(四条边长度相等,类似正方形) 【教学类-83-01】20241215立体书三角嘴1.0——小鸡(正菱形嘴)-CSDN博客文章浏览阅读744次,点赞22次…...
vscode设置终端代理
转载请标明出处:小帆的帆的博客 设置终端代理 修改项目的.vscode/settings.json {"terminal.integrated.env.windows": {"http_proxy": "http://127.0.0.1:7890","https_proxy": "http://127.0.0.1:7890"}, }…...
【C++】函数计算题解论
博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 💯前言💯题目描述💯思路解析3.1 函数的递归定义3.2 边界条件控制3.3 记忆化搜索 💯C实现代码💯添加解释💯小结 💯前言 在…...
Redis篇-21--运维篇3-集群(分片,水平扩展,高可用,集群配置案例,扩展哨兵案例)
1、概述 Redis集群(Cluster)通过分片(sharding)实现了水平扩展,允许数据分布在多个节点上,从而提升性能和存储容量。 在Redis集群中,数据被分割成16384个哈希槽(hash slots&#x…...
Unity3d场景童话梦幻卡通Q版城镇建筑植物山石3D模型游戏美术素材
注明:网络素材,仅供学习使用! https://download.csdn.net/download/elineSea/90017291...
深入理解addEventListener中的第二个参数:listener
起因 首先,之前留给我们的一点东西,js的深入内容关键在addEventListener,这个函数中的参数,它们三个参数,分别为type、listener、options,当然在这里还有一些小的问题,比如mdn文档中它介绍到了另…...
数据库镜像(Database Mirroring):高可用性与灾难恢复技术
一、引言 在现代信息系统中,数据的可用性和完整性至关重要,尤其是对金融、电商、医疗等高并发和高可靠性要求的行业。数据库镜像(Database Mirroring) 作为一种高可用性与灾难恢复技术,通过将主数据库的数据实时复制到…...
【Qt】按钮类控件:QPushButton、QRadioButton、QCheckBox、ToolButton
目录 QPushButton 例子: QRadioButton 例子: 按钮的常见信号函数 单选按钮分组 例子: QCheckButton 例子: QToolButton QWidget的常见属性及其功能对于它的派生类控件都是有效的(也就是Qt中的各种控件),包括…...
day-21 内核链表以及栈
1.昨日作业 1.删除指定节点 找到删除就完事了,双向可以停在删除处。 /***************************** 功能:删除指定结点(通过姓名)* 参数:phead;oldname; * 返回:成功0,失-1&…...
深度与视差的关系及其转换
深度与视差的关系及其转换 在计算机视觉和立体视觉中,深度和视差是两个重要的概念。理解这两者之间的关系对于实现立体图像处理、三维重建以及深度估计至关重要。在这篇博客中,我们将深入探讨深度和视差的概念,并介绍它们之间的转换关系。 …...
Unity全局光照详解
之前就学过但是太久没用又忘了,因此用最简洁易懂的语言做个记录。 全局光照分为两个系统,分别是实时光照和混合光照。(点击window/Rendering/Lighing打开此面板) 其中全局光照对于我来说都是新技术了,上一次学…...
外观模式的理解和实践
外观模式(Facade Pattern)是一种常用的软件设计模式,它提供了一个统一的接口,用来访问子系统中的一群接口。该模式定义了一个高层的接口,使得子系统更容易使用。简单来说,外观模式就是通过引入一个外观角色…...
【前端知识】Javascript进阶-类和继承
文章目录 概述一、类(Class)二、继承(Inheritance) 三、继承的实现方式作用一、类和作用二、继承和作用 概述 当然可以,以下是对JavaScript中类和继承的详细介绍: 一、类(Class) 定…...
Kylin麒麟操作系统 | Nginx服务部署
目录 一、理论储备1. Nginx概述2. Nginx与Apache的区别3. Nginx的服务配置 二、任务实施任务1 Nginx的编译安装1. Server配置2. 客户端测试 任务2 Nginx反向代理1. Server1配置2. Server2配置3. 客户端测试 一、理论储备 1. Nginx概述 Nginx是一个轻量级的web服务器ÿ…...
51单片机--- 串口控制仿真
51单片机--- 串口控制仿真 实验目标:51单片机接收串口数据,根据数据点亮LED。 实验步骤: 在Proteus里画出原理图 在Keil里用C语言编写程序 在Proteus中导入HEX文件,启动仿真 实验协议: 波特率115200 数据位:8位,停止位:1位,校验位:无。 命令格式: 一条命令为…...
<数据集>输电线塔杂物识别数据集<目标检测>
数据集下载链接 <数据集>输电线塔杂物识别数据集<目标检测>https://download.csdn.net/download/qq_53332949/90141102数据集格式:VOCYOLO格式 图片数量:1099张 标注数量(xml文件个数):1099 …...