π的可视化理解

211 阅读1分钟

过年了,没什么东西好送给大家,最近看到了一个π可视化的短视频但是没有相关源码; 撸一个给大家,没什么内容就直接上图,上源码了

微信图片_20240101034245.png

微信图片_20240101034241.png

微信图片_20240101034234.png

<html>
	<head>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			canvas {
				transform: scale(1.5);
			}
			body{
				background-image: linear-gradient(to right, #333, #0b0b0b);
			}
			.box{
				width: 100vw;
				height: 100vh;
				display: flex;
				align-items: center;
				justify-content: center;
			}
		</style>
	</head>
	<body>
		<div class="box">
			<canvas id="canvas"></canvas>
		</div>
		<script>
			let doublex = 1
			const bufferCanvas = document.createElement('canvas');
			const bufferCtx = bufferCanvas.getContext('2d');
			const canvas = document.getElementById('canvas');
			const ctx = canvas.getContext('2d');
			let targetarr = []
			const width = canvas.width = 500;
			const height = canvas.height = 500;
			bufferCanvas.width = width;
			bufferCanvas.height = height;
			let angle = 0;
			let lastTime = 0;

			function draw() {

				ctx.clearRect(0, 0, width, height);
				ctx.drawImage(bufferCanvas, 0, 0);
				// 计算旋转角度
				angle += (0.01*doublex)
				const rotatedEndpoint = rotateEndpoint(angle); // 逆时针旋转 45 度,即 π/4 弧度
				// 保存环境
				ctx.save();
				bufferCtx.save()

				// 画实心点
				ctx.beginPath();
				ctx.fillStyle = '#fff';
				ctx.arc(250, 250, 2, 0, 2 * Math.PI);
				ctx.fill();

				// 画空心点
				ctx.beginPath();
				ctx.strokeStyle = '#fff';
				ctx.translate(0, 0);
				ctx.arc(rotatedEndpoint.x, rotatedEndpoint.y, 2, 0, 2 * Math.PI);
				ctx.stroke();

				// 画连线
				ctx.beginPath();
				ctx.moveTo(250, 250);
				ctx.lineTo(rotatedEndpoint.x, rotatedEndpoint.y);
				ctx.strokeStyle = '#fff';
				ctx.stroke();

				const endpoint = calculateEndpoint(rotatedEndpoint.x, rotatedEndpoint.y, 100, angle * Math.PI);
				targetarr.push(endpoint.x, endpoint.y)
				// 画实心点
				ctx.beginPath();
				ctx.strokeStyle = '#fff';
				ctx.arc(endpoint.x, endpoint.y, 2, 0, 2 * Math.PI);
				ctx.stroke();

				bufferCtx.beginPath();
				bufferCtx.fillStyle = '#fff';
				bufferCtx.arc(endpoint.x, endpoint.y, 0.5, 0, 2 * Math.PI);
				bufferCtx.fill();

				// 画连线
				ctx.beginPath();
				ctx.moveTo(rotatedEndpoint.x, rotatedEndpoint.y);
				ctx.lineTo(endpoint.x, endpoint.y);
				ctx.strokeStyle = '#fff';
				ctx.stroke();

				// 恢复环境  
				ctx.restore();
				bufferCtx.restore();
				requestAnimationFrame(draw);
				// setTimeout(()=>{
				// 	draw()
				// },10)
			}

			function rotateEndpoint(radians) {
				const startX = 250; // 起始点 x 坐标
				const startY = 250; // 起始点 y 坐标
				const endX = 250; // 终点 x 坐标
				const endY = 150; // 终点 y 坐标

				// 计算线段长度和角度
				const length = Math.sqrt(Math.pow(endX - startX, 2) + Math.pow(endY - startY, 2));
				const angle = Math.atan2(endY - startY, endX - startX);

				// 应用旋转弧度
				const rotatedAngle = angle + radians;

				// 计算旋转后的终点坐标
				const rotatedEndX = startX + length * Math.cos(rotatedAngle);
				const rotatedEndY = startY + length * Math.sin(rotatedAngle);

				return {
					x: rotatedEndX,
					y: rotatedEndY
				};
			}

			function calculateEndpoint(startX, startY, length, radians) {
				const endX = startX + length * Math.cos(radians);
				const endY = startY + length * Math.sin(radians);

				return {
					x: endX,
					y: endY
				};
			}
			draw();
		</script>

	</body>
</html>

预览地址:pi.hanyue325.cloud/