引言
李萨如图是一种由两个互相垂直的正弦波合成形成的图形。通过调整这两个正弦波的频率,可以得到各种复杂的图案。本文将介绍如何使用 HTML 和 Canvas 来绘制李萨如图,并添加滑块来控制两个方向上的频率变化,同时让图形产生 3D 旋转的效果。
步骤一:创建基本的 HTML 结构
首先,我们需要创建一个基本的 HTML 文件结构,并引入必要的 CSS 样式和 JavaScript 脚本。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Lissajous Figure</title> <style> body { display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; background-color: #f0f0f0; } canvas { border: 1px solid black; } .controls { position: absolute; top: 10px; left: 10px; } input[type="range"] { width: 200px; margin-bottom: 10px; } </style> </head> <body> <div class="controls"> <label for="frequencyX">Frequency X:</label> <input type="range" id="frequencyX" min="1" max="20" value="5"> <span id="valueX">5</span><br>
<label for="frequencyY">Frequency Y:</label> <input type="range" id="frequencyY" min="1" max="20" value="4"> <span id="valueY">4</span> </div> <canvas id="lissajousCanvas" width="500" height="500"></canvas>
<script> </script> </body> </html>
|
步骤二:编写 JavaScript 代码
接下来,我们将在 <script>
标签内编写 JavaScript 代码来绘制李萨如图,并实现动态效果。
初始化变量
首先,获取 Canvas 元素及其上下文,以及滑块元素和显示频率值的 span 元素。
1 2 3 4 5 6 7 8 9 10
| const canvas = document.getElementById('lissajousCanvas'); const ctx = canvas.getContext('2d'); const frequencyXInput = document.getElementById('frequencyX'); const frequencyYInput = document.getElementById('frequencyY'); const valueXSpan = document.getElementById('valueX'); const valueYSpan = document.getElementById('valueY');
let frequencyX = parseInt(frequencyXInput.value); let frequencyY = parseInt(frequencyYInput.value); let delta = 0;
|
绘制李萨如图
定义 drawLissajous
函数来绘制李萨如图。我们将使用 requestAnimationFrame
来不断更新画面,从而实现动画效果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| function drawLissajous() { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.beginPath(); ctx.strokeStyle = 'blue'; ctx.lineWidth = 2;
const centerX = canvas.width / 2; const centerY = canvas.height / 2; const radius = 200;
for (let t = 0; t <= Math.PI * 4; t += 0.01) { const x = centerX + radius * Math.sin(frequencyX * t + delta); const y = centerY + radius * Math.sin(frequencyY * t);
if (t === 0) { ctx.moveTo(x, y); } else { ctx.lineTo(x, y); } }
ctx.stroke();
delta += 0.01; requestAnimationFrame(drawLissajous); }
|
添加事件监听器
为滑块添加事件监听器,以便在用户调整滑块时更新频率值。
1 2 3 4 5 6 7 8 9
| frequencyXInput.addEventListener('input', () => { frequencyX = parseInt(frequencyXInput.value); valueXSpan.textContent = frequencyX; });
frequencyYInput.addEventListener('input', () => { frequencyY = parseInt(frequencyYInput.value); valueYSpan.textContent = frequencyY; });
|
启动绘图函数
最后,调用 drawLissajous
函数来启动整个绘制过程。
完整代码
以下是完整的 HTML 文件代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Lissajous Figure</title> <style> body { display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; background-color: #f0f0f0; } canvas { border: 1px solid black; } .controls { position: absolute; top: 10px; left: 10px; } input[type="range"] { width: 200px; margin-bottom: 10px; } </style> </head> <body> <div class="controls"> <label for="frequencyX">Frequency X:</label> <input type="range" id="frequencyX" min="1" max="20" value="5"> <span id="valueX">5</span><br>
<label for="frequencyY">Frequency Y:</label> <input type="range" id="frequencyY" min="1" max="20" value="4"> <span id="valueY">4</span> </div> <canvas id="lissajousCanvas" width="500" height="500"></canvas>
<script> const canvas = document.getElementById('lissajousCanvas'); const ctx = canvas.getContext('2d'); const frequencyXInput = document.getElementById('frequencyX'); const frequencyYInput = document.getElementById('frequencyY'); const valueXSpan = document.getElementById('valueX'); const valueYSpan = document.getElementById('valueY');
let frequencyX = parseInt(frequencyXInput.value); let frequencyY = parseInt(frequencyYInput.value); let delta = 0;
function drawLissajous() { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.beginPath(); ctx.strokeStyle = 'blue'; ctx.lineWidth = 2;
const centerX = canvas.width / 2; const centerY = canvas.height / 2; const radius = 200;
for (let t = 0; t <= Math.PI * 4; t += 0.01) { const x = centerX + radius * Math.sin(frequencyX * t + delta); const y = centerY + radius * Math.sin(frequencyY * t);
if (t === 0) { ctx.moveTo(x, y); } else { ctx.lineTo(x, y); } }
ctx.stroke();
delta += 0.01; requestAnimationFrame(drawLissajous); }
frequencyXInput.addEventListener('input', () => { frequencyX = parseInt(frequencyXInput.value); valueXSpan.textContent = frequencyX; });
frequencyYInput.addEventListener('input', () => { frequencyY = parseInt(frequencyYInput.value); valueYSpan.textContent = frequencyY; });
drawLissajous(); </script> </body> </html>
|
总结
通过以上步骤,我们成功地使用 HTML 和 Canvas 实现了一个带有滑块控制的李萨如图,并实现了 3D 旋转效果。你可以根据自己的需求进一步调整样式和功能。希望这篇教程对你有所帮助!
这样就完成了一篇详细的博客文章教程,帮助读者了解如何使用 HTML 和 Canvas 绘制李萨如图并实现动态效果。