news 2026/6/15 16:43:30

光线折射的代码

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
光线折射的代码

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>光的折射控制器</title>
<style>
body {
padding: 20px;
background-color: #f5f5f5;
font-family: "Microsoft YaHei", Arial, sans-serif;
}
#canvas-container {
position: relative;
width: 800px;
height: 600px;
margin: 20px auto;
border: 2px solid #333;
background-color: #fff;
/* 确保容器可见 */
display: block;
}
#refraction-canvas {
width: 100%;
height: 100%;
/* 修复canvas渲染模糊 */
image-rendering: -webkit-optimize-contrast;
}
.controls {
width: 800px;
margin: 0 auto;
padding: 15px;
background-color: #fff;
border: 1px solid #ddd;
border-radius: 5px;
margin-bottom: 10px;
}
.control-group {
margin-bottom: 15px;
line-height: 30px;
}
label {
display: inline-block;
width: 150px;
font-weight: bold;
}
.angle-label {
margin-left: 10px;
color: #666;
}
/* 成果展示框样式 */
.result-box {
width: 800px;
margin: 10px auto;
padding: 20px;
background-color: #fff;
border: 1px solid #ddd;
border-radius: 5px;
font-size: 16px;
line-height: 1.8;
}
.result-box h4 {
margin-top: 0;
color: #2c3e50;
border-bottom: 1px solid #eee;
padding-bottom: 10px;
}
.result-item {
margin: 8px 0;
}
.result-key {
font-weight: bold;
color: #3498db;
display: inline-block;
width: 180px;
}
.result-value {
color: #27ae60;
}
.warning {
color: #e74c3c;
font-weight: bold;
}
/* 兼容IE的滑块样式 */
input[type="range"] {
width: 200px;
height: 20px;
}
</style>
</head>
<body>
<div class="controls">
<div class="control-group">
<label for="angle">入射角(θ₁):</label>
<input type="range" id="angle" min="0" max="90" value="30" step="1">
<span id="angle-value" class="angle-label">30°</span>
</div>
<div class="control-group">
<label for="n1">介质1折射率(n₁):</label>
<input type="range" id="n1" min="1.0" max="2.0" value="1.0" step="0.1">
<span id="n1-value" class="angle-label">1.0</span>
</div>
<div class="control-group">
<label for="n2">介质2折射率(n₂):</label>
<input type="range" id="n2" min="1.0" max="2.0" value="1.5" step="0.1">
<span id="n2-value" class="angle-label">1.5</span>
</div>
<div class="control-group">
<label for="color">光线颜色:</label>
<input type="color" id="color" value="#ff0000">
</div>
</div>

<div id="canvas-container">
<canvas id="refraction-canvas"></canvas>
</div>

<!-- 成果展示框 -->
<div class="result-box">
<h4>光的折射计算成果</h4>
<div class="result-item">
<span class="result-key">入射角度(θ₁):</span>
<span id="res-incident-angle" class="result-value">30.0°</span>
</div>
<div class="result-item">
<span class="result-key">介质1折射率(n₁):</span>
<span id="res-n1" class="result-value">1.0</span>
</div>
<div class="result-item">
<span class="result-key">介质2折射率(n₂):</span>
<span id="res-n2" class="result-value">1.5</span>
</div>
<div class="result-item">
<span class="result-key">折射角度(θ₂):</span>
<span id="res-refraction-angle" class="result-value">19.47°</span>
</div>
<div class="result-item">
<span class="result-key">现象说明:</span>
<span id="res-phenomenon" class="result-value">正常折射</span>
</div>
<div class="result-item">
<span class="result-key">斯涅尔定律验证:</span>
<span id="res-snell" class="result-value">n₁sinθ₁ = 0.500,n₂sinθ₂ = 0.500(相等)</span>
</div>
</div>

<script>
// 全局变量初始化
var canvas, ctx, container;
var angleInput, n1Input, n2Input, colorInput;
var angleValue, n1Value, n2Value;
var resIncidentAngle, resN1, resN2, resRefractionAngle, resPhenomenon, resSnell;

// 页面加载完成后初始化
window.onload = function() {
// 获取DOM元素
canvas = document.getElementById('refraction-canvas');
ctx = canvas.getContext('2d');
container = document.getElementById('canvas-container');

// 成果展示框元素
resIncidentAngle = document.getElementById('res-incident-angle');
resN1 = document.getElementById('res-n1');
resN2 = document.getElementById('res-n2');
resRefractionAngle = document.getElementById('res-refraction-angle');
resPhenomenon = document.getElementById('res-phenomenon');
resSnell = document.getElementById('res-snell');

// 控件元素
angleInput = document.getElementById('angle');
n1Input = document.getElementById('n1');
n2Input = document.getElementById('n2');
colorInput = document.getElementById('color');
angleValue = document.getElementById('angle-value');
n1Value = document.getElementById('n1-value');
n2Value = document.getElementById('n2-value');

// 绑定事件(兼容所有浏览器)
angleInput.addEventListener('input', updateAndDraw);
n1Input.addEventListener('input', updateAndDraw);
n2Input.addEventListener('input', updateAndDraw);
colorInput.addEventListener('input', drawRefraction);

// 监听窗口大小变化
window.addEventListener('resize', resizeCanvas);

// 初始化画布和绘制
resizeCanvas();
drawRefraction();
};

// 设置canvas实际分辨率(修复模糊+空白问题)
function resizeCanvas() {
// 强制设置canvas的实际宽高(与容器一致)
canvas.width = container.offsetWidth;
canvas.height = container.offsetHeight;
}

// 更新控件显示并绘制
function updateAndDraw() {
// 更新控件显示值
angleValue.textContent = angleInput.value + "°";
n1Value.textContent = n1Input.value;
n2Value.textContent = n2Input.value;
// 绘制折射效果
drawRefraction();
}

// 核心绘制函数
function drawRefraction() {
// 清空画布(必做,防止重绘重叠)
ctx.clearRect(0, 0, canvas.width, canvas.height);

// 获取参数
var width = canvas.width;
var height = canvas.height;
var centerX = width / 2;
var mediumLineY = height / 2; // 介质分界线
var incidentAngleDeg = parseFloat(angleInput.value); // 入射角(角度)
var incidentAngle = incidentAngleDeg * Math.PI / 180; // 转弧度
var n1 = parseFloat(n1Input.value);
var n2 = parseFloat(n2Input.value);
var lightColor = colorInput.value;

// 1. 绘制介质背景
// 介质1(上半部分)
ctx.fillStyle = 'rgba(173, 216, 230, 0.5)';
ctx.fillRect(0, 0, width, mediumLineY);
// 介质2(下半部分)
ctx.fillStyle = 'rgba(255, 228, 196, 0.5)';
ctx.fillRect(0, mediumLineY, width, height);
// 介质分界线
ctx.strokeStyle = '#333';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.moveTo(0, mediumLineY);
ctx.lineTo(width, mediumLineY);
ctx.stroke();

// 2. 绘制法线(垂直虚线)
ctx.strokeStyle = '#888';
ctx.lineWidth = 1;
ctx.setLineDash([5, 5]);
ctx.beginPath();
ctx.moveTo(centerX, 0);
ctx.lineTo(centerX, height);
ctx.stroke();
ctx.setLineDash([]); // 恢复实线

// 3. 计算入射光线坐标
var incidentLineLength = 200;
var incidentStartX = centerX - incidentLineLength * Math.sin(incidentAngle);
var incidentStartY = mediumLineY - incidentLineLength * Math.cos(incidentAngle);
var incidentEndX = centerX;
var incidentEndY = mediumLineY;

// 4. 斯涅尔定律计算折射角
var refractionAngle = 0;
var refractionAngleDeg = 0;
var hasRefraction = true;
var phenomenon = "正常折射";
var sinTheta1 = Math.sin(incidentAngle);
var sinTheta2 = (n1 / n2) * sinTheta1;

// 全反射判断
if (sinTheta2 > 1) {
refractionAngle = Math.PI - incidentAngle; // 反射角=入射角
refractionAngleDeg = incidentAngleDeg;
hasRefraction = false;
phenomenon = "<span class='warning'>全反射(无折射光线)</span>";
} else {
refractionAngle = Math.asin(sinTheta2);
refractionAngleDeg = refractionAngle * 180 / Math.PI;
}

// 5. 计算折射/反射光线坐标
var refractionLineLength = 200;
var refractionEndX = centerX + refractionLineLength * Math.sin(refractionAngle);
var refractionEndY;
if (hasRefraction) {
refractionEndY = mediumLineY + refractionLineLength * Math.cos(refractionAngle);
} else {
refractionEndY = mediumLineY - refractionLineLength * Math.cos(refractionAngle);
}

// 6. 绘制入射光线
ctx.strokeStyle = lightColor;
ctx.lineWidth = 3;
ctx.beginPath();
ctx.moveTo(incidentStartX, incidentStartY);
ctx.lineTo(incidentEndX, incidentEndY);
drawArrowhead(ctx, incidentEndX, incidentEndY, incidentStartX, incidentStartY, 10);
ctx.stroke();

// 7. 绘制折射/反射光线
ctx.beginPath();
ctx.moveTo(incidentEndX, incidentEndY);
ctx.lineTo(refractionEndX, refractionEndY);
drawArrowhead(ctx, refractionEndX, refractionEndY, incidentEndX, incidentEndY, 10);
ctx.stroke();

// 8. 标注入射角和折射角
drawAngleLabel(ctx, centerX, mediumLineY, incidentAngle, 'θ₁', -incidentLineLength/2);
var refractionLabel = hasRefraction ? 'θ₂' : '全反射';
drawAngleLabel(ctx, centerX, mediumLineY, refractionAngle, refractionLabel, refractionLineLength/2, !hasRefraction);

// 9. 更新成果展示框
resIncidentAngle.textContent = incidentAngleDeg.toFixed(1) + "°";
resN1.textContent = n1.toFixed(1);
resN2.textContent = n2.toFixed(1);

if (hasRefraction) {
resRefractionAngle.textContent = refractionAngleDeg.toFixed(2) + "°";
} else {
resRefractionAngle.innerHTML = "<span class='warning'>-" + incidentAngleDeg.toFixed(1) + "°(反射角)</span>";
}

resPhenomenon.innerHTML = phenomenon;

var n1Sin1 = (n1 * sinTheta1).toFixed(3);
var n2Sin2 = hasRefraction ? (n2 * sinTheta2).toFixed(3) : "无(全反射)";
var snellText;
if (hasRefraction) {
snellText = "n₁sinθ₁ = " + n1Sin1 + ",n₂sinθ₂ = " + n2Sin2 + "(相等)";
} else {
snellText = "n₁sinθ₁ = " + n1Sin1 + " > n₂(满足全反射条件)";
}
resSnell.innerHTML = snellText;
}

// 绘制箭头(辅助函数)
function drawArrowhead(ctx, fromX, fromY, toX, toY, size) {
var angle = Math.atan2(fromY - toY, fromX - toX);
ctx.moveTo(toX, toY);
ctx.lineTo(
toX + size * Math.cos(angle - Math.PI/6),
toY + size * Math.sin(angle - Math.PI/6)
);
ctx.lineTo(
toX + size * Math.cos(angle + Math.PI/6),
toY + size * Math.sin(angle + Math.PI/6)
);
ctx.lineTo(toX, toY);
}

// 绘制角度标注(辅助函数)
function drawAngleLabel(ctx, x, y, angle, label, radius, isReflection) {
if (isReflection === undefined) {
isReflection = false;
}
ctx.fillStyle = '#333';
ctx.font = '16px "Microsoft YaHei", Arial';
var startAngle = isReflection ? Math.PI/2 + angle : Math.PI/2 - angle;
var endAngle = Math.PI/2;

// 绘制角度弧线
ctx.beginPath();
ctx.arc(x, y, radius, startAngle, endAngle, isReflection);
ctx.stroke();

// 绘制标签
var labelX = x + (radius + 20) * Math.cos((startAngle + endAngle)/2);
var labelY = y + (radius + 20) * Math.sin((startAngle + endAngle)/2);
ctx.fillText(label, labelX, labelY);
}
</script>
</body>
</html>

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/15 14:11:19

基于SpringBoot的预制菜调度管控系统设计与实现毕业设计项目源码

题目简介本课题聚焦预制菜行业供应链管理痛点&#xff0c;基于 SpringBoot 框架研发预制菜调度管控系统&#xff0c;旨在解决预制菜从生产、仓储到配送全流程中调度效率低、库存与订单匹配失衡、物流轨迹不可控等问题&#xff0c;实现预制菜供应链的智能化、精细化管控。系统面…

作者头像 李华
网站建设 2026/6/15 15:56:27

谷歌SEO本地排名解密:位置让你入场,但评论决C位

虽然俗话说的好&#xff0c;但对于任何一个实体商家来说&#xff0c;“酒香也怕巷子深”是刻在骨子里的经营焦虑。在数字时代&#xff0c;这条“巷子”就是谷歌地图上的搜索排名。长久以来&#xff0c;一个几乎被奉为圭臬的法则是&#xff1a;离用户越近&#xff0c;排名就越靠…

作者头像 李华
网站建设 2026/5/5 22:25:58

NumPy 字符串函数

NumPy 字符串函数 引言 NumPy 是 Python 中一个强大的科学计算库,它提供了大量的函数和方法来处理数值数据。除了数值计算外,NumPy 也支持字符串操作。本文将详细介绍 NumPy 中的字符串函数,帮助您更好地理解和应用这些函数。 NumPy 字符串函数概述 NumPy 提供了一系列用…

作者头像 李华
网站建设 2026/6/12 11:31:23

光影向善,大爱无界!第44届华鼎奖好莱坞揭晓 安吉丽娜·朱莉榜上有名

时值世界电影诞辰130周年的重要节点&#xff0c;一场汇聚星光与大爱的公益盛会于好莱坞璀璨启幕——第44届全球公益和慈善华鼎奖以发布会形式隆重揭晓获奖名单。作为华鼎奖品牌升级后首次推出的公益专项评选&#xff0c;本届盛典以“影视赋能公益”为核心&#xff0c;打破传统奖…

作者头像 李华
网站建设 2026/6/14 12:19:04

滚珠丝杆直线导轨厂家哪家适配自动化设备高精度传动需求?

自动化设备的精度越来越卷——从3C产品的微小元件装配到半导体的晶圆传输&#xff0c;都需要微米级的定位精度。很多用户问我&#xff1a;“哪些滚珠丝杆直线导轨厂家能适配这种高精度需求&#xff1f;”今天就来聊聊这个话题&#xff0c;结合实际场景&#xff0c;看看什么样的…

作者头像 李华