canvas--模拟水波波浪(利用三角函数正弦曲线实现)--完整代码

这篇博客介绍了如何利用JavaScript和HTML5 Canvas结合正弦函数来创建波浪动画效果。通过调整振幅、角频率、初相和图像平移等参数,实现了波浪的动态变化。文章还提供了完整的代码示例,展示了如何通过帧动画和线性渐变实现波浪的移动和颜色过渡。
摘要由CSDN通过智能技术生成

实现原理

看到波浪特征的时候,难免会有人想到正余弦曲线。对于波陡很小的波动,一般都选择正弦或者余弦曲线来表示波形。

正弦曲线示意图

在这里插入图片描述

正弦曲线公式:y=Asin(ωx+φ)+h

A:表示振幅,值越大曲线越陡峭。用来控制波浪的高度
ω:表示角频率(ω=2π/T,T为函数的周期)
       T值大于1时:T值越大周期越短。用来控制波浪的宽度
       T值小于1大于0时:周期变长
φ:表示初相
       相移是-φ/ω 在ω不变的情况下,φ为正值:曲线向左移动;φ为负值:曲线向右移动。控制波浪的水平移动
h:表示图像向y轴正方向平移的长度,控制曲线上下移动。控制水位的高度

动画效果实现思路

主要是利用相移,通过不断水平移动曲线,产生出波浪移动的感觉,可以绘制多条曲线,曲线之间通过控制属性(高度、宽度、移动速度)产生视觉差

上代码

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>三角函数模拟水波</title>
		<style>
			html,
			body {
				padding: 0;
				margin: 0;
				width: 100%;
				height: 100%;
			}
			canvas {
				width: 100%;
				height: 500px;
			}
		</style>
	</head>
	<body>
		<div>
			<canvas id="canvas"></canvas>
		</div>
		<script type="text/javascript">
			var canvas = document.getElementById("canvas"),
				ctx = canvas.getContext('2d'),
				width = canvas.width = canvas.offsetWidth,
				height = canvas.height = canvas.offsetHeight;
			console.log(height)
			//声明参数
			var A = 30,
				W = 1 / 200,
				Q = 0,
				H = height / 2;
			var A2 = 30,
				W2 = 1 / 300,
				Q2 = 0,
				H2 = height / 2;
			var speed = -0.01;
			var speed2 = -0.02;
			
			//创建线性渐变
			var lingrad = ctx.createLinearGradient(0, 0, width, 0);
			//规定渐变对象中的颜色和停止位置
			lingrad.addColorStop(0, 'rgba(0,186,128,0.8)');
			lingrad.addColorStop(1, 'rgba(111,224,195,1)');
			
			var lingrad2 = ctx.createLinearGradient(0, 0, width, 0);
			lingrad2.addColorStop(0, 'rgba(111,224,195,1)');
			lingrad2.addColorStop(1, 'rgba(0,186,128,0.8)');
			
			//绘图方法
			(function draw() {
				/**
				 * 将Q随时间不断增加或减小,即可得到不同时间的不同图像
				 * 使用window.requestAnimationFrame实现帧动画
				 */
				window.requestAnimationFrame(draw);
				ctx.clearRect(0, 0, width, height); // 清空画布
				
				ctx.beginPath(); //开始路径
				ctx.strokeStyle = "#000"; //设置线条颜色
				ctx.fillStyle = lingrad;  //填充渐变色
				ctx.lineWidth = 1; //设置线条宽度
				ctx.moveTo(0, height / 2); //起始点位置    moveTo(x,y)可把窗口的左上角移动到一个指定的坐标
				Q += speed;
				for(let x = 0; x <= width; x++) { //绘制x对应y的
					var y = A * Math.sin(W * x + Q) + H;
					ctx.lineTo(x, y);
				}
				ctx.lineTo(width, height);
				ctx.lineTo(0, height);
				ctx.fill();
				ctx.closePath() //闭合路径
				/**
				 * globalCompositeOperation 属性设置或返回如何将一个源(新的)图像绘制到目标(已有)的图像上。
						源图像 = 您打算放置到画布上的绘图。
						目标图像 = 您已经放置在画布上的绘图。
					destination-over:在源图像上方显示目标图像
				 */
				ctx.globalCompositeOperation = "destination-over"
				
				ctx.beginPath();
				ctx.strokeStyle = "#000";
				ctx.lineWidth = 1;
				ctx.fillStyle = lingrad2;
				Q2 += speed2;
				for(let x = 0; x < width; x++) {
					var y = A2 * Math.sin(x * W2 + Q2) + H2;
					ctx.lineTo(x, y);
				}
				ctx.lineTo(width, height);
				ctx.lineTo(0, height);
				ctx.fill()
				ctx.closePath();

			})()
		</script>
	</body>
</html>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值