<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>光的折射控制器</title> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: "Microsoft YaHei", sans-serif; } body { background-color: #f5f5f5; padding: 20px; } .container { max-width: 800px; margin: 0 auto; background: white; padding: 30px; border-radius: 10px; box-shadow: 0 0 15px rgba(0,0,0,0.1); } h1 { text-align: center; color: #333; margin-bottom: 30px; } .controls { display: flex; flex-wrap: wrap; gap: 20px; margin-bottom: 30px; } .control-group { flex: 1; min-width: 200px; } label { display: block; margin-bottom: 8px; font-weight: bold; color: #555; } input[type="range"], select { width: 100%; padding: 5px; border: 1px solid #ddd; border-radius: 5px; } input[type="number"] { width: 80px; padding: 5px; border: 1px solid #ddd; border-radius: 5px; text-align: center; } .value-display { margin-top: 5px; color: #666; } #canvas-container { width: 100%; height: 400px; border: 2px solid #333; border-radius: 5px; position: relative; overflow: hidden; background: linear-gradient(to bottom, #e0f7fa 0%, #bbdefb 50%, #f1f8e9 50%, #dcedc8 100%); } #refraction-canvas { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } .law-tip { text-align: center; margin-top: 20px; font-style: italic; color: #777; } </style> </head> <body> <div class="container"> <h1>光的折射控制器</h1> <div class="controls"> <div class="control-group"> <label for="incident-angle">入射角 (°)</label> <input type="range" id="incident-angle" min="0" max="89" value="30"> <div class="value-display">当前值: <span id="incident-angle-value">30</span>°</div> </div> <div class="control-group"> <label for="n1">介质1折射率</label> <input type="number" id="n1" min="1" max="3" step="0.01" value="1.00"> <div class="value-display">当前值: <span id="n1-value">1.00</span></div> </div> <div class="control-group"> <label for="n2">介质2折射率</label> <input type="number" id="n2" min="1" max="3" step="0.01" value="1.50"> <div class="value-display">当前值: <span id="n2-value">1.50</span></div> </div> <div class="control-group"> <label for="light-color">光线颜色</label> <select id="light-color"> <option value="#ff0000">红色</option> <option value="#00ff00">绿色</option> <option value="#0000ff" selected>蓝色</option> <option value="#ffff00">黄色</option> <option value="#ff00ff">紫色</option> <option value="#ffffff">白色</option> </select> </div> </div> <div id="canvas-container"> <canvas id="refraction-canvas"></canvas> </div> <div class="law-tip">斯涅尔定律:n₁·sinθ₁ = n₂·sinθ₂</div> </div> <script> $(document).ready(function() { // 获取DOM元素 const canvas = document.getElementById('refraction-canvas'); const ctx = canvas.getContext('2d'); const incidentAngleSlider = $('#incident-angle'); const incidentAngleValue = $('#incident-angle-value'); const n1Input = $('#n1'); const n1Value = $('#n1-value'); const n2Input = $('#n2'); const n2Value = $('#n2-value'); const lightColorSelect = $('#light-color'); // 设置canvas尺寸 function resizeCanvas() { const container = $('#canvas-container'); canvas.width = container.width(); canvas.height = container.height(); drawRefraction(); } $(window).resize(resizeCanvas); resizeCanvas(); // 实时更新数值显示 incidentAngleSlider.on('input', function() { const val = $(this).val(); incidentAngleValue.text(val); drawRefraction(); }); n1Input.on('input', function() { const val = parseFloat($(this).val()).toFixed(2); n1Value.text(val); drawRefraction(); }); n2Input.on('input', function() { const val = parseFloat($(this).val()).toFixed(2); n2Value.text(val); drawRefraction(); }); lightColorSelect.on('change', drawRefraction); // 绘制折射效果 function drawRefraction() { // 获取参数 const incidentAngle = parseFloat(incidentAngleSlider.val()); // 入射角(度) const n1 = parseFloat(n1Input.val()); // 介质1折射率 const n2 = parseFloat(n2Input.val()); // 介质2折射率 const lightColor = lightColorSelect.val(); // 光线颜色 // 清空画布 ctx.clearRect(0, 0, canvas.width, canvas.height); const centerX = canvas.width / 2; const centerY = canvas.height / 2; // 两种介质的分界面(水平线) // 绘制介质分界线和法线 ctx.beginPath(); ctx.moveTo(0, centerY); ctx.lineTo(canvas.width, centerY); ctx.strokeStyle = '#333'; ctx.lineWidth = 2; ctx.stroke(); ctx.beginPath(); ctx.moveTo(centerX, 0); ctx.lineTo(centerX, canvas.height); ctx.strokeStyle = '#999'; ctx.lineWidth = 1; ctx.setLineDash([5, 5]); ctx.stroke(); ctx.setLineDash([]); // 计算折射角(斯涅尔定律) const incidentRad = incidentAngle * Math.PI / 180; // 转换为弧度 let refractionAngle = 0; let isTotalReflection = false; // 计算折射角,判断是否发生全反射 const sinTheta2 = (n1 / n2) * Math.sin(incidentRad); if (Math.abs(sinTheta2) > 1) { isTotalReflection = true; // 全反射 } else { refractionAngle = Math.asin(sinTheta2) * 180 / Math.PI; // 转换为度 } // 绘制入射光线 const rayLength = Math.min(canvas.width, canvas.height) / 2; const incidentStartX = centerX - rayLength * Math.sin(incidentRad); const incidentStartY = centerY - rayLength * Math.cos(incidentRad); ctx.beginPath(); ctx.moveTo(incidentStartX, incidentStartY); ctx.lineTo(centerX, centerY); ctx.strokeStyle = lightColor; ctx.lineWidth = 3; ctx.stroke(); // 绘制折射/反射光线 if (isTotalReflection) { // 全反射:绘制反射光线 const reflectEndX = centerX + rayLength * Math.sin(incidentRad); const reflectEndY = centerY - rayLength * Math.cos(incidentRad); ctx.beginPath(); ctx.moveTo(centerX, centerY); ctx.lineTo(reflectEndX, reflectEndY); ctx.strokeStyle = lightColor; ctx.lineWidth = 3; ctx.stroke(); // 绘制全反射提示 ctx.font = '16px Microsoft YaHei'; ctx.fillStyle = '#ff0000'; ctx.fillText('发生全反射', centerX + 20, centerY - 50); } else { // 折射:绘制折射光线 const refractionRad = refractionAngle * Math.PI / 180; const refractionEndX = centerX + rayLength * Math.sin(refractionRad); const refractionEndY = centerY + rayLength * Math.cos(refractionRad); ctx.beginPath(); ctx.moveTo(centerX, centerY); ctx.lineTo(refractionEndX, refractionEndY); ctx.strokeStyle = lightColor; ctx.lineWidth = 3; ctx.stroke(); } // 绘制角度文本 ctx.font = '14px Microsoft YaHei'; ctx.fillStyle = '#333'; ctx.fillText(`入射角: ${incidentAngle.toFixed(1)}°`, centerX - 100, centerY - 20); if (!isTotalReflection) { ctx.fillText(`折射角: ${refractionAngle.toFixed(1)}°`, centerX + 20, centerY + 30); } else { ctx.fillText(`反射角: ${incidentAngle.toFixed(1)}°`, centerX + 20, centerY - 50); } } // 初始绘制 drawRefraction(); }); </script> </body> </html>
人工智能作业--光的折射
张小明
前端开发工程师
深入浅出理解Spring Boot中的依赖注入
在现代软件开发中,依赖注入(Dependency Injection,简称DI)已经成为了一种常见且重要的设计模式。它的核心思想是将对象的依赖关系从代码中解耦出来,从而提高代码的可维护性、可测试性和灵活性。在Java开发中࿰…
Canvas 指纹追踪揭秘:为什么你换了 IP 和 浏览器,网站还能认出你是谁?(附 Python 检测脚本)
👻 前言:无痕模式的“谎言” 你是否遇到过这种情况: 你在京东看了一双鞋,没登录账号,然后清除了浏览器 Cookies,换了 IP 地址,打开了 Chrome 的“无痕模式”。 结果,当你打开另一个…
【计算机毕业设计案例】基于java+vue的个人健康管理系统的设计与实现(程序+文档+讲解+定制)
博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…
浅谈银行系统对接中的不可思议
01 引言 银行系统的安全级别应该是相当高的,与银行接口对接(银企直联)过程中也遭遇了平时开发中不常见的问题,甚至当时表示不理解。 前前后后对接了两家银行:招商银行和中信银行,安全要求各异,也…
KNN分类预测:用Matlab轻松实现
KNN分类预测 可以选取80%的数据训练,20%测试(可自定义百分比) Matlab代码备注清晰,易于使用在机器学习领域,K 近邻(K-Nearest Neighbors,简称 KNN)算法是一种简单而有效的分类算法。…