前端 | (十四)canvas基本用法 | 尚硅谷前端HTML5教程(html5入门经典)

news2024/11/27 0:28:44

文章目录

  • 📚canvas基本用法
    • 🐇什么是canvas(画布)
    • 🐇替换内容
    • 🐇canvas标签的两个属性
    • 🐇渲染上下文
  • 📚绘制矩形
    • 🐇绘制矩形
    • 🐇strokeRect时,边框像素渲染问题
    • 🐇添加样式和颜色
    • 🐇lineJoin
  • 📚绘制路径
    • 🐇canvas绘制路径
    • 🐇lineCap
    • 🐇save
    • 🐇restore
    • 🔥电子签名实例
  • 📚绘制曲线
    • 🐇canvas绘制圆形
    • 🐇arcTo
    • 🐇二次贝塞尔
    • 🐇三次贝塞尔
  • 📚canvas中的变换
    • 🐇translate(x, y)
    • 🐇rotate(angle)
    • 🐇scale(x, y)
    • 🔥放缩变换实例
    • 🔥画一个电子钟表
  • 📚图片
    • 🐇插入图片(需要image对象)
    • 🐇设置背景(需要image对象)
    • 🐇渐变
    • 🔥图片变动画
  • 📚文本
    • 🐇绘制文本
    • 🐇文本样式
    • 🐇阴影(文本阴影&盒模型阴影)
  • 📚像素操作
    • 🐇得到像素数据
    • 🔥马赛克实例
  • 📚合成
    • 🐇全局透明度的设置
    • 🐇合成
    • 🔥刮刮卡实例

  • 前端 | ( 十)HTML5简介及相关新增属性
  • 尚硅谷前端HTML5教程(html5入门经典)

📚canvas基本用法

🐇什么是canvas(画布)

  • <canvas> 是 HTML5 新增的元素,可用于通过使用JavaScript中的脚本来绘制图形。例如,它可以用于绘制图形,创建动画。<canvas> 最早由Apple引入WebKit。
  • 我们可以使用<canvas>标签来定义一个canvas元素
  • 使用<canvas>标签时,建议要成对出现,不要使用闭合的形式。
  • canvas元素默认具有高宽:width: 300pxheight:150px

🐇替换内容

  • <canvas>很容易定义一些替代内容。由于某些较老的浏览器(尤其是IE9之前的IE浏览器)不支持HTML元素"canvas",但在这些浏览器上你应该要给用户展示些替代内容。
  • 我们只需要在<canvas>标签中提供替换内容就可以。
  • 支持<canvas>的浏览器将会忽略在容器中包含的内容,并且只是正常渲染canvas。不支持<canvas>的浏览器会显示代替内容。
    <!-- 如果浏览器不支持​<canvas>元素,那么它会显示"您的浏览器不支持画布元素 请您换成萌萌的谷歌"。 -->
    <canvas id="test" width="300" height="300">
    	<span>您的浏览器不支持画布元素 请您换成可爱的谷歌</span>
    </canvas>
    

🐇canvas标签的两个属性

  • <canvas> 看起来和 元素很相像,唯一的不同就是它并没有 src 和 alt 属性。
  • 实际上,<canvas> 标签只有两个属性—— width和height。这些都是可选的。
  • 当没有设置宽度和高度的时候,canvas会初始化宽度为300像素和高度为150像素。
  • 画布的高宽
    • html属性设置width height时只影响画布本身不影画布内容。
    • css属性设置width height时不但会影响画布本身的高宽,还会使画布中的内容等比例缩放(缩放参照于画布默认的尺寸)。

🐇渲染上下文

  • <canvas> 元素只是创造了一个固定大小的画布,要想在它上面去绘制内容,我们需要找到它的渲染上下文。
  • <canvas> 元素有一个叫做 getContext() 的方法,这个方法是用来获得渲染上下文和它的绘画功能。getContext()只有一个参数:上下文的格式
  • 获取方式
    var canvas = document.getElementById('box');
    var ctx = canvas.getContext('2d');
    
  • 检查支持性
    var canvas = document.getElementById('tutorial');
    if (canvas.getContext){
    	var ctx = canvas.getContext('2d');
    } 
    

📚绘制矩形

🐇绘制矩形

  • canvas提供了三种方法绘制矩形:
    • 绘制一个填充的矩形(填充色默认为黑色):fillRect(x, y, width, height)
    • 绘制一个矩形的边框(默认边框为:一像素实心黑色):strokeRect(x, y, width, height)
    • 清除指定矩形区域,让清除部分完全透明:clearRect(x, y, width, height)
  • x与y指定了在canvas画布上所绘制的矩形的左上角(相对于原点)的坐标。
  • width和height设置矩形的尺寸(存在边框的话,边框会在width上占据一个边框的宽度,height同理)。
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style type="text/css">
			*{
				margin: 0;
				padding: 0;
			}
			html,body{
				height: 100%;
				overflow: hidden;
			}
			body{
				background: pink;
			}
			#test{
				background: gray;
				position: absolute;
				left: 0;
				top: 0;
				right: 0;
				bottom: 0;
				margin: auto;
			}
		</style>
	</head>
	<body>
		<canvas id="test" width="300" height="300">
			<span>您的浏览器不支持画布元素 请您换成可爱的谷歌</span>
		</canvas>
	</body>
	<script type="text/javascript">
		window.onload=function(){
			//拿到画布
			var canvas = document.querySelector("#test");
			if(canvas.getContext){
				var ctx = canvas.getContext("2d");
				//注意不加单位,填充的矩形
				ctx.fillRect(0,0,100,100)
				//带边框的矩形  
				ctx.strokeRect(100.5,100.5,100,100)
				// 清除指定矩形区域,让清除部分完全透明
				// ctx.clearRect(0,0,100,100)
			}
		}
	</script>
</html>

在这里插入图片描述

🐇strokeRect时,边框像素渲染问题

  • 按理渲染出的边框应该是1px的,canvas在渲染矩形边框时,边框宽度是平均分在偏移位置的两侧。
  • context.strokeRect(10,10,50,50):边框会渲染在10.5 和 9.5之间,浏览器是不会让一个像素只用自己的一半的,相当于边框会渲染在9到11之间。
  • context.strokeRect(10.5,10.5,50,50):边框会渲染在10到11之间。

🐇添加样式和颜色

  • fillStyle:设置图形的填充颜色。
  • strokeStyle:设置图形轮廓的颜色。
    • 默认情况下,线条和填充颜色都是黑色(CSS 颜色值 #000000)
  • lineWidth:这个属性设置当前绘线的粗细。属性值必须为正数。描述线段宽度的数字。 0、 负数、 Infinity 和 NaN 会被忽略。默认值是1.0。

🐇lineJoin

  • 设定线条与线条间接合处的样式(默认是 miter)

    • round : 圆角
    • bevel : 斜角
    • miter : 直角
    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="UTF-8">
    		<title></title>
    		<style type="text/css">
    			*{
    				margin: 0;
    				padding: 0;
    			}
    			html,body{
    				height: 100%;
    				overflow: hidden;
    			}
    			body{
    				background: pink;
    			}
    			#test{
    				background: gray;
    				position: absolute;
    				left: 0;
    				top: 0;
    				right: 0;
    				bottom: 0;
    				margin: auto;
    			}
    		</style>
    	</head>
    	<body>
    		<canvas id="test" width="300" height="300">
    			<span>您的浏览器不支持画布元素 请您换成可爱的谷歌</span>
    		</canvas>
    	</body>
    	<script type="text/javascript">
    		window.onload=function(){
    			//拿到画布
    			var canvas = document.querySelector("#test");
    			if(canvas.getContext){
    				var ctx = canvas.getContext("2d");
    				// 设置图形的填充颜色
    				ctx.fillStyle="deeppink";
    				// 设置图形轮廓的颜色
    				ctx.strokeStyle="pink";
    				// 当前绘线的粗细
    				ctx.lineWidth=25;
    				// 设定线条与线条间接合处的样式
    				ctx.lineJoin="round";
    				ctx.strokeRect(100,100,100,100)
    				ctx.fillRect(0,0,100,100)
                    //ctx.clearRect(100,100,100,100)
    			}
    		}
    	</script>
    </html>
    

在这里插入图片描述


  • rect画矩形
    var canvas = document.querySelector("#test");
    if(canvas.getContext){
    	var ctx = canvas.getContext("2d");
    	ctx.rect(50,50,100,100);
    	ctx.fillStyle="skyblue";
    	ctx.strokeStyle="black";
    	ctx.fill();
    	ctx.stroke();
    }
    

在这里插入图片描述

📚绘制路径

🐇canvas绘制路径

图形的基本元素是路径。路径是通过不同颜色和宽度的线段或曲线相连形成的不同形状的点的集合。

  • 首先,创建路径起始点

    • beginPath():新建一条路径,生成之后,图形绘制命令被指向到路径上准备生成路径。
      • 本质上,路径是由很多子路径构成,这些子路径都是在一个列表中,所有的子路径(线、弧形、等等)构成图形。
      • 而每次这个方法调用之后,列表清空重置,然后我们就可以重新绘制新的图形。
  • 使用画图命令去画出路径

    • moveTo(x, y)
      • 将笔触移动到指定的坐标x以及y上
      • 当canvas初始化或者beginPath()调用后,你通常会使用moveTo()函数设置起点
    • lineTo(x, y)
      • 将笔触移动到指定的坐标x以及y上
      • 绘制一条从当前位置到指定x以及y位置的直线。
  • 之后你把路径封闭

    • closePath()
      • 闭合路径之后图形绘制命令又重新指向到上下文中。
      • 闭合路径closePath(),不是必需的。这个方法会通过绘制一条从当前点到开始点的直线来闭合图形。
      • 如果图形是已经闭合了的,即当前点为开始点,该函数什么也不做。当你调用fill()函数时,所有没有闭合的形状都会自动闭合,所以你不需要调用closePath()函数。但是调用stroke()时不会自动闭合。
      • stroke():通过线条来绘制图形轮廓。不会自动调用closePath()。
      • fill():通过填充路径的内容区域生成实心的图形。自动调用closePath()。
  • 一旦路径生成,你就能通过描边或填充路径区域来渲染图形。

    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="UTF-8">
    		<title></title>
    		<style type="text/css">
    			*{
    				margin: 0;
    				padding: 0;
    			}
    			html,body{
    				height: 100%;
    				overflow: hidden;
    			}
    			body{
    				background: pink;
    			}
    			#test{
    				background: gray;
    				position: absolute;
    				left: 0;
    				top: 0;
    				right: 0;
    				bottom: 0;
    				margin: auto;
    			}
    		</style>
    	</head>
    	<body>
    		<canvas id="test" width="300" height="300">
    			<span>您的浏览器不支持画布元素 请您换成可爱的谷歌</span>
    		</canvas>
    	</body>
    	<script type="text/javascript">
    		window.onload=function(){
    			var canvas = document.querySelector("#test");
    			if(canvas.getContext){
    				var ctx = canvas.getContext("2d");
    				ctx.strokeStyle="deeppink";
    				ctx.lineWidth=10;
    				ctx.moveTo(100,100);
    				ctx.lineTo(100,200);
    				ctx.lineTo(200,200);
    				ctx.closePath();
    				ctx.stroke();
    				//fill方法会自动合并路径
    				ctx.fill();
    			}
    		}
    	</script>
    </html>
    

在这里插入图片描述

🐇lineCap

  • lineCap 是 Canvas 2D API 指定如何绘制每一条线段末端的属性。有3个可能的值,分别是:
    • butt:线段末端以方形结束。
    • round:线段末端以圆形结束
    • square:线段末端以方形结束,但是增加了一个宽度和线段相同,高度是线段厚度一半的矩形区域
    • 默认值是 butt。
    var canvas = document.querySelector("#test");
    if(canvas.getContext){
    	var ctx = canvas.getContext("2d");
    	ctx.strokeStyle="pink";
    	ctx.lineWidth=10;
    	ctx.lineCap="round";	
    	ctx.moveTo(100,100);
    	ctx.lineTo(100,200);
    	ctx.stroke();
    }
    

在这里插入图片描述

🐇save

  • save() 是 Canvas 2D API 通过将当前状态放入栈中,保存 canvas 全部状态的方法。保存到栈中的绘制状态有下面部分组成:
    • 当前的变换矩阵。
    • 当前的剪切区域。
    • 当前的虚线列表。
    • 以下属性当前的值: strokeStyle, fillStyle, lineWidth, lineCap, lineJoin…

🐇restore

  • restore() 是 Canvas 2D API 通过在绘图状态栈中弹出顶端的状态,将 canvas 恢复到最近的保存状态的方法。

  • 如果没有保存状态,此方法不做任何改变。

    var canvas = document.querySelector("#test");
    if(canvas.getContext){
    	var ctx = canvas.getContext("2d");
    	ctx.save();
    	ctx.fillStyle="pink";
    	ctx.save();
    	// 没保存的不入栈
    	ctx.fillStyle="deeppink";
    	ctx.fillStyle="blue";
    	ctx.save();
    	ctx.fillStyle="red";
    	ctx.save();
    	ctx.fillStyle="green";
    	ctx.save();
    	ctx.beginPath();
    	// 弹出,restore四个是pink,三个是blue,二个是red,一个是green
    	ctx.restore();
    	ctx.restore();
    	ctx.restore();
    	ctx.restore();
    	ctx.fillRect(50,50,100,100);
    }
    

在这里插入图片描述


🔥电子签名实例

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style type="text/css">
			*{
				margin: 0;
				padding: 0;
			}
			body{
				background: #dbd0ff;
			}
			#test{
				position: absolute;
				left: 0;
				right: 0;
				top: 0;
				bottom: 0;
				margin: auto;
				background:white;
			}
		</style>
	</head>
	<body>
		<canvas id="test" width="500" height="500"></canvas>
	</body>
	<script type="text/javascript">
		window.onload=function(){
			var canvas =document.getElementById("test");
			if(canvas.getContext){
				var ctx = canvas.getContext("2d");
			}
			// 在鼠标按下时触发事件
			canvas.onmousedown=function(ev){
				// 获取事件对象
				ev = ev || window.event;
				if(canvas.setCapture){
					// 设置鼠标捕获,确保鼠标事件在元素上持续触发
					canvas.setCapture();
				}
				ctx.beginPath();
				// ev.clientX表示鼠标相对于文档可视区域的水平坐标,canvas.offsetLeft表示画布相对于文档可视区域的水平偏移量
				ctx.moveTo(ev.clientX -canvas.offsetLeft,ev.clientY -canvas.offsetTop);
				document.onmousemove=function(ev){
					// 在整个文档区域内移动鼠标时触发事件
					// 保存画布当前的状态
					ctx.save();
					ctx.strokeStyle="black";
					ev = ev || event;
					// 创建从当前点到指定点的线段,即绘制直线
					ctx.lineTo(ev.clientX -canvas.offsetLeft,ev.clientY -canvas.offsetTop);
					// 绘制已定义的路径
					ctx.stroke();
					ctx.restore();
				}
				// 释放鼠标捕获
				document.onmouseup=function(){
					document.onmousemove=document.onmouseup=null;
					if(document.releaseCapture){
						document.releaseCapture();
					}
				}
				return false;
			}
		}
	</script>
</html>

在这里插入图片描述

📚绘制曲线

  • 角度与弧度的js表达式:radians=(Math.PI/180)*degrees

🐇canvas绘制圆形

  • arc(x, y, radius, startAngle, endAngle, anticlockwise)
    • 画一个以(x,y)为圆心的以radius为半径的圆弧(圆),从startAngle开始到endAngle结束,按照anticlockwise给定的方向(默认为顺时针)来生成。ture:逆时针,false:顺时针
    • x,y为绘制圆弧所在圆上的圆心坐标,radius为半径
    • startAngle以及endAngle参数用弧度定义了开始以及结束的弧度。这些都是以x轴为基准参数anticlockwise 为一个布尔值。为true时,是逆时针方向,否则顺时针方向。
    var canvas = document.querySelector("#test");
    if(canvas.getContext){
    	var ctx = canvas.getContext("2d");
    	ctx.beginPath();
    	ctx.moveTo(100,100);
    	ctx.arc(100,100,50,0,90*Math.PI/180,true);
    	ctx.closePath();
    	ctx.stroke();
    }
    

在这里插入图片描述

🐇arcTo

  • arcTo(x1, y1, x2, y2, radius),根据给定的控制点和半径画一段圆弧。

  • 相当于指定了起点和终点的切线(就是下边示例中,画出的直线就是在画弧线时的切线)

    var canvas = document.querySelector("#test");
    if(canvas.getContext){
    	var ctx = canvas.getContext("2d");
    	ctx.strokeStyle="purple";
    	ctx.beginPath();
    	ctx.moveTo(50,50);
    	ctx.lineTo(300,0);
    	ctx.lineTo(200,200);
    	ctx.stroke();
    	
    	ctx.beginPath();
    	ctx.moveTo(50,50)
    	ctx.arcTo(300,0,200,200,50);
    	ctx.stroke();
    }
    

在这里插入图片描述

🐇二次贝塞尔

  • quadraticCurveTo(cp1x, cp1y, x, y)
    • 绘制二次贝塞尔曲线,cp1x,cp1y为一个控制点,x,y为结束点。
    • 起始点为moveto时指定的点。
    var ctx = canvas.getContext("2d");
    ctx.strokeStyle="purple";
    ctx.beginPath();
    ctx.moveTo(50,50);
    ctx.lineTo(300,0);
    ctx.lineTo(200,200);
    ctx.stroke();
    
    ctx.beginPath();
    ctx.moveTo(50,50)
    ctx.quadraticCurveTo(300,0,200,200);
    ctx.stroke();
    

在这里插入图片描述

🐇三次贝塞尔

  • bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)
    • 绘制三次贝塞尔曲线,cp1x,cp1y为控制点一,cp2x,cp2y为控制点二,x,y为结束点。
    • 起始点为moveto时指定的点。
    var canvas = document.querySelector("#test");
    if(canvas.getContext){
    	var ctx = canvas.getContext("2d");
    	ctx.beginPath();
    	ctx.moveTo(50,50);
    	ctx.lineTo(300,0);
    	ctx.lineTo(0,300);
    	ctx.lineTo(300,300);
    	ctx.stroke();
    	
    	ctx.strokeStyle="purple";
    	ctx.beginPath();
    	ctx.moveTo(50,50)
    	ctx.bezierCurveTo(300,0,0,300,300,300);
    	ctx.stroke();
    }
    

在这里插入图片描述

📚canvas中的变换

🐇translate(x, y)

  • 我们先介绍 translate 方法,它用来移动 canvas的原点到一个不同的位置。
  • translate 方法接受两个参数。x 是左右偏移量,y 是上下偏移量,在 canvas中translate是累加的。
    var canvas = document.querySelector("#test");
    if(canvas.getContext){
    	var ctx = canvas.getContext("2d");
    	ctx.translate(100,100)
    	ctx.beginPath();
    	ctx.fillStyle="skyblue";
    	ctx.fillRect(0,0,100,100);
    }
    

在这里插入图片描述

🐇rotate(angle)

  • 这个方法只接受一个参数:旋转的角度(angle),它是顺时针方向的,以弧度为单位的值。
  • 旋转的中心点始终是 canvas 的原点,如果要改变它,我们需要用到 translate 方法,在canvas中rotate是累加的。
    var canvas = document.querySelector("#test");
    if(canvas.getContext){
    	var ctx = canvas.getContext("2d");
    	ctx.translate(70,70)
    	ctx.rotate(22.1*Math.PI/180)
    	ctx.rotate(22.9*Math.PI/180)
    	ctx.beginPath();
    	ctx.fillStyle="skyblue";
    	ctx.fillRect(50,50,100,100);
    }
    

在这里插入图片描述

🐇scale(x, y)

  • scale 方法接受两个参数。x,y 分别是横轴和纵轴的缩放因子,它们都必须是正值。

  • 值比 1.0 小表示缩小,比 1.0 大则表示放大,值为 1.0 时什么效果都没有。

  • 缩放一般我们用它来增减图形在 canvas 中的像素数目,对形状,位图进行缩小或者放大。

  • 在canvas中scale是累积的。

    var ctx = canvas.getContext("2d");
    ctx.fillStyle="skyblue";
    ctx.beginPath();
    ctx.fillRect(50,50,100,100);
    ctx.beginPath();
    ctx.fillStyle="green";
    ctx.scale(0.5,0.5)
    ctx.fillRect(50,50,100,100);
    ctx.beginPath();
    ctx.fillStyle="yellow";
    // 因为累加,相当于两倍
    ctx.scale(4,4)
    ctx.fillRect(50,50,100,100);
    

在这里插入图片描述

🔥放缩变换实例

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style type="text/css">
			*{
				margin: 0;
				padding: 0;
			}
			html,body{
				height: 100%;
				background-color: #dbdbff;
				overflow: hidden;
			}
			#test{
				background: rgba(143, 143, 253, 0.785);
				position: absolute;
				left: 0;
				top: 0;
				right: 0;
				bottom: 0;
				margin: auto;
			}
		</style>
	</head>
	<body>
		<canvas id="test" width="300" height="300">
			<span>您的浏览器不支持画布元素 请您换成可爱的谷歌</span>
		</canvas>
	</body>
	<script type="text/javascript">
		window.onload=function(){
			var angle =0;//角度
			var scale = 0;//比例
			var angleScale = 0;//状态
			var canvas = document.querySelector("#test");
			if(canvas.getContext){
				var ctx = canvas.getContext("2d");
				ctx.fillStyle="rgba(10, 10, 79, 0.785)";
				ctx.save();
				// 将坐标原点平移到150,150
				ctx.translate(150,150);
				
				ctx.beginPath();
				ctx.fillRect(-50,-50,100,100);
				ctx.restore();
				
				// 设定定时器函数,每隔10毫秒执行一次
				setInterval(function(){
					// 每次执行时,将旋转角度标记加1
					angle++;
					ctx.clearRect(0,0,canvas.width,canvas.height);
					ctx.save();
					ctx.translate(150,150);
					// 旋转
					ctx.rotate(angle*Math.PI/180);
					
					// 0~100之间缩放
					if(scale==100){
						angleScale=-1;
					}else if(scale==0){
						angleScale=1;
					}
					scale+=angleScale;
					// 缩放
					ctx.scale(scale/50,scale/50);
					ctx.beginPath();
					ctx.fillRect(-50,-50,100,100);
					ctx.restore();
				},10)
			}
		}
	</script>
</html>

在这里插入图片描述

🔥画一个电子钟表

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style type="text/css">
			*{
				margin: 0;
				padding: 0;
			}
			html,body{
				height: 100%;
				overflow: hidden;
				background: rgb(197, 197, 255);
			}
			#clock{
				background: rgb(167, 208, 255);
				position: absolute;
				left: 50%;
				top: 50%;
				transform: translate3d(-50%,-50%,0);
			}
		</style>
	</head>
	<body>
		<canvas id="clock" width="400" height="400"></canvas>
	</body>
	<script type="text/javascript">
		window.onload=function(){
	var clock = document.querySelector("#clock"); 
	if(clock.getContext){ 
		var ctx = clock.getContext("2d"); 
		// 定时器函数,每隔1秒执行一次
		setInterval(function(){ 
			// 清除整个画布的内容
			ctx.clearRect(0,0,clock.width,clock.height); 
			// 调用move函数
			move(); 
		},1000);
	
		move(); 
		// move函数,用于绘制时钟
		function move(){ 
			ctx.save(); 
			ctx.lineWidth = 8; 
		  	ctx.strokeStyle = "black"; 
			// 设置线条末端的形状为圆形
		  	ctx.lineCap = "round"; 
            // 将坐标原点平移到(200, 200)的位置
			ctx.translate(200,200); 
			// 对画布进行旋转操作,旋转的角度为-90°,即将角度转换为弧度单位,并逆时针旋转
			ctx.rotate(-90*Math.PI/180); 
			
			ctx.beginPath(); 
            
			// 外层空心圆盘
			ctx.save(); 
			ctx.strokeStyle="#325FA2"; 
			ctx.lineWidth = 14;
			
			ctx.beginPath();
			// 绘制一个从0°到360°的弧线,即画一个圆
			ctx.arc(0,0,140,0,360*Math.PI/180); 
			ctx.stroke(); // 绘制已定义的路径
			ctx.restore(); // 恢复之前保存的画布状态
			
			// 时针刻度
			ctx.save(); 
			// 循环绘制12个时针刻度
			for(var i=0;i<12;i++){ 
				// 逆时针旋转30°,即将角度转换为弧度单位
				ctx.rotate(30*Math.PI/180); 
				ctx.beginPath(); 
				ctx.moveTo(100,0) 
				ctx.lineTo(120,0); 
				ctx.stroke(); 
			}
			ctx.restore(); 
			
			// 分针刻度
			ctx.save(); 
			ctx.lineWidth=4; 
			// 循环绘制60个分针刻度
			for(var i=0;i<60;i++){ 
				// 逆时针旋转6°,即将角度转换为弧度单位
				ctx.rotate(6*Math.PI/180); 
				// 如果不是整点刻度,则绘制
				if((i+1)%5!=0){ 
					ctx.beginPath();
					ctx.moveTo(117,0) 
					ctx.lineTo(120,0); 
					ctx.stroke(); 
				}
			}
			ctx.restore(); 
			
			// 时针、分针、秒针、表座
			// 创建一个Date对象,获取当前时间
			var date = new Date(); 
			// 获取当前的秒数
			var s = date.getSeconds(); 
			// 获取当前的分钟数,并加上秒数的部分
			var m = date.getMinutes()+s/60; 
			// 获取当前的小时数,并加上分钟数的部分
			var h = date.getHours()+m/60; 
			// 如果小时数大于12,则减去12
			h = h>12?h-12:h; 
			
			// 时针
			ctx.save() 
			ctx.lineWidth=14; 
			// 逆时针旋转小时数乘以30°,即将角度转换为弧度单位
			ctx.rotate(h*30*Math.PI/180) 
			ctx.beginPath() 
			ctx.moveTo(-20,0); 
			ctx.lineTo(80,0);
			ctx.stroke(); 
			ctx.restore() 
			
			// 分针
			ctx.save() 
			ctx.lineWidth=10; 
			// 逆时针旋转分钟数乘以6°,即将角度转换为弧度单位
			ctx.rotate(m*6*Math.PI/180) 
			ctx.beginPath() 
			ctx.moveTo(-28,0); 
			ctx.lineTo(112,0); 
			ctx.stroke(); 
			ctx.restore() 
			
			// 秒针
			ctx.save() 
			ctx.lineWidth=6; 
			ctx.strokeStyle="#D40000"; 
			ctx.fillStyle="#D40000"; 
			// 逆时针旋转秒数乘以6°,即将角度转换为弧度单位
			ctx.rotate(s*6*Math.PI/180) 
			ctx.beginPath(); 
			ctx.moveTo(-30,0); 
			ctx.lineTo(83,0); 
			ctx.stroke(); 
			
			// 表座
			ctx.beginPath(); 
			ctx.arc(0,0,10,0,360*Math.PI/180); 
			ctx.fill(); 
			
			// 秒针头
			ctx.beginPath(); 
			ctx.arc(96,0,10,0,360*Math.PI/180);
			ctx.stroke(); 
			ctx.restore() 
			ctx.restore(); 
		}
	}
}
	</script>
</html>

在这里插入图片描述

📚图片

🐇插入图片(需要image对象)

  • canvas操作图片时,必须要等图片加载完才能操作
  • drawImage(image, x, y, width, height):其中 image 是 image 或者 canvas 对象,x 和 y 是其在目标 canvas 里的起始坐标。这个方法多了2个参数:width 和 height,这两个参数用来控制 当像canvas画入时应该缩放的大小
    var ctx = canvas.getContext("2d");
    var img = new Image();
    img.src="tg.png";
    img.onload=function(){
    	draw();
    }
    function draw(){
    	ctx.drawImage(img,0,0,img.width,img.height)
    }
    

🐇设置背景(需要image对象)

  • createPattern(image, repetition)

  • image:图像源

  • epetition:“repeat” 、“repeat-x” 、“repeat-y” 、“no-repeat”

  • 一般情况下,我们都会将createPattern返回的对象作为fillstyle的值

    var canvas = document.querySelector("#test");
    if(canvas.getContext){
    		var ctx = canvas.getContext("2d");
    		var img = new Image();
    		img.src="tg.png";
    		img.onload=function(){
    			draw();
    		}
    		function draw(){
    			var pattern = ctx.createPattern(img,"no-repeat")
    			ctx.fillStyle=pattern;
    			ctx.fillRect(0,0,300,300);
    		}	
    	}
    

🐇渐变

  • 线性渐变:createLinearGradient(x1, y1, x2, y2),表示渐变的起点 (x1,y1) 与终点 (x2,y2)
  • gradient.addColorStop(position, color)
    • gradient :createLinearGradient的返回值
    • addColorStop 方法接受 2 个参数,position 参数必须是一个 0.0 与 1.0 之间的数值,表示渐变中颜色所在的相对位置。例如,0.5 表示颜色会出现在正中间。
    • color 参数必须是一个有效的 CSS 颜色值(如 #FFF, rgba(0,0,0,1),等等)。
    var canvas = document.querySelector("#test");
    if(canvas.getContext){
    	var ctx = canvas.getContext("2d");
    	var gradient =  ctx.createLinearGradient(0, 0, 200, 200);
    	gradient.addColorStop(0,"red");
    	gradient.addColorStop(0.5,"yellow");
    	gradient.addColorStop(0.7,"pink");
    	gradient.addColorStop(1,"green");
    	ctx.fillStyle=gradient;
    	ctx.fillRect(0,0,300,300);
    }
    

在这里插入图片描述


  • 径向渐变:createRadialGradient(x1, y1, r1, x2, y2, r2)

    • 前三个参数则定义另一个以(x1,y1) 为原点,半径为 r1 的圆
    • 后三个参数则定义另一个以 (x2,y2) 为原点,半径为 r2 的圆
    var canvas = document.querySelector("#test");
    if(canvas.getContext){
    	var ctx = canvas.getContext("2d");
    	var gradient = ctx.createRadialGradient(150, 150, 50, 150, 150, 100)
    	gradient.addColorStop(0,"red");
    	gradient.addColorStop(0.5,"yellow");
    	gradient.addColorStop(0.7,"pink");
    	gradient.addColorStop(1,"green");
    	ctx.fillStyle=gradient;
    	ctx.fillRect(0,0,300,300);	
    }
    

在这里插入图片描述

🔥图片变动画

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style type="text/css">
			*{
				margin: 0;
				padding: 0;
			}
			html,body{
				height: 100%;
				overflow: hidden;
			}
			#test{
				background: white;
				position: absolute;
				left: 0;
				top: 0;
				right: 0;
				bottom: 0;
				margin: auto;
			}
		</style>
	</head>
	<body>
		<canvas id="test" width="300" height="300"></canvas>
	</body>
	<script type="text/javascript">
		window.onload=function(){
			var canvas = document.querySelector("#test");
			canvas.width = document.documentElement.clientWidth;
			canvas.height = document.documentElement.clientHeight;
			if(canvas.getContext){
				var ctx = canvas.getContext("2d");
				// 用于标记当前显示的图片序号
				var flag = 0;
				// 用于控制图片在x轴的偏移量
				var value=0;
				setInterval(function(){
					ctx.clearRect(0,0,canvas.width,canvas.height)
					value+=10;
					flag++;
					if(flag==9){
						// 当图片序号达到9时,重新设置为1
						flag=1;
					}
					var img = new Image();
					img.src="img/q_r"+(flag)+".jpg";
					img.onload=function(){
						draw(this);
					}	
				},100)
				function draw(img){
					ctx.drawImage(img,value,0)
				}
			}
		}	
	</script>
</html>

在这里插入图片描述

📚文本

🐇绘制文本

  • canvas 提供了两种方法来渲染文本:

    • fillText(text, x, y):在指定的(x,y)位置填充指定的文本
    • strokeText(text, x, y):在指定的(x,y)位置绘制文本边框
    var canvas = document.querySelector("#test");
    if(canvas.getContext){
    	var ctx = canvas.getContext("2d");
    	ctx.fillStyle="skyblue"
    	ctx.font="40px sans-serif"
    	ctx.fillText("lalayouyi",70,150);
    	ctx.strokeText("lalayouyi",70,150);
    }
    

在这里插入图片描述

🐇文本样式

  • font = value

    • 当前我们用来绘制文本的样式,这个字符串使用和 CSS font 属性相同的语法。
    • 默认的字体是 10px sans-serif。
    • font属性在指定时,必须要有。大小和字体 缺一不可
  • textAlign = value:文本对齐选项。可选的值包括: left, right center.

  • textBaseline = value:描述绘制文本时,当前文本基线的属性。

  • measureText() 方法返回一个 TextMetrics 对象,包含关于文本尺寸的信息(例如文本的宽度)

  • canvas中文本水平垂直居中

    var oC =document.getElementById('c1');
    var oGC = oC.getContext('2d');
    oGC.font = '60px impact';
    oGC.textAlign = 'left';
    oGC.textBaseline = 'middle'; 
    var w = oGC.measureText('lalayouyi').width;
    oGC.fillText('lalayouyi',(oC.width - w)/2 , (oC.height - 60)/2);
    

在这里插入图片描述

🐇阴影(文本阴影&盒模型阴影)

  • shadowOffsetX = float:shadowOffsetX 和 shadowOffsetY 用来设定阴影在 X 和 Y 轴的延伸距离,它们默认都为 0。
  • shadowOffsetY = float:shadowOffsetX 和 shadowOffsetY 用来设定阴影在 X 和 Y 轴的延伸距离,它们默认都为 0。
  • shadowBlur = float:shadowBlur 用于设定阴影的模糊程度,其数值并不跟像素数量挂钩,也不受变换矩阵的影响,默认为 0。
  • shadowColor = color(必需项):shadowColor 是标准的 CSS 颜色值,用于设定阴影颜色效果,默认是全透明的黑色。
    var oC =document.getElementById('c1');
    var oGC = oC.getContext('2d');
    oGC.font = '60px impact';
    oGC.textAlign = 'left';
    oGC.textBaseline = 'middle'; 
    var w = oGC.measureText('lalayouyi').width;
    //文本阴影&盒阴影
    oGC.shadowOffsetX = 20;
    oGC.shadowOffsetY = 20;
    oGC.shadowBlur = 30;
    oGC.shadowColor = "yellow";
    oGC.fillText('lalayouyi',(oC.width - w)/2 , (oC.height - 60)/2);
    

在这里插入图片描述

📚像素操作

到目前为止,我们尚未深入了解Canvas画布真实像素的原理,事实上,你可以直接通过ImageData对象操纵像素数据,直接读取或将数据数组写入该对象中。

🐇得到像素数据

  • getImageData():获得一个包含画布场景像素数据的ImageData对像,它代表了画布区域的对象数据
  • ctx.getImageData(sx, sy, sw, sh)
    • sx:将要被提取的图像数据矩形区域的左上角 x 坐标。
    • sy:将要被提取的图像数据矩形区域的左上角 y 坐标。
    • sw:将要被提取的图像数据矩形区域的宽度。
    • sh:将要被提取的图像数据矩形区域的高度。
  • ImageData对象中存储着canvas对象真实的像素数据,它包含以下几个只读属性:
    • width:图片宽度,单位是像素
    • height:图片高度,单位是像素
    • data:Uint8ClampedArray类型的一维数组

  • putImageData()方法去对场景进行像素数据的写入。
  • putImageData(myImageData, dx, dy):dx和dy参数表示你希望在场景内左上角绘制的像素数据所得到的设备坐标。
  • ctx.createImageData(width, height):创建一个ImageData对象,默认创建出来的是透明的。
    var ctx = canvas.getContext("2d");
    // 设置填充样式为"rgba(255, 192, 203,1)"
    ctx.fillStyle="rgba(255, 192, 203,1)";
    ctx.fillRect(0,0,100,100);
    // 获取矩形区域(0, 0, 100, 100)内的图像数据
    var imageData = ctx.getImageData(0,0,100,100);
    // var imageData = ctx.createImageData(100,100);
    // 透明度即为数组 ​imageData.data​中下标为4i+3的值(其中i表示像素点的索引)。
    // 将每个像素点的透明度设置为100,即不完全透明状态。
    for(var i=0;i<imageData.data.length;i++){
    	imageData.data[4*i+3]=100;
    }
    // 重新绘制
    ctx.putImageData(imageData,0,0)
    

在这里插入图片描述

🔥马赛克实例

  • 流程

    • 创建一个Image对象,并将其src属性设置为图片路径。
    • 在图片加载完成后,设置canvas的宽度为图片宽度的两倍,高度为图片高度。调用draw函数绘制原始图片。
    • 在draw函数中
      • 首先使用ctx.drawImage方法绘制原始图片。
      • 使用ctx.getImageData方法获取原始图片的图像数据,并保存在oldImgdata变量中。
      • 使用ctx.createImageData方法创建新的图像数据,并保存在newImgdata变量中。
      • 定义size变量为5,表示每个小方块的大小为5像素。
      • 使用嵌套的循环遍历每个小方块内的像素点,随机获取小方块内某个像素点的颜色信息,并将该颜色信息应用于整个小方块内的像素。
      • 清除画布内容。
      • 使用ctx.putImageData方法将修改后的新图像数据绘制到画布上。
  • 通过获取和设置图像数据的像素颜色信息,将原始图片划分为小块,并在每个小块中随机选择一个像素点的颜色信息,并应用于整个小块内的所有像素点,从而实现像素化的效果。

    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="UTF-8">
    		<title></title>
    		<style type="text/css">
    			*{
    				margin: 0;
    				padding: 0;
    			}
    			html,body{
    				height: 100%;
    				overflow: hidden;
    			}
    			#msk{
    				position: absolute;
    				left: 50%;
    				top: 50%;
    				transform: translate3d(-50%,-50%,0);
    			}
    		</style>
    	</head>
    	<body>
    		<canvas id="msk" ></canvas>
    	</body>
    	<script type="text/javascript">
    		var oc = document.querySelector("#msk");
    		if(oc.getContext){
    			var ctx = oc.getContext("2d");
    			var img = new Image();
    			img.src="2.png";
    			img.onload=function(){
    				oc.width=img.width*2;
    				oc.height=img.height;
    				draw();
    			}
    			
    			function draw(){
    				ctx.drawImage(img,0,0);
    				var oldImgdata = ctx.getImageData(0,0,img.width,img.height);
    				var newImgdata = ctx.createImageData(img.width,img.height);
    				// 定义每个小方块的大小为5像素
    				var size = 5;
    				for(var i=0;i<oldImgdata.width/size;i++){
    					for(var j=0;j<oldImgdata.height/size;j++){
    						// 获取当前小方块内某个像素的颜色信息
    						var color = getPxInfo(oldImgdata,i*size+Math.floor(Math.random()*size),j*size+Math.floor(Math.random()*size));
    						for(var a=0;a<size;a++){
    							for(var b=0;b<size;b++){
    								// 设置新图像数据中的像素颜色信息
    								setPxInfo(newImgdata,i*size+a,j*size+b,color)
    							}
    						}
    					}
    				}
    				ctx.clearRect(0,0,oc.width,oc.height);
    				ctx.putImageData(newImgdata,0,0);
    			}
    
    			// 获取指定位置像素的颜色信息
    			function getPxInfo(imgdata,x,y){
    				var color = [];
    				var data = imgdata.data;
    				var w = imgdata.width;
    				var h = imgdata.height;
    				// 获取像素点的红色值
    				color[0]=data[(y*w+x)*4];
    				// 获取像素点的绿色值
    				color[1]=data[(y*w+x)*4+1];
    				// 获取像素点的蓝色值
    				color[2]=data[(y*w+x)*4+2];
    				// 获取像素点的透明度值
    				color[3]=data[(y*w+x)*4+3];
    				// 返回颜色信息数组
    				return color;
    			}
    			
    			// 设置指定位置像素的颜色信息
    			function setPxInfo(imgdata,x,y,color){
    				var data = imgdata.data;
    				var w = imgdata.width;
    				var h = imgdata.height;
    				data[(y*w+x)*4]=color[0];
    				data[(y*w+x)*4+1]=color[1];
    				data[(y*w+x)*4+2]=color[2];
    				data[(y*w+x)*4+3]=color[3];
    			}
    		}
    	</script>
    </html>
    

在这里插入图片描述

📚合成

🐇全局透明度的设置

globalAlpha = value。这个属性影响到 canvas 里所有图形的透明度,有效的值范围是 0.0 (完全透明)到 1.0(完全不透明),默认是 1.0。

var ctx = canvas.getContext("2d");
ctx.fillStyle="red";
ctx.globalAlpha=.4;
ctx.fillRect(0,0,100,100);
ctx.fillRect(100,100,100,100);

在这里插入图片描述

🐇合成

globalCompositeOperation属性用于设置绘制图形时的组合操作方式。组合操作可以理解为将已有的图形和新绘制的图形进行合并或者覆盖的方式。该属性的值可以是以下几种:

  • "source-over"(默认值):新绘制的图形覆盖在已有图形之上。这是最常用的组合操作方式。

  • "source-in":新绘制的图形只显示于已有图形的重叠部分,其他部分不可见。

  • "source-out":新绘制的图形只显示于已有图形之外的部分,与已有图形重叠的部分不可见。

  • "source-atop":新绘制的图形显示于已有图形上方的重叠部分,与已有图形下方的部分不可见。

  • "destination-over":已有的图形覆盖在新绘制的图形之上。

  • "destination-in":已有的图形只显示于新绘制图形的重叠部分,其他部分不可见。

  • "destination-out":已有的图形只显示于新绘制图形之外的部分,与新绘制图形重叠的部分不可见。

  • "destination-atop":已有的图形显示于新绘制图形上方的重叠部分,与新绘制图形下方的部分不可见。

  • "lighter":将已有的图形和新绘制的图形颜色混合,得到更亮的颜色。

  • "copy":新绘制的图形完全替换已有的图形。

  • "xor":新绘制的图形与已有的图形进行异或运算,产生一种类似于橡皮擦的效果。

var ctx = canvas.getContext("2d");
ctx.fillStyle="pink";
ctx.fillRect(50,50,100,100);
// 控制新绘制的图形如何与已有的图形进行组合。
// 源图形仅会在与目标图形重叠的区域内显示,并且会覆盖目标图形,而非重叠区域将保持目标图形原有的样式。
ctx.globalCompositeOperation="destination-atop";
ctx.fillStyle="green";
ctx.fillRect(100,100,100,100);

在这里插入图片描述

🔥刮刮卡实例

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no"></meta>
		<title></title>
		<style type="text/css">
			*{
				margin: 0;
				padding: 0;
			}
			html,body{
				height: 100%;
				overflow: hidden;
			}
			#wrap,ul,ul>li{
				height: 100%;
			}
			ul>li{
				background: url(img/b.png);
				background-size:100% 100% ;
			}
			canvas{
				position: absolute;
				left: 0;
				top: 0;
				transition:1s;
			}
		</style>
	</head>
	<body>
		<div id="wrap">
			 <!-- 画布 -->
			<canvas></canvas>
			<ul>
				<li></li>
			</ul>
		</div>
	</body>
	
	<script type="text/javascript">
		window.onload = function() {
    		var canvas = document.querySelector("canvas"); 
			canvas.width = document.documentElement.clientWidth;
			canvas.height = document.documentElement.clientHeight;
			if (canvas.getContext) {
				var ctx = canvas.getContext("2d"); 
				var img = new Image();
				img.src = "img/a.png"; 
				img.onload = function() { 
					draw(); 
				}

				//绘制画布
				function draw() {
					// 记录透明像素点的数量
					var flag = 0; 
					// 将图片绘制到画布上
					ctx.drawImage(img, 0, 0, canvas.width, canvas.height); 
					// 判断是否正在绘制路径(使得刮刮乐更平滑)
					var isDrawing = false; 
					var lastX = 0; // 上一个绘制点的水平坐标
					var lastY = 0; // 上一个绘制点的垂直坐标
					canvas.addEventListener("mousedown", startDrawing); 
					canvas.addEventListener("mousemove", drawPath); 
					canvas.addEventListener("mouseup", stopDrawing); 

					/**
					 * 开始绘制路径
					 * @param {MouseEvent} ev 鼠标按下事件
					 */
					function startDrawing(ev) {
						isDrawing = true; 
						// 获取当前鼠标位置的水平坐标
						var x = ev.clientX - canvas.offsetLeft; 
						// 获取当前鼠标位置的垂直坐标
						var y = ev.clientY - canvas.offsetTop; 
						// 记录起始坐标
						[lastX, lastY] = [x, y]; 
					}

					/**
					 * 绘制路径
					 * @param {MouseEvent} ev 鼠标移动事件
					 */
					function drawPath(ev) {
						if (!isDrawing) return; 
						var x = ev.clientX - canvas.offsetLeft; 
						var y = ev.clientY - canvas.offsetTop; 
						// 设置绘制模式为“目标图像透明部分显示出来”
						ctx.globalCompositeOperation = "destination-out";
						ctx.lineWidth = 40; 
						ctx.lineCap = "round"; 
						ctx.lineJoin = "round"; 
						ctx.save(); 
						ctx.beginPath(); 
						ctx.moveTo(lastX, lastY); 
						ctx.lineTo(x, y); 
						ctx.stroke(); 
						ctx.restore(); 
						[lastX, lastY] = [x, y]; 
					}

					/**
					 * 停止绘制路径
					 */
					function stopDrawing() {
						isDrawing = false; 
						var imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
						// 计算像素总数
						var allPx = imgData.width * imgData.height; 
						for (var i = 0; i < allPx; i++) {
							// 判断像素是否透明
							if (imgData.data[4 * i + 3] === 0) { 
								flag++; 
							}
						}
						// 如果透明像素点数量超过一半,则将画布透明度设置为0(就认为已经刮得差不多
						if (flag >= allPx / 2) { 
							canvas.style.opacity = 0;
						}
					}
					// 监听CSS过渡效果结束事件
					canvas.addEventListener("transitionend", function() { 
						this.remove(); // 移除画布元素
					})
				}
			}
		}
	</script>
</html>

在这里插入图片描述

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

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

相关文章

【Redis】String字符串类型-常用命令

文章目录 String字符串类型常用命令setgetMGETMSET 计数命令INCRINCRBYDECRDECRBYINCRBYFLOAT 其它命令APPENDGETRANGESETRANGESTRLEN 命令总结 String字符串类型 1&#xff09;⾸先Redis中所有的键的类型都是字符串类型 2&#xff09;字符串类型的值&#xff08;value&#…

鉴源实验室 | 自动驾驶传感器攻击研究

作者 | 付海涛 上海控安可信软件创新研究院汽车网络安全组 来源 | 鉴源实验室 社群 | 添加微信号“TICPShanghai”加入“上海控安51fusa安全社区” 01 自动驾驶汽车的脆弱性 自2015年以来&#xff0c;汽车的信息安全问题受到国内外的广泛关注。而随着汽车的智能化与网联化的…

C语言scanf()函数读取包含空格的字符串

scanf()函数读取输入时&#xff0c;遇到空格或者回车结束读取&#xff1b; 所以输入的字符串中有空格&#xff0c;到空格就中断了&#xff1b; 根据资料&#xff0c;使用 "%[^\n]" 这样的格式化符遇到空格继续读取&#xff0c;直到敲了回车&#xff1b; 看一下&am…

微信小程序UI自动化测试实践:Minium+PageObject

小程序架构上分为渲染层和逻辑层&#xff0c;尽管各平台的运行环境十分相似&#xff0c;但是还是有些许的区别&#xff08;如下图&#xff09;&#xff0c;比如说JavaScript 语法和 API 支持不一致&#xff0c;WXSS 渲染表现也有不同&#xff0c;所以不论是手工测试&#xff0c…

Javaweb之HTML,CSS的详细解析

2. HTML & CSS 1). 什么是HTML ? HTML: HyperText Markup Language&#xff0c;超文本标记语言。 超文本&#xff1a;超越了文本的限制&#xff0c;比普通文本更强大。除了文字信息&#xff0c;还可以定义图片、音频、视频等内容。 标记语言&#xff1a;由标签构成的语言…

Netty在Firbase中的使用

1.1前言 实时更新是现代应用程序中用户体验的一个组成部分。随着用户期待这样的行为&#xff0c;越来越多的应用程序都正在实时地向用户推送数据的变化。通过传统的3层架构很难实现实时的数据同步&#xff0c;其需要开发者管理他们自己的运维、服务器以及伸缩。通过维护到客户…

会声会影2024对比2023变化以及功能对比

全新会声会影2024版本现已登场&#xff0c;小伙伴们相信已经急不可待地想知道2024版到底有哪些新功能。对比2023版本&#xff0c;会声会影2024版本有没有功能的增强&#xff1f;事不宜迟&#xff0c;现在就让我们一起来看看会声会影2024对比2023的变化&#xff0c;包括功能对比…

Spring Boot整合Swagger

&#x1f648;作者简介&#xff1a;练习时长两年半的Java up主 &#x1f649;个人主页&#xff1a;程序员老茶 &#x1f64a; ps:点赞&#x1f44d;是免费的&#xff0c;却可以让写博客的作者开心好久好久&#x1f60e; &#x1f4da;系列专栏&#xff1a;Java全栈&#xff0c;…

Java 为什么不推荐在 while 循环中使用 sleep() 我悟了

文章目录 前言原因是否正确方案是否合理定时轮询场景事件机制等待和唤醒 个人简介 前言 最近逛 CSDN 看到一篇文章&#xff0c;文章大意是说为什么在循环中不推荐使用 sleep 操作&#xff0c;原因在于线程挂起和唤醒会有很大的性能消耗&#xff0c;并推荐使用 Timer 及 Schedu…

描述低轨星座的特点和通信挑战,以及它们在5G和B5G中的作用。

文章目录 2章4 章5章&#xff08;没看&#xff09;6章&#xff08;没看&#xff09; 2章 将卫星星座中每个物理链路中可实现的数据速率、传播延迟和多普勒频移与3GPP技术报告中的参数进行分析和比较[3]。 相关配置 面向连接的网络&#xff0c;预先简历链路 卫星和地面终端有…

能卷死同行的收银系统源码--服装店收银系统+进销存、PHP+mysql

涉及零售服装门店收银系统源码 超市务管理系统源码 便利店收银系统源码 进销存erp/scrm的供应链订货系统源码 saas门店连锁加盟收银系统源码 走过路过不要错过。 整理采用ThinkPHPmysql&#xff0c;二开门槛低&#xff0c; 模块化设计&#xff0c;前后端分离。 前端&…

使用JMeter进行接口压力测试

1.我首先创建一个线程组 2.创建好之后如图所示 3. 进行配置 4. 然后添加一个https请求 5.创建好之后设置请求方法和对应参数 6.设置表格监听器 7.创建好之后如图所示 8.保存jmx文件后点击运行进行测试&#xff0c;结果反馈如下图

Maxwell for 3dMax渲染器的安装方法

Maxwell渲染器的安装方法 Maxwell Render是一个基于控制光传输的数学方程的渲染引擎&#xff0c;这意味着所有元素&#xff0c;如发射器材料和相机&#xff0c;都是从物理精确的模型中导出的。Maxwell Render是无偏的&#xff0c;因此不使用任何技巧来计算场景中每个像素的照明…

信息论基础知识1

1.1 自信息定义&#xff1a;把某个消息出现的不确定性大小&#xff0c;用这个消息出现的概率的对数表示&#xff1a; I(X)-logp(x) 1.2 在任何一个信息流通的系统中&#xff0c;都有一个发出信息的发送端&#xff08;信源&#xff09;&#xff0c;有一个接收信息的接收端…

我的计算机启蒙书:信息学竞赛入门书提高篇

你是否曾读过一本让你欲罢不能的计算机书籍&#xff1f;它可能为你打开了新的技术世界大门&#xff0c;或者是帮助你解决了棘手的编程难题。 我从百度上搜到其相关介绍&#xff1a; 信息学奥赛一本通&#xff0c;是一本系统性、综合性的信息学竞赛教材&#xff0c;由著名信息学…

[架构之路-254/创业之路-85]:目标系统 - 横向管理 - 源头:信息系统战略规划的常用方法论,为软件工程的实施指明方向!!!

目录 总论&#xff1a; 一、数据处理阶段的方法论 1.1 企业信息系统规划法BSP 1.1.1 概述 1.1.2 原则 1.2 关键成功因素法CSF 1.2.1 概述 1.2.2 常见的企业成功的关键因素 1.3 战略集合转化法SST&#xff1a;把战略目标转化成信息的集合 二、管理信息系统阶段的方法论…

Ubuntu20.04下安装Redis环境

apt安装Redis环境 更新apt-get安装镜像源 安装Redis sudo apt-get install -y redis-server设置密码 # 编辑Redis的配置文件redis.conf&#xff0c;如果不知道配置文件的位置可以执行whereis redis.conf查看 sudo vim /etc/redis/redis.conf取消文件中的requirepass注释&am…

draw.io与项目管理——如何利用流程图工具提高项目管理效率

draw.io 是一款强大的图形绘制工具&#xff0c;用于创建各种类型的图表、流程图、组织结构图、网络图和平面设计等。它提供了丰富的绘图工具和预定义的图形库&#xff0c;使用户能够轻松创建专业水平的图形作品。 draw.io具有直观的界面和简单易用的功能&#xff0c;适合各种用…

Windows 安全

Windows sec study N F T S 文件系统 \color{#FC5531}{NFTS 文件系统} NFTS文件系统 常用命令 \color{#FC5531}{常用命令} 常用命令 磁盘管理 \color{#FC5531}{磁盘 管理} 磁盘管理 文件备份 \color{#FC5531}{文件备份} 文件备份 安全策略管理 \color{#FC5531}{安全策略管理} 安…