河池市网站建设_网站建设公司_跨域_seo优化
2025/12/25 20:02:25 网站建设 项目流程

<!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 {

font-family: 'Microsoft YaHei', sans-serif;

display: flex;

flex-direction: column;

align-items: center;

padding: 20px;

background-color: #f4f6f9;

margin: 0;

}

h1 {

color: #2c3e50;

text-align: center;

}

.container {

width: 90%;

max-width: 800px;

display: flex;

flex-direction: column;

gap: 15px;

}

.controls {

display: grid;

grid-template-columns: 1fr 1fr;

gap: 15px;

background-color: #ecf0f1;

padding: 15px;

border-radius: 8px;

}

label {

font-weight: bold;

color: #34495e;

}

input[type="range"],

input[type="number"],

select {

width: 100%;

padding: 8px;

border-radius: 5px;

border: 1px solid #bdc3c7;

font-size: 14px;

}

canvas {

border: 1px solid #ccc;

background-color: #ffffff;

margin-top: 10px;

box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);

border-radius: 4px;

}

.info {

margin-top: 15px;

padding: 12px;

background-color: #d5f5e3;

border-left: 5px solid #2ecc71;

font-size: 15px;

color: #27ae60;

white-space: pre-line;

}

</style>

</head>

<body>

<h1>✨ 光的折射模拟器(斯涅尔定律演示)</h1>

<div class="container">

<div class="controls">

<div>

<label>入射角 θ₁ (度):</label>

<input type="range" id="angleSlider" min="0" max="90" value="30" step="0.1" />

<span id="angleValue">30.0°</span>

</div>

<div>

<label>介质1折射率 n₁:</label>

<input type="number" id="n1Input" step="0.01" min="1.00" max="2.50" value="1.00" />

</div>

<div>

<label>介质2折射率 n₂:</label>

<input type="number" id="n2Input" step="0.01" min="1.00" max="2.50" value="1.50" />

</div>

<div>

<label>光线颜色:</label>

<select id="colorSelect">

<option value="red">🔴 红色</option>

<option value="green">🟢 绿色</option>

<option value="blue">🔵 蓝色</option>

<option value="yellow">🟡 黄色</option>

<option value="magenta">🟣 品红</option>

</select>

</div>

</div>

<canvas id="refractionCanvas" width="800" height="500"></canvas>

<div class="info" id="angleDisplay">

入射角 θ₁ = 30.0°

折射角 θ₂ = 19.5°

验证斯涅尔定律:n₁·sinθ₁ ≈ n₂·sinθ₂

</div>

</div>

<!-- 使用国内 CDN 加载 jQuery -->

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

<script>

$(function () {

const canvas = document.getElementById('refractionCanvas');

const ctx = canvas.getContext('2d');

const width = canvas.width;

const height = canvas.height;

// 中间分界线 y 坐标

const boundaryY = height / 2;

function draw() {

const theta1Deg = parseFloat($('#angleSlider').val());

const n1 = parseFloat($('#n1Input').val());

const n2 = parseFloat($('#n2Input').val());

const color = $('#colorSelect').val();

const theta1Rad = (theta1Deg * Math.PI) / 180;

let theta2Rad = 0;

let theta2Deg = 0;

// 斯涅尔定律:n1*sin(θ1) = n2*sin(θ2)

const sinTheta2 = (n1 * Math.sin(theta1Rad)) / n2;

// 判断是否全反射

if (Math.abs(sinTheta2) <= 1) {

theta2Rad = Math.asin(sinTheta2);

theta2Deg = (theta2Rad * 180) / Math.PI;

} else {

theta2Deg = "全反射";

}

// 更新显示角度和公式

$('#angleValue').text(`${theta1Deg.toFixed(1)}°`);

$('#angleDisplay').text(

`入射角 θ₁ = ${theta1Deg.toFixed(1)}°\n` +

`折射角 θ₂ = ${typeof theta2Deg === 'number' ? theta2Deg.toFixed(1) : theta2Deg}°\n` +

`验证斯涅尔定律:n₁·sinθ₁ = n₂·sinθ₂?\n` +

(typeof theta2Deg === 'number'

? `→ ${n1.toFixed(2)} × sin(${theta1Deg.toFixed(1)}°) ≈ ${(n1 * Math.sin(theta1Rad)).toFixed(4)}\n → ${n2.toFixed(2)} × sin(${theta2Deg.toFixed(1)}°) ≈ ${(n2 * Math.sin(theta2Rad)).toFixed(4)}`

: `→ |sin(θ₂)| > 1,发生全反射`)

);

// 清空画布

ctx.clearRect(0, 0, width, height);

// 绘制上下区域

ctx.fillStyle = '#e3f2fd'; // 介质1:浅蓝

ctx.fillRect(0, 0, width, boundaryY);

ctx.fillStyle = '#f3e5f5'; // 介质2:浅紫

ctx.fillRect(0, boundaryY, width, boundaryY);

// 绘制分界线

ctx.beginPath();

ctx.moveTo(0, boundaryY);

ctx.lineTo(width, boundaryY);

ctx.strokeStyle = '#333';

ctx.lineWidth = 2;

ctx.stroke();

// 绘制法线(虚线)

ctx.setLineDash([6, 4]);

ctx.beginPath();

ctx.moveTo(width / 2, 0);

ctx.lineTo(width / 2, height);

ctx.strokeStyle = '#555';

ctx.lineWidth = 1.5;

ctx.stroke();

ctx.setLineDash([]);

// 设置光源位置(在画布左侧上方)

const originX = width / 2;

const originY = boundaryY;

// 绘制入射光线

const incidentLength = 140;

const incidentX = originX - incidentLength * Math.sin(theta1Rad);

const incidentY = originY - incidentLength * Math.cos(theta1Rad);

drawArrow(ctx, incidentX, incidentY, originX, originY, color, 3);

// 如果没有全反射,绘制折射光线;否则绘制反射光线

if (typeof theta2Deg === 'number') {

const refractedLength = 140;

const refractedX = originX + refractedLength * Math.sin(theta2Rad);

const refractedY = originY + refractedLength * Math.cos(theta2Rad);

drawArrow(ctx, originX, originY, refractedX, refractedY, color, 3);

} else {

// 全反射:向上反射

const reflectedLength = 140;

const reflectedX = originX + reflectedLength * Math.sin(theta1Rad);

const reflectedY = originY - reflectedLength * Math.cos(theta1Rad);

drawArrow(ctx, originX, originY, reflectedX, reflectedY, color, 3, true);

}

}

// 绘制带箭头的线段

function drawArrow(context, fromX, fromY, toX, toY, color, lineWidth, isReflection = false) {

context.strokeStyle = color;

context.fillStyle = color;

context.lineWidth = lineWidth;

context.beginPath();

context.moveTo(fromX, fromY);

context.lineTo(toX, toY);

context.stroke();

// 绘制箭头

const headLen = 10;

const angle = Math.atan2(toY - fromY, toX - fromX);

context.beginPath();

context.moveTo(toX, toY);

context.lineTo(

toX - headLen * Math.cos(angle - Math.PI / 6),

toY - headLen * Math.sin(angle - Math.PI / 6)

);

context.lineTo(

toX - headLen * Math.cos(angle + Math.PI / 6),

toY - headLen * Math.sin(angle + Math.PI / 6)

);

context.closePath();

context.fill();

// 反射标记

if (isReflection) {

context.font = '14px Microsoft YaHei';

context.fillStyle = 'red';

context.fillText('反射!', toX + 12, toY - 10);

}

}

// 初始化绘制

draw();

// 绑定所有控件事件

$('#angleSlider, #n1Input, #n2Input, #colorSelect')

.on('input change', draw);

});

</script>

</body>

</html>

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询