Files
dsProject/dsLightRag/static/deepseek_html_20250812_5fd0ec.html

769 lines
27 KiB
HTML
Raw Normal View History

2025-08-14 15:45:08 +08:00
<!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://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
}
body {
display: flex;
background: linear-gradient(135deg, #1a2a6c, #2c3e50);
color: #fff;
min-height: 100vh;
overflow: hidden;
}
/* 左侧控制面板样式 */
.control-panel {
width: 320px;
background: rgba(25, 35, 65, 0.85);
padding: 20px;
box-shadow: 5px 0 15px rgba(0, 0, 0, 0.4);
backdrop-filter: blur(10px);
overflow-y: auto;
height: 100vh;
z-index: 10;
}
.panel-title {
text-align: center;
margin-bottom: 25px;
padding-bottom: 15px;
border-bottom: 2px solid #3498db;
color: #4ecdc4;
font-size: 24px;
text-shadow: 0 0 10px rgba(78, 205, 196, 0.5);
}
.panel-description {
text-align: center;
margin-bottom: 20px;
color: #bdc3c7;
font-size: 16px;
line-height: 1.5;
}
.control-section {
margin-bottom: 25px;
padding: 15px;
background: rgba(30, 40, 70, 0.6);
border-radius: 10px;
border: 1px solid rgba(52, 152, 219, 0.3);
}
.section-title {
color: #3498db;
margin-bottom: 15px;
font-size: 18px;
display: flex;
align-items: center;
}
.section-title i {
margin-right: 10px;
font-size: 20px;
}
.control-group {
margin-bottom: 15px;
}
label {
display: block;
margin-bottom: 8px;
color: #ecf0f1;
font-weight: 500;
}
input[type="range"] {
width: 100%;
margin-top: 5px;
height: 6px;
background: #2c3e50;
border-radius: 3px;
outline: none;
-webkit-appearance: none;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 18px;
height: 18px;
background: #3498db;
border-radius: 50%;
cursor: pointer;
}
.value-display {
display: flex;
justify-content: space-between;
color: #bdc3c7;
font-size: 14px;
margin-top: 5px;
}
.checkbox-group {
display: flex;
align-items: center;
margin-bottom: 12px;
}
.checkbox-group input {
margin-right: 10px;
width: 18px;
height: 18px;
cursor: pointer;
}
.checkbox-group label {
margin-bottom: 0;
cursor: pointer;
}
.btn-group {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-top: 15px;
}
button {
flex: 1;
min-width: 120px;
padding: 12px 15px;
background: linear-gradient(to right, #3498db, #2980b9);
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
font-weight: 600;
transition: all 0.3s ease;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.2);
}
button:hover {
background: linear-gradient(to right, #2980b9, #2573a7);
transform: translateY(-2px);
box-shadow: 0 6px 8px rgba(0, 0, 0, 0.3);
}
button:active {
transform: translateY(1px);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}
.axis-btn-group {
display: flex;
gap: 10px;
}
.axis-btn-group button {
flex: 1;
padding: 10px;
min-width: auto;
}
/* 右侧主展示区样式 */
.main-display {
flex: 1;
display: flex;
flex-direction: column;
position: relative;
padding: 20px;
}
.display-header {
text-align: center;
margin-bottom: 20px;
z-index: 5;
}
.main-title {
font-size: 32px;
color: #4ecdc4;
margin-bottom: 10px;
text-shadow: 0 0 15px rgba(78, 205, 196, 0.7);
}
.main-description {
font-size: 18px;
color: #ecf0f1;
max-width: 800px;
margin: 0 auto;
line-height: 1.6;
}
#crystal-container {
flex: 1;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
background: rgba(10, 20, 40, 0.4);
border: 1px solid rgba(52, 152, 219, 0.2);
}
.interaction-hint {
text-align: center;
padding: 15px;
background: rgba(25, 35, 65, 0.7);
border-radius: 8px;
margin-top: 20px;
color: #bdc3c7;
font-size: 16px;
border: 1px solid rgba(52, 152, 219, 0.3);
}
.legend {
display: flex;
justify-content: center;
gap: 30px;
margin-top: 20px;
padding: 10px;
}
.legend-item {
display: flex;
align-items: center;
gap: 8px;
}
.legend-color {
width: 20px;
height: 20px;
border-radius: 50%;
}
.na-color {
background: #3498db;
}
.cl-color {
background: #2ecc71;
}
.lattice-color {
background: #e74c3c;
width: 25px;
height: 3px;
border-radius: 0;
}
/* 响应式设计 */
@media (max-width: 1024px) {
body {
flex-direction: column;
}
.control-panel {
width: 100%;
height: auto;
max-height: 50vh;
}
.main-display {
height: 50vh;
}
}
/* 装饰元素 */
.science-icon {
position: absolute;
opacity: 0.05;
font-size: 200px;
color: #3498db;
z-index: 0;
}
.icon-1 { top: 10%; left: 35%; }
.icon-2 { top: 40%; left: 70%; }
.icon-3 { top: 70%; left: 20%; }
</style>
</head>
<body>
<!-- 左侧控制面板 -->
<div class="control-panel">
<h1 class="panel-title">岩盐结构</h1>
<p class="panel-description">NaCl晶体模型交互演示</p>
<!-- 离子半径设置 -->
<div class="control-section">
<h2 class="section-title">离子半径设置</h2>
<div class="control-group">
<label for="na-radius">钠离子半径</label>
<input type="range" id="na-radius" min="0.1" max="0.5" step="0.01" value="0.3">
<div class="value-display">
<span>0.1</span>
<span id="na-value">0.3</span>
<span>0.5</span>
</div>
</div>
<div class="control-group">
<label for="cl-radius">氯离子半径</label>
<input type="range" id="cl-radius" min="0.1" max="0.7" step="0.01" value="0.45">
<div class="value-display">
<span>0.1</span>
<span id="cl-value">0.45</span>
<span>0.7</span>
</div>
</div>
</div>
<!-- 视图控制 -->
<div class="control-section">
<h2 class="section-title">视图控制</h2>
<div class="checkbox-group">
<input type="checkbox" id="show-ions" checked>
<label for="show-ions">显示/隐藏离子</label>
</div>
<div class="checkbox-group">
<input type="checkbox" id="show-lattice" checked>
<label for="show-lattice">显示/隐藏晶胞</label>
</div>
<div class="btn-group">
<button id="show-octa">显示八面体</button>
<button id="only-octa">仅显示八面体</button>
<button id="cut-cell">切八分之一晶胞</button>
<button id="reset-view">重置视图</button>
</div>
</div>
<!-- 观察视角 -->
<div class="control-section">
<h2 class="section-title">观察视角</h2>
<div class="axis-btn-group">
<button id="view-x">X轴</button>
<button id="view-y">Y轴</button>
<button id="view-z">Z轴</button>
</div>
</div>
<div class="control-section">
<h2 class="section-title">化学知识</h2>
<p style="color: #ecf0f1; line-height: 1.6; font-size: 15px;">
氯化钠晶体属于面心立方结构,其中钠离子(Na⁺)和氯离子(Cl⁻)交替排列。
每个离子周围都有6个带相反电荷的离子形成八面体配位结构。
晶胞是晶体中最小的重复单元边长约为0.564 nm。
</p>
</div>
</div>
<!-- 右侧主展示区 -->
<div class="main-display">
<div class="display-header">
<h1 class="main-title">氯化钠晶胞结构学演示</h1>
<p class="main-description">高中化学交互式教学演示 - 探索岩盐的晶体结构及离子排列方式</p>
</div>
<!-- 3D展示容器 -->
<div id="crystal-container"></div>
<!-- 交互提示 -->
<div class="interaction-hint">
提示您可以使用鼠标拖拽旋转视角滚轮缩放视图按住Shift键平移视图
</div>
<!-- 图例 -->
<div class="legend">
<div class="legend-item">
<div class="legend-color na-color"></div>
<span>钠离子 (Na⁺)</span>
</div>
<div class="legend-item">
<div class="legend-color cl-color"></div>
<span>氯离子 (Cl⁻)</span>
</div>
<div class="legend-item">
<div class="legend-color lattice-color"></div>
<span>晶胞边界</span>
</div>
</div>
<!-- 装饰图标 -->
<div class="science-icon icon-1">⚗️</div>
<div class="science-icon icon-2">🧪</div>
<div class="science-icon icon-3">🔬</div>
</div>
<script>
// 主要变量
let scene, camera, renderer, controls;
let naIons = [], clIons = [], latticeLines = [], octahedrons = [];
let naRadius = 0.3, clRadius = 0.45;
let isOctaVisible = false;
// 初始化场景
function init() {
// 创建场景
scene = new THREE.Scene();
scene.background = new THREE.Color(0x0c1428);
// 创建相机
camera = new THREE.PerspectiveCamera(75, window.innerWidth / (window.innerHeight - 80), 0.1, 1000);
camera.position.set(2, 2, 2);
// 创建渲染器
const container = document.getElementById('crystal-container');
renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setSize(container.clientWidth, container.clientHeight);
container.appendChild(renderer.domElement);
// 添加轨道控制
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.05;
// 添加光源
const ambientLight = new THREE.AmbientLight(0x404040, 1.5);
scene.add(ambientLight);
const directionalLight1 = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight1.position.set(1, 1, 1);
scene.add(directionalLight1);
const directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.5);
directionalLight2.position.set(-1, -1, -1);
scene.add(directionalLight2);
// 创建坐标轴辅助
const axesHelper = new THREE.AxesHelper(2);
scene.add(axesHelper);
// 创建晶胞结构
createCrystalStructure();
// 添加事件监听器
setupEventListeners();
// 开始动画循环
animate();
// 窗口大小调整监听
window.addEventListener('resize', onWindowResize);
}
// 创建氯化钠晶胞结构
function createCrystalStructure() {
// 清除现有对象
naIons.forEach(ion => scene.remove(ion));
clIons.forEach(ion => scene.remove(ion));
latticeLines.forEach(line => scene.remove(line));
octahedrons.forEach(octa => scene.remove(octa));
naIons = [];
clIons = [];
latticeLines = [];
octahedrons = [];
// 钠离子位置(面心立方)
const naPositions = [
[0, 0, 0], [0.5, 0.5, 0], [0.5, 0, 0.5], [0, 0.5, 0.5],
[1, 0, 0], [1, 0.5, 0.5], [0.5, 1, 0], [0, 1, 0.5],
[0, 0, 1], [0.5, 0.5, 1], [0.5, 0, 1], [0, 0.5, 1],
[1, 0, 1], [1, 0.5, 1], [0.5, 1, 1], [0, 1, 1]
];
// 氯离子位置(面心立方,偏移)
const clPositions = [
[0.5, 0, 0], [0, 0.5, 0], [0, 0, 0.5], [0.5, 0.5, 0.5],
[0.5, 1, 0], [0, 1, 0.5], [1, 0.5, 0], [1, 0, 0.5],
[0.5, 0, 1], [0, 0.5, 1], [0, 0, 1.5], [0.5, 0.5, 1.5],
[0.5, 1, 1], [0, 1, 1.5], [1, 0.5, 1], [1, 0, 1.5]
];
// 创建钠离子(蓝色)
const naGeometry = new THREE.SphereGeometry(naRadius, 32, 32);
const naMaterial = new THREE.MeshPhongMaterial({
color: 0x3498db,
shininess: 100,
specular: 0xffffff
});
naPositions.forEach(pos => {
const naIon = new THREE.Mesh(naGeometry, naMaterial);
naIon.position.set(pos[0], pos[1], pos[2]);
scene.add(naIon);
naIons.push(naIon);
});
// 创建氯离子(绿色)
const clGeometry = new THREE.SphereGeometry(clRadius, 32, 32);
const clMaterial = new THREE.MeshPhongMaterial({
color: 0x2ecc71,
shininess: 100,
specular: 0xffffff
});
clPositions.forEach(pos => {
const clIon = new THREE.Mesh(clGeometry, clMaterial);
clIon.position.set(pos[0], pos[1], pos[2]);
scene.add(clIon);
clIons.push(clIon);
});
// 创建晶胞边界(红色线框)
const latticeMaterial = new THREE.LineBasicMaterial({ color: 0xe74c3c });
// 底部
createLatticeLine([0,0,0], [1,0,0], latticeMaterial);
createLatticeLine([1,0,0], [1,0,1], latticeMaterial);
createLatticeLine([1,0,1], [0,0,1], latticeMaterial);
createLatticeLine([0,0,1], [0,0,0], latticeMaterial);
// 顶部
createLatticeLine([0,1,0], [1,1,0], latticeMaterial);
createLatticeLine([1,1,0], [1,1,1], latticeMaterial);
createLatticeLine([1,1,1], [0,1,1], latticeMaterial);
createLatticeLine([0,1,1], [0,1,0], latticeMaterial);
// 侧面
createLatticeLine([0,0,0], [0,1,0], latticeMaterial);
createLatticeLine([1,0,0], [1,1,0], latticeMaterial);
createLatticeLine([1,0,1], [1,1,1], latticeMaterial);
createLatticeLine([0,0,1], [0,1,1], latticeMaterial);
// 创建八面体结构(中心位置)
createOctahedron(0.5, 0.5, 0.5);
}
// 创建晶格线
function createLatticeLine(start, end, material) {
const points = [];
points.push(new THREE.Vector3(start[0], start[1], start[2]));
points.push(new THREE.Vector3(end[0], end[1], end[2]));
const geometry = new THREE.BufferGeometry().setFromPoints(points);
const line = new THREE.Line(geometry, material);
scene.add(line);
latticeLines.push(line);
}
// 创建八面体结构
function createOctahedron(x, y, z) {
const octaGroup = new THREE.Group();
// 中心钠离子
const centerGeometry = new THREE.SphereGeometry(naRadius * 1.2, 32, 32);
const centerMaterial = new THREE.MeshPhongMaterial({
color: 0x3498db,
emissive: 0x0044aa,
shininess: 100
});
const centerIon = new THREE.Mesh(centerGeometry, centerMaterial);
centerIon.position.set(x, y, z);
octaGroup.add(centerIon);
// 六个氯离子(八面体顶点)
const vertices = [
[x, y, z - 0.7], // 下方
[x, y, z + 0.7], // 上方
[x, y - 0.7, z], // 前方
[x, y + 0.7, z], // 后方
[x - 0.7, y, z], // 左侧
[x + 0.7, y, z] // 右侧
];
const vertexGeometry = new THREE.SphereGeometry(clRadius * 1.2, 32, 32);
const vertexMaterial = new THREE.MeshPhongMaterial({
color: 0x2ecc71,
emissive: 0x008844,
shininess: 100
});
vertices.forEach(v => {
const vertex = new THREE.Mesh(vertexGeometry, vertexMaterial);
vertex.position.set(v[0], v[1], v[2]);
octaGroup.add(vertex);
});
// 八面体边(连接中心到顶点)
const edgeMaterial = new THREE.LineBasicMaterial({
color: 0xf39c12,
linewidth: 2,
transparent: true,
opacity: 0.7
});
vertices.forEach(v => {
const points = [];
points.push(new THREE.Vector3(x, y, z));
points.push(new THREE.Vector3(v[0], v[1], v[2]));
const geometry = new THREE.BufferGeometry().setFromPoints(points);
const line = new THREE.Line(geometry, edgeMaterial);
octaGroup.add(line);
});
// 八面体面
const faces = [
[vertices[0], vertices[2], vertices[4]],
[vertices[0], vertices[2], vertices[5]],
[vertices[0], vertices[3], vertices[4]],
[vertices[0], vertices[3], vertices[5]],
[vertices[1], vertices[2], vertices[4]],
[vertices[1], vertices[2], vertices[5]],
[vertices[1], vertices[3], vertices[4]],
[vertices[1], vertices[3], vertices[5]]
];
const faceMaterial = new THREE.MeshBasicMaterial({
color: 0xf39c12,
transparent: true,
opacity: 0.15,
side: THREE.DoubleSide
});
faces.forEach(face => {
const geometry = new THREE.BufferGeometry();
const vertices = [
new THREE.Vector3(face[0][0], face[0][1], face[0][2]),
new THREE.Vector3(face[1][0], face[1][1], face[1][2]),
new THREE.Vector3(face[2][0], face[2][1], face[2][2])
];
geometry.setFromPoints(vertices);
geometry.computeVertexNormals();
const triangle = new THREE.Mesh(geometry, faceMaterial);
octaGroup.add(triangle);
});
octaGroup.visible = isOctaVisible;
scene.add(octaGroup);
octahedrons.push(octaGroup);
}
// 设置事件监听器
function setupEventListeners() {
// 离子半径控制
document.getElementById('na-radius').addEventListener('input', function() {
naRadius = parseFloat(this.value);
document.getElementById('na-value').textContent = naRadius.toFixed(2);
createCrystalStructure();
});
document.getElementById('cl-radius').addEventListener('input', function() {
clRadius = parseFloat(this.value);
document.getElementById('cl-value').textContent = clRadius.toFixed(2);
createCrystalStructure();
});
// 显示/隐藏离子
document.getElementById('show-ions').addEventListener('change', function() {
const isVisible = this.checked;
naIons.forEach(ion => ion.visible = isVisible);
clIons.forEach(ion => ion.visible = isVisible);
});
// 显示/隐藏晶胞
document.getElementById('show-lattice').addEventListener('change', function() {
latticeLines.forEach(line => line.visible = this.checked);
});
// 显示八面体
document.getElementById('show-octa').addEventListener('click', function() {
isOctaVisible = true;
octahedrons.forEach(octa => octa.visible = true);
});
// 仅显示八面体
document.getElementById('only-octa').addEventListener('click', function() {
isOctaVisible = true;
octahedrons.forEach(octa => octa.visible = true);
naIons.forEach(ion => ion.visible = false);
clIons.forEach(ion => ion.visible = false);
latticeLines.forEach(line => line.visible = false);
document.getElementById('show-ions').checked = false;
document.getElementById('show-lattice').checked = false;
});
// 切八分之一晶胞
document.getElementById('cut-cell').addEventListener('click', function() {
naIons.forEach(ion => {
const pos = ion.position;
ion.visible = (pos.x <= 0.5 && pos.y <= 0.5 && pos.z <= 0.5);
});
clIons.forEach(ion => {
const pos = ion.position;
ion.visible = (pos.x <= 0.5 && pos.y <= 0.5 && pos.z <= 0.5);
});
latticeLines.forEach(line => line.visible = false);
document.getElementById('show-lattice').checked = false;
});
// 重置视图
document.getElementById('reset-view').addEventListener('click', function() {
// 重置相机位置
camera.position.set(2, 2, 2);
camera.lookAt(0, 0, 0);
controls.reset();
// 重置参数
naRadius = 0.3;
clRadius = 0.45;
document.getElementById('na-radius').value = naRadius;
document.getElementById('cl-radius').value = clRadius;
document.getElementById('na-value').textContent = naRadius.toFixed(2);
document.getElementById('cl-value').textContent = clRadius.toFixed(2);
document.getElementById('show-ions').checked = true;
document.getElementById('show-lattice').checked = true;
isOctaVisible = false;
createCrystalStructure();
});
// 视角控制
document.getElementById('view-x').addEventListener('click', function() {
camera.position.set(3, 0, 0);
camera.lookAt(0, 0, 0);
controls.update();
});
document.getElementById('view-y').addEventListener('click', function() {
camera.position.set(0, 3, 0);
camera.lookAt(0, 0, 0);
controls.update();
});
document.getElementById('view-z').addEventListener('click', function() {
camera.position.set(0, 0, 3);
camera.lookAt(0, 0, 0);
controls.update();
});
}
// 窗口大小调整处理
function onWindowResize() {
const container = document.getElementById('crystal-container');
camera.aspect = container.clientWidth / container.clientHeight;
camera.updateProjectionMatrix();
renderer.setSize(container.clientWidth, container.clientHeight);
}
// 动画循环
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
}
// 页面加载完成后初始化
window.addEventListener('load', init);
</script>
</body>
</html>