Gemini 3 pro 体验,太强大了(附带生成的代码)
Google Gemini 3 Pro展示了强大的AI编程能力,通过实例演示了其响应复杂Prompt的能力。用户请求开发一个完整的双人黑八台球HTML游戏,Gemini不仅生成了完整的游戏代码,还解决了初始版本的两个关键问题:1)支持鼠标超出桌面区域的大力度击球操作;2)修复进球后无法继续操作的问题。生成的代码包含物理引擎、游戏状态管理和UI交互,可直接保存为HTML文件运行。该案例展示了Gemi
·
昨晚被很多 AI 博主关于 Google 推出了最新一代的 Gemini 3 Pro 刷屏了。今天恰好有时间就做了一下体验。真的很强大,这就给大家两个例子体会一下。
1. 台球小游戏HTML
Prompt
黑八才十六台球游戏网页,完整实现对局功能,支持双人对局,通过仿真球杆操作
第一次的 prompt 生成的代码出现了两个 bug,进行第二次对话:
我测试了,遇到几个问题:
1. 超过台球桌的范围就无法操控,不便于进行不同力度的打击;
2. 进了一球以后就无法进行后续操作
Gemini 3 Pro 给出的代码
可以创建一个 html 文件,然后一键复制以下代码,进行尝试。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Web 黑八台球 v2.0</title>
<style>
body {
margin: 0;
background-color: #1a1a1a;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: white;
user-select: none; /* 防止拖拽选中文本 */
overflow: hidden; /* 防止拖拽出滚动条 */
}
h2 { margin-bottom: 15px; letter-spacing: 2px; }
#game-wrapper {
position: relative;
padding: 20px;
background: #5c3a21; /* 木纹底色 */
border-radius: 15px;
box-shadow: 0 10px 30px rgba(0,0,0,0.8);
}
canvas {
background-color: #0b6623;
border: 4px solid #3e2714;
border-radius: 4px;
cursor: default; /* 鼠标样式交由JS控制 */
display: block;
}
#ui-layer {
margin-top: 20px;
width: 840px;
display: flex;
justify-content: space-between;
align-items: center;
}
.player-card {
padding: 10px 25px;
background: #333;
border-radius: 8px;
border: 3px solid transparent;
text-align: center;
min-width: 100px;
transition: all 0.3s;
}
.active-turn {
border-color: #f1c40f;
background: #444;
box-shadow: 0 0 15px rgba(241, 196, 15, 0.4);
transform: scale(1.05);
}
.score { font-size: 24px; font-weight: bold; margin-top: 5px; display: block; }
.controls { text-align: center; color: #888; font-size: 12px; }
.btn {
margin-top: 5px;
padding: 8px 20px;
background: #e74c3c;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-weight: bold;
}
.btn:hover { background: #c0392b; }
/* 悬浮提示框 */
#toast {
position: absolute;
top: 40%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0, 0, 0, 0.85);
color: #fff;
padding: 20px 40px;
border-radius: 10px;
font-size: 24px;
font-weight: bold;
pointer-events: none;
opacity: 0;
transition: opacity 0.3s;
border: 2px solid #f1c40f;
z-index: 10;
}
</style>
</head>
<body>
<h2>🎱 仿真黑八台球</h2>
<div id="game-wrapper">
<canvas id="poolCanvas" width="800" height="400"></canvas>
<div id="toast">提示信息</div>
</div>
<div id="ui-layer">
<div id="p1-card" class="player-card active-turn">
玩家 1 (实心)<br><span class="score" id="p1-score">0</span>
</div>
<div class="controls">
<p>移动鼠标瞄准 | 按住左键拖拽蓄力 | 松开击球</p>
<p>支持鼠标移出桌面进行大力度拉杆</p>
<button class="btn" onclick="game.reset()">重置比赛</button>
</div>
<div id="p2-card" class="player-card">
玩家 2 (花色)<br><span class="score" id="p2-score">0</span>
</div>
</div>
<script>
// --- 基础数学库 ---
const Vector = {
new: (x, y) => ({x, y}),
add: (v1, v2) => ({x: v1.x + v2.x, y: v1.y + v2.y}),
sub: (v1, v2) => ({x: v1.x - v2.x, y: v1.y - v2.y}),
mult: (v, n) => ({x: v.x * n, y: v.y * n}),
dot: (v1, v2) => v1.x * v2.x + v1.y * v2.y,
mag: (v) => Math.sqrt(v.x * v.x + v.y * v.y),
normalize: (v) => {
let m = Math.sqrt(v.x * v.x + v.y * v.y);
return m === 0 ? {x:0, y:0} : {x: v.x/m, y: v.y/m};
},
dist: (v1, v2) => Math.sqrt((v1.x-v2.x)**2 + (v1.y-v2.y)**2)
};
// --- 游戏配置 ---
const CONFIG = {
WIDTH: 800,
HEIGHT: 400,
BALL_R: 10,
POCKET_R: 22,
FRICTION: 0.988, // 地面摩擦
WALL_BOUNCE: 0.85, // 墙壁弹性
MAX_POWER: 25, // 最大力度
POWER_SCALE: 0.15 // 拉杆距离转力度的比例
};
// --- 游戏状态管理 ---
const game = {
canvas: document.getElementById('poolCanvas'),
ctx: null,
balls: [],
whiteBall: null,
pockets: [],
// 状态标志
state: {
isMoving: false, // 球是否在滚动
isAiming: false, // 是否在瞄准(鼠标未按下)
isCharging: false, // 是否在蓄力(鼠标按下)
turn: 1, // 当前玩家 1 或 2
p1Score: 0,
p2Score: 0,
gameOver: false,
turnInfo: {
pottedAny: false, // 本回合是否进球
foul: false // 本回合是否犯规
}
},
// 鼠标输入
input: {
x: 0,
y: 0,
mouseDownX: 0,
mouseDownY: 0
},
init() {
this.ctx = this.canvas.getContext('2d');
this.setupInputs();
this.setupPockets();
this.reset();
this.loop();
},
setupPockets() {
// 6个球袋位置
this.pockets = [
Vector.new(0, 0), Vector.new(CONFIG.WIDTH/2, 0), Vector.new(CONFIG.WIDTH, 0),
Vector.new(0, CONFIG.HEIGHT), Vector.new(CONFIG.WIDTH/2, CONFIG.HEIGHT), Vector.new(CONFIG.WIDTH, CONFIG.HEIGHT)
];
},
// 重点修复:鼠标事件绑定到 window 以支持出界操作
setupInputs() {
window.addEventListener('mousemove', (e) => {
const rect = this.canvas.getBoundingClientRect();
// 即使移出canvas,也要计算相对于canvas的坐标
this.input.x = e.clientX - rect.left;
this.input.y = e.clientY - rect.top;
});
window.addEventListener('mousedown', (e) => {
if (this.state.isMoving || this.state.gameOver) return;
// 只有当鼠标在canvas范围内按下时才开始蓄力,或者放宽限制?
// 最好是:只要还没开始动,点击哪里都可以开始拖拽,或者限制在桌内。
// 这里限制:必须在canvas内部按下才能开始蓄力,但可以拖出去。
const rect = this.canvas.getBoundingClientRect();
const inX = e.clientX - rect.left;
const inY = e.clientY - rect.top;
if (inX >= 0 && inX <= CONFIG.WIDTH && inY >= 0 && inY <= CONFIG.HEIGHT) {
this.state.isCharging = true;
this.state.isAiming = false;
}
});
window.addEventListener('mouseup', (e) => {
if (this.state.isCharging) {
this.shoot();
this.state.isCharging = false;
}
});
},
reset() {
this.balls = [];
this.state.p1Score = 0;
this.state.p2Score = 0;
this.state.turn = 1;
this.state.gameOver = false;
this.state.isMoving = false;
this.updateUI();
this.hideToast();
// 白球
this.whiteBall = { x: 200, y: 200, vx: 0, vy: 0, color: '#fff', id: 0, active: true };
this.balls.push(this.whiteBall);
// 生成台球堆 (简单的金字塔)
const startX = 600;
const startY = 200;
const r = CONFIG.BALL_R;
const rows = 5;
let idCounter = 1;
// 简化的颜色/ID逻辑:8号球必须在中间,其他随意混排
// 这里为了简单,不严格区分花色位置,只保证8号球位置
// 实际规则中:角球通常一花一色
let positions = [];
for(let i=0; i<rows; i++) {
for(let j=0; j<=i; j++) {
let x = startX + i * (r * 1.732) + Math.random(); // 加微小抖动防止物理死锁
let y = startY - i * r + j * (r * 2) + Math.random();
positions.push({x, y});
}
}
// 分配ID
// 8号球是第5个位置 (索引4,第三排中间)
let ids = [1, 9, 2, 10, 8, 3, 11, 7, 14, 4, 5, 13, 15, 6, 12];
positions.forEach((pos, index) => {
let id = ids[index];
let color = this.getBallColor(id);
this.balls.push({
x: pos.x, y: pos.y,
vx: 0, vy: 0,
color: color,
id: id,
active: true
});
});
},
getBallColor(id) {
if(id === 8) return '#000';
if(id === 0) return '#fff';
const colors = ['#e6b333', '#3498db', '#e74c3c', '#9b59b6', '#e67e22', '#2ecc71', '#800000'];
return colors[(id - 1) % 7];
},
shoot() {
if (!this.whiteBall.active) return;
// 计算力度向量
// 逻辑:鼠标当前位置 -> 白球位置 = 施力方向
// 距离 = 力度
let mouseV = Vector.new(this.input.x, this.input.y);
let ballV = Vector.new(this.whiteBall.x, this.whiteBall.y);
let aimDir = Vector.sub(ballV, mouseV); // 方向:鼠标指向白球
let dist = Vector.mag(aimDir);
// 限制最大力度
let power = dist * CONFIG.POWER_SCALE;
if (power > CONFIG.MAX_POWER) power = CONFIG.MAX_POWER;
if (power < 0.2) return; // 防止误触
let normalDir = Vector.normalize(aimDir);
let velocity = Vector.mult(normalDir, power);
this.whiteBall.vx = velocity.x;
this.whiteBall.vy = velocity.y;
// 重置回合状态
this.state.turnInfo.pottedAny = false;
this.state.turnInfo.foul = false;
},
update() {
let moving = false;
// 1. 物理更新
this.balls.forEach(b => {
if (!b.active) return;
// 移动
b.x += b.vx;
b.y += b.vy;
// 摩擦力
b.vx *= CONFIG.FRICTION;
b.vy *= CONFIG.FRICTION;
// 停止阈值
if (Math.abs(b.vx) < 0.05 && Math.abs(b.vy) < 0.05) {
b.vx = 0; b.vy = 0;
} else {
moving = true;
}
// 墙壁碰撞
if (b.x < CONFIG.BALL_R) { b.x = CONFIG.BALL_R; b.vx *= -CONFIG.WALL_BOUNCE; }
if (b.x > CONFIG.WIDTH - CONFIG.BALL_R) { b.x = CONFIG.WIDTH - CONFIG.BALL_R; b.vx *= -CONFIG.WALL_BOUNCE; }
if (b.y < CONFIG.BALL_R) { b.y = CONFIG.BALL_R; b.vy *= -CONFIG.WALL_BOUNCE; }
if (b.y > CONFIG.HEIGHT - CONFIG.BALL_R) { b.y = CONFIG.HEIGHT - CONFIG.BALL_R; b.vy *= -CONFIG.WALL_BOUNCE; }
});
// 2. 球球碰撞 (多次迭代以提高稳定性)
for(let iter=0; iter<8; iter++) {
for (let i = 0; i < this.balls.length; i++) {
for (let j = i + 1; j < this.balls.length; j++) {
let b1 = this.balls[i];
let b2 = this.balls[j];
if (!b1.active || !b2.active) continue;
let dx = b2.x - b1.x;
let dy = b2.y - b1.y;
let dist = Math.sqrt(dx*dx + dy*dy);
if (dist < CONFIG.BALL_R * 2) {
// 碰撞发生
let angle = Math.atan2(dy, dx);
let sin = Math.sin(angle);
let cos = Math.cos(angle);
// 旋转坐标系
let pos1 = {x: 0, y: 0};
let pos2 = {x: dx * cos + dy * sin, y: dy * cos - dx * sin};
let vel1 = {x: b1.vx * cos + b1.vy * sin, y: b1.vy * cos - b1.vx * sin};
let vel2 = {x: b2.vx * cos + b2.vy * sin, y: b2.vy * cos - b2.vx * sin};
// 碰撞反应 (一维弹性碰撞)
let vxTotal = vel1.x - vel2.x;
vel1.x = ((vel1.x - vel2.x) + vel2.x); // 简化:等质量交换速度
// 实际上等质量完全弹性碰撞:v1_new = v2, v2_new = v1
let temp = vel1.x;
vel1.x = vel2.x;
vel2.x = temp;
// 修正重叠 (防止粘连)
let absV = Math.abs(vel1.x) + Math.abs(vel2.x);
let overlap = (CONFIG.BALL_R * 2 - dist) + 0.5; // 加一点额外推力
// 简单的位置修正
let posCorrection = overlap / 2;
pos1.x -= posCorrection;
pos2.x += posCorrection;
// 旋转回原坐标系
let pos1F = {x: pos1.x * cos - pos1.y * sin, y: pos1.y * cos + pos1.x * sin};
let pos2F = {x: pos2.x * cos - pos2.y * sin, y: pos2.y * cos + pos2.x * sin};
// 注意:这里不能直接改 pos,因为 pos 是相对的。
// 更简单的防重叠:直接把两个球推开
let normal = {x: dx/dist, y: dy/dist};
b1.x -= normal.x * (overlap/2);
b1.y -= normal.y * (overlap/2);
b2.x += normal.x * (overlap/2);
b2.y += normal.y * (overlap/2);
b1.vx = vel1.x * cos - vel1.y * sin;
b1.vy = vel1.y * cos + vel1.x * sin;
b2.vx = vel2.x * cos - vel2.y * sin;
b2.vy = vel2.y * cos + vel2.x * sin;
}
}
}
}
// 3. 进袋检测 (每帧都做)
this.balls.forEach(b => {
if (!b.active) return;
for (let p of this.pockets) {
if (Vector.dist(Vector.new(b.x, b.y), p) < CONFIG.POCKET_R) {
this.handlePot(b);
}
}
});
// 4. 状态流转
// 检测到从“运动”变为“静止”的瞬间
if (this.state.isMoving && !moving) {
this.onTurnEnd();
}
this.state.isMoving = moving;
},
handlePot(ball) {
ball.active = false;
if (ball.id === 0) {
// 白球进袋
this.state.turnInfo.foul = true;
this.showToast("白球进袋!犯规!");
// 延迟复位白球,以便视觉上它先消失
setTimeout(() => {
this.whiteBall.active = true;
this.whiteBall.x = 200;
this.whiteBall.y = 200;
this.whiteBall.vx = 0;
this.whiteBall.vy = 0;
// 防止复位时重叠
// (简单起见不检测重叠,真实游戏需检测)
}, 500);
} else if (ball.id === 8) {
// 黑8进袋
let myScore = this.state.turn === 1 ? this.state.p1Score : this.state.p2Score;
// 简单规则:如果不满7球进黑8判负,满了判胜
// 这里简化:进了黑8游戏结束
if (myScore < 7) {
this.showToast(`黑8提前进袋!玩家 ${this.state.turn} 判负!`);
} else {
this.showToast(`恭喜!玩家 ${this.state.turn} 获胜!`);
}
this.state.gameOver = true;
} else {
// 普通球
this.state.turnInfo.pottedAny = true;
if (this.state.turn === 1) this.state.p1Score++;
else this.state.p2Score++;
}
this.updateUI();
},
onTurnEnd() {
if (this.state.gameOver) return;
// 回合逻辑判断
let switchTurn = true;
if (this.state.turnInfo.foul) {
switchTurn = true; // 犯规一定换人
} else if (this.state.turnInfo.pottedAny) {
switchTurn = false; // 进球且没犯规,连杆
this.showToast(`漂亮!玩家 ${this.state.turn} 继续击球`);
}
if (switchTurn) {
this.state.turn = this.state.turn === 1 ? 2 : 1;
this.updateUI();
}
},
draw() {
this.ctx.clearRect(0, 0, CONFIG.WIDTH, CONFIG.HEIGHT);
// 绘制球袋
this.ctx.fillStyle = '#111';
this.pockets.forEach(p => {
this.ctx.beginPath();
this.ctx.arc(p.x, p.y, CONFIG.POCKET_R, 0, Math.PI*2);
this.ctx.fill();
});
// 绘制球杆/瞄准线 (仅当静止且白球在场且未结束)
if (!this.state.isMoving && this.whiteBall.active && !this.state.gameOver) {
this.drawCue();
}
// 绘制球
this.balls.forEach(b => {
if(b.active) this.drawBall(b);
});
},
drawBall(b) {
this.ctx.beginPath();
this.ctx.arc(b.x, b.y, CONFIG.BALL_R, 0, Math.PI*2);
this.ctx.fillStyle = b.color;
this.ctx.fill();
// 简单的球体阴影/高光
this.ctx.strokeStyle = "rgba(0,0,0,0.3)";
this.ctx.lineWidth = 1;
this.ctx.stroke();
this.ctx.beginPath();
this.ctx.arc(b.x - 3, b.y - 3, 2, 0, Math.PI*2);
this.ctx.fillStyle = "rgba(255,255,255,0.5)";
this.ctx.fill();
// 花色球条纹 (ID > 8)
if (b.id > 8) {
this.ctx.beginPath();
this.ctx.arc(b.x, b.y, CONFIG.BALL_R - 2, 0, Math.PI*2);
this.ctx.strokeStyle = "rgba(255,255,255,0.8)";
this.ctx.lineWidth = 2;
this.ctx.stroke();
}
if (b.id !== 0) {
this.ctx.fillStyle = (b.id === 8 || b.color === '#000') ? 'white' : 'black';
this.ctx.font = "10px Arial";
this.ctx.textAlign = "center";
this.ctx.textBaseline = "middle";
this.ctx.fillText(b.id, b.x, b.y);
}
},
drawCue() {
let mouseV = Vector.new(this.input.x, this.input.y);
let ballV = Vector.new(this.whiteBall.x, this.whiteBall.y);
// 计算角度:鼠标指向白球
let angle = Math.atan2(ballV.y - mouseV.y, ballV.x - mouseV.x);
this.ctx.save();
this.ctx.translate(this.whiteBall.x, this.whiteBall.y);
this.ctx.rotate(angle);
// 1. 瞄准线 (向前延伸)
this.ctx.beginPath();
this.ctx.strokeStyle = "rgba(255, 255, 255, 0.4)";
this.ctx.setLineDash([4, 4]);
this.ctx.moveTo(0, 0);
this.ctx.lineTo(800, 0); // 瞄准线
this.ctx.stroke();
this.ctx.setLineDash([]);
// 2. 球杆绘制
// 如果正在蓄力,计算拉杆距离
let pullDist = 0;
if (this.state.isCharging) {
// 计算鼠标到白球的距离作为力度参考
let dist = Vector.dist(mouseV, ballV);
// 限制视觉上的最大拉杆距离
let power = dist * CONFIG.POWER_SCALE;
if (power > CONFIG.MAX_POWER) power = CONFIG.MAX_POWER;
// 将力度转换为像素偏移,使得球杆后退
pullDist = power * 5; // 视觉放大系数
// 绘制力度条
this.ctx.fillStyle = this.getPowerColor(power);
this.ctx.fillRect(-10, -20, power * 4, 5); // 简易力度条
}
// 绘制球杆本体 (在白球后方,即负x方向)
const cueOffset = 15 + pullDist;
// 注意:canvas旋转后,x正方向是瞄准方向。球杆应该在 x 负方向。
this.ctx.beginPath();
this.ctx.fillStyle = "#8d5524"; // 杆身
this.ctx.fillRect(-300 - cueOffset, -4, 300, 8);
this.ctx.fillStyle = "#ecf0f1"; // 杆头
this.ctx.fillRect(-5 - cueOffset, -4, 5, 8);
this.ctx.fillStyle = "#e67e22"; // 握把装饰
this.ctx.fillRect(-300 - cueOffset, -4, 80, 8);
this.ctx.restore();
},
getPowerColor(power) {
let p = power / CONFIG.MAX_POWER;
if (p < 0.5) return `rgb(${p*2*255}, 255, 0)`;
return `rgb(255, ${(1-p)*2*255}, 0)`;
},
loop() {
game.update();
game.draw();
requestAnimationFrame(() => game.loop());
},
showToast(msg) {
const t = document.getElementById('toast');
t.innerText = msg;
t.style.opacity = 1;
clearTimeout(this.toastTimer);
this.toastTimer = setTimeout(() => t.style.opacity = 0, 2000);
},
hideToast() {
document.getElementById('toast').style.opacity = 0;
},
updateUI() {
document.getElementById('p1-score').innerText = this.state.p1Score;
document.getElementById('p2-score').innerText = this.state.p2Score;
const p1Card = document.getElementById('p1-card');
const p2Card = document.getElementById('p2-card');
if (this.state.turn === 1) {
p1Card.classList.add('active-turn');
p2Card.classList.remove('active-turn');
} else {
p2Card.classList.add('active-turn');
p1Card.classList.remove('active-turn');
}
}
};
// 启动游戏
game.init();
</script>
</body>
</html>
效果

2. 半导体二极管知识教学HTML
Prompt
我是一名计算机专业教师,正在授课《电子电路技术》。目前授课到半导体部分。
现在设计并创建一个非常有创意的网页。能展示常见的半导体二极管元器件,能进行 3d 的旋转和放大;二极管的基本结构和类型;二极管的伏安特性;二极管的应用举例;
可以使用任何库来完成我需要的效果,但要确保我能把所有内容黏贴到一个单独的 HTML 文件中,并直接在 Chrome 中打开。
我将给你 PPT 和教案做参考。
第一次的对话,自动调用了 Canvas 工具,不过没有预览出效果。
让 Gemini 修复了大概 3 次后,出现了第一次的效果。
认为出现的效果不佳,因此提出修改意见
有一些问题:
1. 授课对象是 xxxx
2. 3d 虚拟元件库上的出现了带叉的方块,是不是字符集没有识别
3. 3d 虚拟元件库增加检波管、检波管、检波管、光电二极管
4. 增加二极管的符号介绍;增加二极管的整流;增加二极管的限幅
Gemini 3 Pro 给出的代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>电子电路技术 - 半导体二极管 3D 交互教学</title>
<!-- 引入 Tailwind CSS 用于美观的 UI -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- 配置 Import Map 以便在浏览器中直接使用 React 和 Three.js 模块 -->
<script type="importmap">
{
"imports": {
"react": "https://esm.sh/react@18.2.0",
"react-dom": "https://esm.sh/react-dom@18.2.0",
"react-dom/client": "https://esm.sh/react-dom@18.2.0/client",
"three": "https://esm.sh/three@0.160.0",
"@react-three/fiber": "https://esm.sh/@react-three/fiber@8.15.14?external=react,react-dom,three",
"@react-three/drei": "https://esm.sh/@react-three/drei@9.96.1?external=react,react-dom,three,@react-three/fiber",
"recharts": "https://esm.sh/recharts@2.10.4?external=react,react-dom",
"lucide-react": "https://esm.sh/lucide-react@0.309.0?external=react,react-dom"
}
}
</script>
<!-- 引入 Babel 用于在浏览器中编译 JSX -->
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<style>
body { margin: 0; background-color: #f8fafc; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; }
.glass-panel {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.2);
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.15);
}
/* 自定义滚动条 */
::-webkit-scrollbar { width: 8px; }
::-webkit-scrollbar-track { background: #f1f1f1; }
::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: #94a3b8; }
/* 简单的淡入动画 */
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.animate-fadeIn {
animation: fadeIn 0.5s ease-out forwards;
}
</style>
</head>
<body>
<div id="root"></div>
<script type="text/babel" data-type="module">
import React, { useState, useRef, useEffect, useMemo } from 'react';
import { createRoot } from 'react-dom/client';
import * as THREE from 'three';
import { Canvas, useFrame } from '@react-three/fiber';
import { OrbitControls, Text, Environment, ContactShadows, Float } from '@react-three/drei';
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ReferenceLine, ResponsiveContainer, ReferenceArea } from 'recharts';
import { Zap, BookOpen, Activity, PenTool, Power, ChevronRight, RotateCw, Info, PlayCircle, RefreshCcw, Waves, Scissors, Sun } from 'lucide-react';
// --- 3D 模型组件 ---
// 注意:3D场景内的文字标签全部改为英文,以修复中文字符集显示乱码的问题。
// 1. 整流二极管 (1N4007 风格)
const RectifierDiode = (props) => {
return (
<group {...props}>
{/* 管体 - 黑色圆柱 */}
<mesh rotation={[0, 0, Math.PI / 2]} position={[0, 0, 0]}>
<cylinderGeometry args={[0.6, 0.6, 2.5, 32]} />
<meshStandardMaterial color="#1a1a1a" roughness={0.4} metalness={0.1} />
</mesh>
{/* 银色色环 (阴极) */}
<mesh rotation={[0, 0, Math.PI / 2]} position={[0.8, 0, 0]}>
<cylinderGeometry args={[0.61, 0.61, 0.4, 32]} />
<meshStandardMaterial color="#e2e8f0" roughness={0.3} metalness={0.8} />
</mesh>
{/* 引脚 */}
<mesh rotation={[0, 0, Math.PI / 2]} position={[-2.25, 0, 0]}>
<cylinderGeometry args={[0.1, 0.1, 2, 16]} />
<meshStandardMaterial color="#cbd5e1" metalness={0.9} roughness={0.1} />
</mesh>
<mesh rotation={[0, 0, Math.PI / 2]} position={[2.25, 0, 0]}>
<cylinderGeometry args={[0.1, 0.1, 2, 16]} />
<meshStandardMaterial color="#cbd5e1" metalness={0.9} roughness={0.1} />
</mesh>
{/* 英文标签 */}
<Text position={[-1.5, 1, 0]} fontSize={0.3} color="#334155">Anode (+)</Text>
<Text position={[1.5, 1, 0]} fontSize={0.3} color="#334155">Cathode (-)</Text>
</group>
);
};
// 2. 发光二极管 (LED)
const LED = ({ color = "#ef4444", active }) => {
return (
<group rotation={[0, 0, 0]} position={[0, -0.5, 0]}>
{/* 灯体 */}
<mesh position={[0, 1, 0]}>
<cylinderGeometry args={[0.8, 0.8, 1.5, 32]} />
<meshPhysicalMaterial
color={color}
transparent
opacity={0.8}
transmission={0.5}
roughness={0.1}
emissive={active ? color : "#000"}
emissiveIntensity={active ? 2 : 0}
/>
</mesh>
{/* 顶部圆顶 */}
<mesh position={[0, 1.75, 0]}>
<sphereGeometry args={[0.8, 32, 16, 0, Math.PI * 2, 0, Math.PI / 2]} />
<meshPhysicalMaterial
color={color}
transparent
opacity={0.8}
transmission={0.5}
roughness={0.1}
emissive={active ? color : "#000"}
emissiveIntensity={active ? 2 : 0}
/>
</mesh>
{/* 底部边缘 */}
<mesh position={[0, 0.2, 0]}>
<cylinderGeometry args={[0.9, 0.9, 0.2, 32]} />
<meshPhysicalMaterial color={color} transparent opacity={0.9} />
</mesh>
{/* 引脚 (长脚阳极,短脚阴极) */}
<mesh position={[0.3, -1.5, 0]}>
<cylinderGeometry args={[0.08, 0.08, 3.5, 16]} />
<meshStandardMaterial color="#cbd5e1" metalness={0.9} roughness={0.1} />
</mesh>
<mesh position={[-0.3, -1.25, 0]}>
<cylinderGeometry args={[0.08, 0.08, 3, 16]} />
<meshStandardMaterial color="#cbd5e1" metalness={0.9} roughness={0.1} />
</mesh>
<Text position={[1.2, -1, 0]} fontSize={0.25} color="#334155">Long: Pos (+)</Text>
<Text position={[-1.2, -1, 0]} fontSize={0.25} color="#334155">Short: Neg (-)</Text>
</group>
);
};
// 3. 稳压二极管 (玻璃封装)
const ZenerDiode = (props) => {
return (
<group {...props}>
{/* 玻璃管体 */}
<mesh rotation={[0, 0, Math.PI / 2]} position={[0, 0, 0]}>
<cylinderGeometry args={[0.4, 0.4, 1.8, 32]} />
<meshPhysicalMaterial color="#fca5a5" transmission={0.8} opacity={0.6} transparent roughness={0.1} />
</mesh>
{/* 内部黑环 (阴极) */}
<mesh rotation={[0, 0, Math.PI / 2]} position={[0.5, 0, 0]}>
<cylinderGeometry args={[0.38, 0.38, 0.4, 32]} />
<meshStandardMaterial color="#000000" />
</mesh>
{/* 引脚 */}
<mesh rotation={[0, 0, Math.PI / 2]} position={[-1.9, 0, 0]}>
<cylinderGeometry args={[0.08, 0.08, 2, 16]} />
<meshStandardMaterial color="#cbd5e1" metalness={0.9} />
</mesh>
<mesh rotation={[0, 0, Math.PI / 2]} position={[1.9, 0, 0]}>
<cylinderGeometry args={[0.08, 0.08, 2, 16]} />
<meshStandardMaterial color="#cbd5e1" metalness={0.9} />
</mesh>
<Text position={[0, -1, 0]} fontSize={0.3} color="#ef4444">Zener Diode</Text>
<Text position={[1.2, 0.8, 0]} fontSize={0.2} color="gray">Cathode</Text>
</group>
);
};
// 4. 检波二极管 (Detector Diode - 点接触型,玻璃封装)
const DetectorDiode = (props) => {
return (
<group {...props}>
{/* 玻璃管体 - 更透明细长 */}
<mesh rotation={[0, 0, Math.PI / 2]} position={[0, 0, 0]}>
<cylinderGeometry args={[0.3, 0.3, 1.6, 32]} />
<meshPhysicalMaterial color="#e0f2fe" transmission={0.9} opacity={0.4} transparent roughness={0.05} />
</mesh>
{/* 内部触须 (点接触特征) */}
<mesh rotation={[0, 0, Math.PI / 2]} position={[-0.2, 0, 0]}>
<cylinderGeometry args={[0.02, 0.02, 0.8, 8]} />
<meshStandardMaterial color="#fbbf24" />
</mesh>
{/* 晶片 */}
<mesh rotation={[0, 0, Math.PI / 2]} position={[0.3, 0, 0]}>
<boxGeometry args={[0.1, 0.2, 0.2]} />
<meshStandardMaterial color="#334155" />
</mesh>
{/* 阴极标记环 - 绿色 */}
<mesh rotation={[0, 0, Math.PI / 2]} position={[0.5, 0, 0]}>
<cylinderGeometry args={[0.305, 0.305, 0.2, 32]} />
<meshStandardMaterial color="#22c55e" />
</mesh>
{/* 引脚 */}
<mesh rotation={[0, 0, Math.PI / 2]} position={[-1.8, 0, 0]}>
<cylinderGeometry args={[0.06, 0.06, 2, 16]} />
<meshStandardMaterial color="#cbd5e1" metalness={0.9} />
</mesh>
<mesh rotation={[0, 0, Math.PI / 2]} position={[1.8, 0, 0]}>
<cylinderGeometry args={[0.06, 0.06, 2, 16]} />
<meshStandardMaterial color="#cbd5e1" metalness={0.9} />
</mesh>
<Text position={[0, -1, 0]} fontSize={0.3} color="#22c55e">Detector</Text>
</group>
);
};
// 5. 光电二极管 (Photodiode - 顶部受光)
const Photodiode = (props) => {
return (
<group {...props} rotation={[Math.PI/4, 0, 0]} position={[0, -0.5, 0]}>
{/* 黑色方形底座 */}
<mesh position={[0, 0, 0]}>
<boxGeometry args={[1.0, 0.2, 1.0]} />
<meshStandardMaterial color="#1e293b" />
</mesh>
{/* 黑色圆柱体外壳 */}
<mesh position={[0, 0.5, 0]}>
<cylinderGeometry args={[0.4, 0.4, 0.8, 32]} />
<meshStandardMaterial color="#1e293b" />
</mesh>
{/* 顶部受光窗口 (深蓝色/黑色玻璃) */}
<mesh position={[0, 0.91, 0]}>
<cylinderGeometry args={[0.35, 0.35, 0.05, 32]} />
<meshPhysicalMaterial color="#1e3a8a" transmission={0.2} roughness={0.1} metalness={0.8} />
</mesh>
{/* 引脚 */}
<mesh position={[0.2, -1.0, 0]}>
<cylinderGeometry args={[0.05, 0.05, 2, 16]} />
<meshStandardMaterial color="#cbd5e1" metalness={0.9} />
</mesh>
<mesh position={[-0.2, -1.0, 0]}>
<cylinderGeometry args={[0.05, 0.05, 2, 16]} />
<meshStandardMaterial color="#cbd5e1" metalness={0.9} />
</mesh>
<Text position={[0, -1.5, 0]} fontSize={0.3} color="#3b82f6">Photodiode</Text>
</group>
);
};
// --- 功能组件 ---
// 伏安特性曲线图表
const VIChart = () => {
// 模拟硅二极管的 V-I 数据 (结合PPT中的死区0.5V,导通0.7V)
const data = [
{ u: -10, i: -50, region: '击穿区' },
{ u: -8, i: -5, region: '反向击穿' },
{ u: -5, i: -0.1, region: '反向截止' },
{ u: -2, i: 0, region: '反向截止' },
{ u: 0, i: 0, region: '死区' },
{ u: 0.2, i: 0, region: '死区' },
{ u: 0.5, i: 0.1, region: '死区' },
{ u: 0.6, i: 2, region: '导通区' },
{ u: 0.7, i: 15, region: '导通区' },
{ u: 0.8, i: 40, region: '导通区' },
{ u: 0.9, i: 80, region: '导通区' },
];
return (
<div className="w-full h-80 bg-white rounded-lg p-4 shadow-sm border border-slate-100">
<h3 className="text-lg font-bold mb-2 text-slate-700 flex items-center gap-2">
<Activity className="w-5 h-5 text-blue-500"/>
二极管伏安特性曲线 (硅管)
</h3>
<ResponsiveContainer width="100%" height="100%">
<LineChart data={data} margin={{ top: 5, right: 20, bottom: 20, left: 0 }}>
<CartesianGrid strokeDasharray="3 3" stroke="#e2e8f0" />
<XAxis dataKey="u" type="number" domain={[-10, 1]} label={{ value: '电压 U (V)', position: 'insideBottomRight', offset: -5 }} />
<YAxis label={{ value: '电流 I (mA)', angle: -90, position: 'insideLeft' }} />
<Tooltip
contentStyle={{ backgroundColor: 'rgba(255,255,255,0.95)', borderRadius: '8px', border: '1px solid #e2e8f0', boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1)' }}
formatter={(value, name) => [value + (name === 'i' ? ' mA' : ' V'), name === 'i' ? '电流' : '电压']}
/>
<ReferenceLine x={0} stroke="#94a3b8" strokeWidth={2}/>
<ReferenceLine y={0} stroke="#94a3b8" strokeWidth={2}/>
{/* 区域标注 */}
<ReferenceArea x1={0} x2={0.5} stroke="none" fill="#fee2e2" fillOpacity={0.3} label={{ value: "死区(0-0.5V)", position: 'insideTop', fill: '#ef4444', fontSize: 12 }} />
<ReferenceArea x1={0.5} x2={1} stroke="none" fill="#dbeafe" fillOpacity={0.3} label={{ value: "正向导通", position: 'insideTop', fill: '#3b82f6', fontSize: 12 }} />
<ReferenceArea x1={-8} x2={-10} stroke="none" fill="#ffedd5" fillOpacity={0.5} label={{ value: "反向击穿", position: 'insideBottom', fill: '#f97316', fontSize: 12 }} />
<Line type="monotone" dataKey="i" stroke="#3b82f6" strokeWidth={3} dot={{ r: 4 }} activeDot={{ r: 8 }} />
</LineChart>
</ResponsiveContainer>
<div className="flex flex-wrap justify-center gap-4 text-sm text-slate-500 mt-2">
<span className="flex items-center gap-1"><div className="w-3 h-3 bg-red-200 rounded-sm"></div> 死区: 电压太低无法导通</span>
<span className="flex items-center gap-1"><div className="w-3 h-3 bg-blue-200 rounded-sm"></div> 导通区: 电流随电压迅速增大</span>
</div>
</div>
);
};
// 电路仿真组件
const CircuitSimulation = () => {
const [powerOn, setPowerOn] = useState(false);
const [diodeDirection, setDiodeDirection] = useState('forward'); // forward (正向), reverse (反向)
// 判断灯是否亮:开关闭合 且 二极管正向
const isLit = powerOn && diodeDirection === 'forward';
return (
<div className="bg-slate-800 p-6 rounded-xl text-white shadow-lg">
<div className="flex justify-between items-center mb-4">
<h3 className="text-lg font-bold flex items-center gap-2">
<Zap className="w-5 h-5 text-yellow-400"/>
仿真实验:单向导电性
</h3>
<div className="text-xs bg-slate-700 px-2 py-1 rounded text-slate-300">
点击开关和元件进行操作
</div>
</div>
{/* 电路可视化区域 */}
<div className="relative bg-slate-900/50 rounded-xl p-8 border border-slate-700 flex flex-col md:flex-row items-center justify-between gap-8 overflow-hidden">
{/* 导线 - 连接线 */}
<div className="absolute inset-0 pointer-events-none">
<svg className="w-full h-full" style={{zIndex: 0}}>
<path d="M 80 80 L 80 40 L 200 40" stroke={powerOn ? "#facc15" : "#475569"} strokeWidth="4" fill="none" className="transition-colors duration-300"/>
<path d="M 280 40 L 400 40" stroke={powerOn ? "#facc15" : "#475569"} strokeWidth="4" fill="none" className="transition-colors duration-300"/>
<path d="M 480 40 L 600 40 L 600 80" stroke={powerOn && diodeDirection === 'forward' ? "#facc15" : "#475569"} strokeWidth="4" fill="none" className="transition-colors duration-300"/>
</svg>
</div>
{/* 1. 电源 */}
<div className="flex flex-col items-center z-10">
<div className="w-16 h-20 bg-slate-200 rounded-md border-4 border-slate-400 flex flex-col items-center justify-center relative shadow-md">
<div className="w-8 h-2 bg-slate-400 absolute -top-2 rounded-t"></div>
<div className="text-2xl font-bold text-slate-700">DC</div>
<div className="text-xs text-slate-500">5V</div>
<div className="absolute -left-4 top-2 text-red-400 font-bold text-xl">+</div>
</div>
<span className="mt-2 text-sm text-slate-300">直流电源</span>
</div>
{/* 2. 开关 */}
<div
className="flex flex-col items-center z-10 cursor-pointer group"
onClick={() => setPowerOn(!powerOn)}
>
<div className="w-20 h-12 bg-slate-700 border-2 border-slate-500 rounded flex items-center justify-center relative hover:border-blue-400 transition-colors shadow-md">
{/* 开关闸刀 */}
<div
className={`w-12 h-1 bg-white absolute transition-transform duration-300 origin-left ${powerOn ? 'rotate-0' : '-rotate-[30deg]'}`}
style={{left: '20%', top: '50%'}}
></div>
<div className="w-2 h-2 bg-slate-400 rounded-full absolute left-4 top-1/2 -translate-y-1/2"></div>
<div className="w-2 h-2 bg-slate-400 rounded-full absolute right-4 top-1/2 -translate-y-1/2"></div>
</div>
<span className="mt-2 text-sm text-slate-300 group-hover:text-blue-300 transition-colors flex items-center gap-1">
开关 S <PlayCircle className="w-3 h-3"/>
</span>
</div>
{/* 3. 二极管 (可翻转) */}
<div
className="flex flex-col items-center z-10 cursor-pointer group"
onClick={() => setDiodeDirection(prev => prev === 'forward' ? 'reverse' : 'forward')}
>
<div className="w-24 h-12 bg-slate-700 border-2 border-slate-500 rounded flex items-center justify-center hover:border-blue-400 transition-colors shadow-md relative">
<div className={`transition-transform duration-500 ${diodeDirection === 'reverse' ? 'rotate-180' : ''}`}>
{/* 二极管符号 SVG */}
<svg width="50" height="30" viewBox="0 0 50 30" fill="none">
<path d="M0 15 H15 M35 15 H50" stroke="white" strokeWidth="2"/>
<path d="M15 5 L15 25 L35 15 Z" fill="#ef4444" stroke="none"/> {/* 三角形 P区 */}
<line x1="35" y1="5" x2="35" y2="25" stroke="white" strokeWidth="3"/> {/* 竖线 N区 */}
</svg>
</div>
</div>
<span className="mt-2 text-sm text-slate-300 group-hover:text-blue-300 transition-colors flex items-center gap-1">
<RefreshCcw className="w-3 h-3"/>
{diodeDirection === 'forward' ? '正向接法' : '反向接法'}
</span>
</div>
{/* 4. 灯泡 */}
<div className="flex flex-col items-center z-10">
<div className={`w-16 h-16 rounded-full border-4 flex items-center justify-center transition-all duration-300 ${isLit ? 'bg-yellow-200 border-yellow-400 shadow-[0_0_40px_rgba(250,204,21,0.8)]' : 'bg-slate-800 border-slate-600'}`}>
<Zap className={`w-8 h-8 ${isLit ? 'text-yellow-600 fill-yellow-600' : 'text-slate-600'}`} />
</div>
<span className="mt-2 text-sm text-slate-300">负载 (灯泡)</span>
</div>
</div>
{/* 实验结论反馈 */}
<div className="mt-4 bg-slate-700/50 p-4 rounded-lg border-l-4 border-blue-500 transition-all">
<p className="font-bold text-sm text-blue-300 mb-1">实验现象分析:</p>
<div className="text-sm text-slate-300">
{powerOn ? (
diodeDirection === 'forward' ?
"✅ 电路导通:二极管正向偏置(阳极接正,阴极接负),电阻极小,灯泡发光。" :
"❌ 电路截止:二极管反向偏置(阳极接负,阴极接正),电阻极大,灯泡不亮。"
) : "⚠️ 电路断开:请先闭合开关 S。"}
</div>
</div>
</div>
);
};
// 主组件
const App = () => {
const [activeModel, setActiveModel] = useState('rectifier'); // rectifier, led, zener, detector, photodiode
const [activeTab, setActiveTab] = useState('types'); // structure, theory, types
// 预设的模型信息
const modelInfo = {
rectifier: { title: "普通整流二极管", desc: "黑色圆柱体,银色色环代表负极(阴极)。主要用于将交流电变为直流电。" },
led: { title: "发光二极管 (LED)", desc: "长引脚为正极,短引脚为负极。通电后发光,常用于指示灯和照明。" },
zener: { title: "稳压二极管", desc: "通常为玻璃封装,黑色环标记负极。工作在反向击穿区,用于稳定电压。" },
detector: { title: "检波二极管", desc: "点接触型,结电容小。用于从高频信号中检出音频信号(检波)。" },
photodiode: { title: "光电二极管", desc: "受光照控制的反向偏置二极管。光照越强,反向电流(光电流)越大。用于光控开关。" }
};
return (
<div className="min-h-screen pb-10">
{/* 页眉 */}
<header className="bg-gradient-to-r from-blue-700 to-indigo-800 text-white p-6 shadow-lg sticky top-0 z-50">
<div className="container mx-auto flex flex-col md:flex-row justify-between items-center">
<div>
<h1 className="text-2xl md:text-3xl font-bold flex items-center gap-3">
<BookOpen className="w-8 h-8"/>
电子电路技术基础
</h1>
<p className="text-blue-200 mt-2 text-sm md:text-base">第六章:半导体及其常用器件 —— 二极管</p>
</div>
<div className="mt-4 md:mt-0 bg-white/10 px-4 py-2 rounded-full text-xs md:text-sm backdrop-blur-sm border border-white/20">
授课对象:xxxx
</div>
</div>
</header>
<main className="container mx-auto px-4 mt-8 grid grid-cols-1 lg:grid-cols-12 gap-8">
{/* 左侧区域:3D 观察与仿真 (LG: 5 cols) */}
<div className="lg:col-span-5 flex flex-col gap-6">
{/* 3D 展示卡片 */}
<div className="glass-panel rounded-2xl overflow-hidden flex flex-col h-[600px] relative shadow-xl">
<div className="absolute top-4 left-4 z-10 bg-white/90 backdrop-blur px-3 py-1 rounded-full text-sm font-bold text-slate-700 shadow-sm flex items-center gap-2">
<RotateCw className="w-4 h-4 text-blue-500"/> 3D 虚拟元件库
</div>
{/* 模型切换按钮 - 更新布局以适应更多按钮 */}
<div className="absolute top-4 right-4 z-10 flex flex-col gap-2">
{['rectifier', 'led', 'zener', 'detector', 'photodiode'].map(key => (
<button
key={key}
onClick={() => setActiveModel(key)}
className={`px-3 py-1.5 text-xs font-medium rounded-lg shadow-sm transition-all text-left border ${activeModel === key ? 'bg-blue-600 text-white border-blue-600' : 'bg-white/90 text-slate-600 border-slate-200 hover:bg-slate-50'}`}
>
{modelInfo[key].title}
</button>
))}
</div>
<div className="flex-1 bg-gradient-to-b from-slate-100 to-slate-200 cursor-move">
<Canvas camera={{ position: [0, 1, 4], fov: 50 }}>
<Environment preset="city" />
<ambientLight intensity={0.6} />
<pointLight position={[10, 10, 10]} intensity={0.8} />
<pointLight position={[-10, -10, -10]} intensity={0.5} />
<Float speed={2} rotationIntensity={0.5} floatIntensity={0.5}>
{activeModel === 'rectifier' && <RectifierDiode />}
{activeModel === 'led' && <LED active={true} />}
{activeModel === 'zener' && <ZenerDiode />}
{activeModel === 'detector' && <DetectorDiode />}
{activeModel === 'photodiode' && <Photodiode />}
</Float>
<ContactShadows position={[0, -1.5, 0]} opacity={0.4} scale={10} blur={2.5} far={4} />
<OrbitControls enableZoom={true} minPolarAngle={Math.PI/4} maxPolarAngle={Math.PI/1.5} />
</Canvas>
</div>
{/* 模型说明信息 */}
<div className="absolute bottom-0 left-0 right-0 bg-white/90 backdrop-blur-md p-4 border-t border-slate-100">
<h4 className="font-bold text-slate-800 flex items-center gap-2">
<Info className="w-4 h-4 text-blue-500"/>
{modelInfo[activeModel].title}
</h4>
<p className="text-xs text-slate-500 mt-1">{modelInfo[activeModel].desc}</p>
</div>
</div>
{/* 电路仿真卡片 */}
<CircuitSimulation />
</div>
{/* 右侧区域:理论知识与图表 (LG: 7 cols) */}
<div className="lg:col-span-7 flex flex-col gap-6">
{/* 选项卡导航 */}
<div className="flex p-1 bg-slate-200/50 rounded-xl">
{[
{ id: 'types', label: '类型与应用', icon: <PenTool className="w-4 h-4"/> },
{ id: 'theory', label: '伏安特性', icon: <Activity className="w-4 h-4"/> },
{ id: 'structure', label: '结构与原理', icon: <BoxIcon /> },
].map(tab => (
<button
key={tab.id}
onClick={() => setActiveTab(tab.id)}
className={`flex-1 flex items-center justify-center gap-2 py-3 rounded-lg text-sm font-bold transition-all ${activeTab === tab.id ? 'bg-white text-blue-600 shadow-sm ring-1 ring-black/5' : 'text-slate-500 hover:text-slate-700 hover:bg-white/50'}`}
>
{tab.icon}
{tab.label}
</button>
))}
</div>
{/* 内容显示区 */}
<div className="bg-white rounded-2xl p-6 shadow-sm border border-slate-100 min-h-[600px] overflow-y-auto max-h-[calc(100vh-200px)]">
{/* 1. 类型与应用 (包含新增的整流与限幅) */}
{activeTab === 'types' && (
<div className="space-y-8 animate-fadeIn">
<section>
<h2 className="text-xl font-bold text-slate-800 border-l-4 border-green-500 pl-3 mb-4">符号与分类</h2>
{/* 符号展示 */}
<div className="flex justify-around bg-slate-50 p-4 rounded-xl border border-slate-100 mb-6">
<div className="text-center">
<svg width="60" height="40" viewBox="0 0 60 40" className="mx-auto mb-1">
<line x1="0" y1="20" x2="20" y2="20" stroke="black" strokeWidth="2"/>
<path d="M20 10 L20 30 L40 20 Z" fill="none" stroke="black" strokeWidth="2"/>
<line x1="40" y1="10" x2="40" y2="30" stroke="black" strokeWidth="2"/>
<line x1="40" y1="20" x2="60" y2="20" stroke="black" strokeWidth="2"/>
<text x="5" y="10" fontSize="10" fill="gray">+</text>
</svg>
<span className="text-xs text-slate-600 font-bold">普通二极管</span>
</div>
<div className="text-center">
<svg width="60" height="40" viewBox="0 0 60 40" className="mx-auto mb-1">
<line x1="0" y1="20" x2="20" y2="20" stroke="black" strokeWidth="2"/>
<path d="M20 10 L20 30 L40 20 Z" fill="none" stroke="black" strokeWidth="2"/>
<polyline points="36,10 40,10 40,30 44,30" fill="none" stroke="black" strokeWidth="2"/>
<line x1="40" y1="20" x2="60" y2="20" stroke="black" strokeWidth="2"/>
</svg>
<span className="text-xs text-slate-600 font-bold">稳压二极管</span>
</div>
<div className="text-center">
<svg width="60" height="40" viewBox="0 0 60 40" className="mx-auto mb-1">
<line x1="0" y1="20" x2="20" y2="20" stroke="black" strokeWidth="2"/>
<path d="M20 10 L20 30 L40 20 Z" fill="none" stroke="black" strokeWidth="2"/>
<line x1="40" y1="10" x2="40" y2="30" stroke="black" strokeWidth="2"/>
<line x1="40" y1="20" x2="60" y2="20" stroke="black" strokeWidth="2"/>
<path d="M25 12 L15 2 M30 12 L20 2" stroke="black" strokeWidth="1.5" markerEnd="url(#arrow)"/>
</svg>
<span className="text-xs text-slate-600 font-bold">发光二极管</span>
</div>
</div>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
<TypeCard
title="整流二极管"
desc="利用单向导电性,将交流电(AC)变为脉动直流电(DC)。"
icon={<Power className="text-slate-500"/>}
tags={['面接触型', '低频']}
color="bg-slate-50"
/>
<TypeCard
title="稳压二极管"
desc="工作在反向击穿区。只要电流限制在允许范围内,电压基本不变。"
icon={<Activity className="text-orange-500"/>}
tags={['反向工作', '电压基准']}
color="bg-orange-50"
/>
<TypeCard
title="检波二极管"
desc="点接触型,结电容极小。用于从高频调幅信号中取出调制信号。"
icon={<Waves className="text-blue-500"/>}
tags={['点接触', '高频', '小电流']}
color="bg-blue-50"
/>
<TypeCard
title="光电二极管"
desc="反向偏置工作。光照越强,反向电流(光电流)越大。"
icon={<Sun className="text-yellow-500"/>}
tags={['光控开关', '光信号接收']}
color="bg-yellow-50"
/>
</div>
</section>
{/* 新增:整流电路 */}
<section>
<h2 className="text-xl font-bold text-slate-800 border-l-4 border-blue-500 pl-3 mb-4">应用一:整流电路</h2>
<div className="bg-white p-4 border rounded-xl flex flex-col md:flex-row gap-6 items-center">
<div className="flex-1">
<p className="text-sm text-slate-600 mb-2">利用二极管的<strong>单向导电性</strong>,把正负交变的交流电变成单方向的脉动直流电。</p>
<div className="h-24 flex items-center justify-center bg-slate-50 rounded border border-slate-200 relative overflow-hidden">
{/* 简单的正弦波转半波示意 */}
<svg viewBox="0 0 200 60" className="w-full h-full">
<path d="M10 30 Q 30 5 50 30 T 90 30 T 130 30" fill="none" stroke="#94a3b8" strokeWidth="2" strokeDasharray="4 2"/>
<path d="M10 30 Q 30 5 50 30 L 90 30 Q 110 5 130 30" fill="none" stroke="#ef4444" strokeWidth="3"/>
<text x="140" y="35" fontSize="10" fill="#ef4444">输出半波</text>
</svg>
</div>
</div>
<div className="w-32 text-xs text-slate-500 bg-slate-100 p-2 rounded">
<strong>半波整流:</strong><br/>正半周导通,负半周截止。效率较低。
</div>
</div>
</section>
{/* 新增:限幅电路 */}
<section>
<h2 className="text-xl font-bold text-slate-800 border-l-4 border-red-500 pl-3 mb-4">应用二:限幅电路</h2>
<div className="bg-white p-4 border rounded-xl flex flex-col md:flex-row gap-6 items-center">
<div className="flex-1">
<p className="text-sm text-slate-600 mb-2">利用二极管导通后<strong>电压恒定</strong>(约0.7V)的特性,将信号限制在一定幅度内。</p>
<div className="h-24 flex items-center justify-center bg-slate-50 rounded border border-slate-200 relative overflow-hidden">
<svg viewBox="0 0 200 60" className="w-full h-full">
<path d="M10 30 L 30 5 L 50 30 L 70 55 L 90 30" fill="none" stroke="#94a3b8" strokeWidth="2" strokeDasharray="4 2"/>
<path d="M10 30 L 20 15 H 40 L 50 30 L 60 45 H 80 L 90 30" fill="none" stroke="#3b82f6" strokeWidth="3"/>
<line x1="0" y1="15" x2="200" y2="15" stroke="#ef4444" strokeWidth="1" strokeDasharray="2"/>
<text x="100" y="12" fontSize="8" fill="#ef4444">限制电压 +E</text>
</svg>
</div>
</div>
<div className="w-32 text-xs text-slate-500 bg-slate-100 p-2 rounded">
<strong>双向限幅:</strong><br/>两个二极管反向并联,可限制信号的正负幅值。
</div>
</div>
</section>
</div>
)}
{/* 2. 伏安特性 */}
{activeTab === 'theory' && (
<div className="space-y-6 animate-fadeIn">
<h2 className="text-xl font-bold text-slate-800 border-l-4 border-blue-500 pl-3">二极管伏安特性曲线</h2>
<p className="text-sm text-slate-600">
将鼠标悬停在曲线上,观察不同电压下的电流变化。注意<strong>死区</strong>和<strong>反向击穿</strong>。
</p>
<VIChart />
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 mt-4">
<div className="bg-blue-50 p-5 rounded-xl border border-blue-100">
<h4 className="font-bold text-blue-800 mb-3 flex items-center gap-2">
<ChevronRight className="w-4 h-4"/> 正向特性 (右半轴)
</h4>
<ul className="text-sm text-slate-700 space-y-2">
<li><strong>死区:</strong>电压较小时( < 0.5V ),电流极小,二极管截止。硅管死区电压约 0.5V,锗管约 0.1V。</li>
<li><strong>导通区:</strong>电压超过死区后,电流迅速增大。</li>
<li><strong>导通压降:</strong>导通后两端电压基本恒定。硅管约 <span className="font-bold text-blue-600">0.6~0.7V</span>,锗管约 0.2~0.3V。</li>
</ul>
</div>
<div className="bg-orange-50 p-5 rounded-xl border border-orange-100">
<h4 className="font-bold text-orange-800 mb-3 flex items-center gap-2">
<ChevronRight className="w-4 h-4"/> 反向特性 (左半轴)
</h4>
<ul className="text-sm text-slate-700 space-y-2">
<li><strong>截止区:</strong>反向电流极小(漏电流),通常微安级别,可视为开路。</li>
<li><strong>击穿区:</strong>反向电压超过 <span className="font-mono font-bold">U(BR)</span> 时,电流剧增。</li>
<li><strong>应用:</strong>稳压二极管就是工作在反向击穿区的特殊二极管。</li>
</ul>
</div>
</div>
</div>
)}
{/* 3. 结构与原理 */}
{activeTab === 'structure' && (
<div className="space-y-8 animate-fadeIn">
<section>
<h2 className="text-xl font-bold text-slate-800 border-l-4 border-purple-500 pl-3 mb-4">半导体基础</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
<div className="bg-slate-50 p-4 rounded-lg border border-slate-100">
<h3 className="font-bold text-slate-700 mb-2">本征半导体</h3>
<p className="text-sm text-slate-600 leading-relaxed">纯净的半导体(如硅 Si、锗 Ge)。导电能力介于导体和绝缘体之间。受热或光照会产生电子-空穴对。</p>
</div>
<div className="bg-slate-50 p-4 rounded-lg border border-slate-100">
<h3 className="font-bold text-slate-700 mb-2">杂质半导体</h3>
<ul className="text-sm text-slate-600 space-y-2">
<li className="flex items-start gap-2"><span className="bg-blue-100 text-blue-800 text-xs font-bold px-1.5 py-0.5 rounded">N型</span> 掺入五价元素(磷),自由电子为多子。</li>
<li className="flex items-start gap-2"><span className="bg-red-100 text-red-800 text-xs font-bold px-1.5 py-0.5 rounded">P型</span> 掺入三价元素(硼),空穴为多子。</li>
</ul>
</div>
</div>
</section>
<section>
<h2 className="text-xl font-bold text-slate-800 border-l-4 border-purple-500 pl-3 mb-4">PN 结的形成</h2>
<div className="flex flex-col items-center bg-gradient-to-r from-red-50 to-blue-50 p-6 rounded-xl border border-slate-200">
<div className="flex w-full max-w-md h-32 rounded-lg overflow-hidden shadow-inner border-2 border-slate-300 relative">
{/* P区 */}
<div className="flex-1 bg-red-200 flex items-center justify-center relative group">
<span className="text-4xl font-black text-red-500 opacity-20 group-hover:opacity-40 transition-opacity">P</span>
<div className="absolute inset-0 p-2 flex flex-wrap justify-center items-center gap-2 opacity-60">
{Array(8).fill(0).map((_,i) => <div key={i} className="w-3 h-3 rounded-full border-2 border-red-600" title="空穴"></div>)}
</div>
</div>
{/* 耗尽层 */}
<div className="w-16 bg-slate-300/50 backdrop-blur-sm border-x border-slate-400/30 flex items-center justify-center flex-col">
<span className="text-[10px] text-slate-600 font-bold text-center">空间电荷区</span>
<div className="flex gap-1 mt-1">
<span className="text-xs text-red-600">-</span><span className="text-xs text-blue-600">+</span>
</div>
</div>
{/* N区 */}
<div className="flex-1 bg-blue-200 flex items-center justify-center relative group">
<span className="text-4xl font-black text-blue-500 opacity-20 group-hover:opacity-40 transition-opacity">N</span>
<div className="absolute inset-0 p-2 flex flex-wrap justify-center items-center gap-2 opacity-60">
{Array(8).fill(0).map((_,i) => <div key={i} className="w-3 h-3 rounded-full bg-blue-600" title="电子"></div>)}
</div>
</div>
</div>
<p className="mt-4 text-sm text-slate-700 text-center max-w-lg">
P型半导体和N型半导体交界面形成<strong>空间电荷区</strong>(耗尽层)。<br/>
内电场方向:<span className="text-blue-600 font-bold">N</span> → <span className="text-red-600 font-bold">P</span>,阻碍多子扩散,利于少子漂移。
</p>
</div>
</section>
</div>
)}
</div>
</div>
</main>
<footer className="text-center text-slate-400 py-8 text-sm">
© 2024 电子电路技术课程教学辅助系统
</footer>
</div>
);
};
// 辅助组件:类型卡片
const TypeCard = ({ title, desc, icon, tags, color }) => (
<div className={`${color} p-5 rounded-xl border border-slate-100 shadow-sm hover:shadow-md transition-all hover:-translate-y-1 cursor-default`}>
<div className="flex items-center gap-3 mb-3">
<div className="p-2 bg-white rounded-lg shadow-sm">{icon}</div>
<h3 className="font-bold text-slate-700">{title}</h3>
</div>
<p className="text-sm text-slate-600 mb-4 leading-relaxed">{desc}</p>
<div className="flex flex-wrap gap-2">
{tags.map((tag, i) => (
<span key={i} className="px-2 py-1 bg-white/60 text-slate-600 text-xs font-medium rounded-md border border-slate-200/50">{tag}</span>
))}
</div>
</div>
);
// 简单的图标占位符
const BoxIcon = () => (
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z"></path>
<polyline points="3.27 6.96 12 12.01 20.73 6.96"></polyline>
<line x1="12" y1="22.08" x2="12" y2="12"></line>
</svg>
);
// 渲染应用
const root = createRoot(document.getElementById('root'));
root.render(<App />);
</script>
</body>
</html>
效果

3D 元器件效果
3D 元器件可以放大、旋转。在元器件下方,有关于该元器件的简单介绍。

概念介绍
针对半导体二极管的类型与应用、伏安特性、结构与原理。


仿真实验
关于半导体的正向偏置和反向偏置,有一个小交互。
-
开关断开

-
正向偏置,电灯可以点亮。

-
反向偏置,电灯没法点亮。

写在最后
引用 AI 大博主卡兹克在他的文章中的一句话结束本篇文章吧。
此即未来。
谢谢大家。
更多推荐




所有评论(0)