console
<!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;
max-width: 900px;
margin: 0 auto;
padding: 20px;
background-color: #f5f5f5;
color: #333;
}
h1 {
color: #2c3e50;
text-align: center;
border-bottom: 2px solid #3498db;
padding-bottom: 10px;
}
h2 {
color: #2980b9;
margin-top: 30px;
}
.theorem {
background-color: #e8f4fc;
padding: 15px;
border-left: 5px solid #3498db;
margin: 20px 0;
border-radius: 0 5px 5px 0;
}
.proof {
background-color: #f9f9f9;
padding: 15px;
border: 1px solid #ddd;
border-radius: 5px;
margin: 15px 0;
}
.interactive {
background-color: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
margin: 25px 0;
text-align: center;
}
canvas {
background-color: #fff;
border: 1px solid #ddd;
margin: 10px auto;
display: block;
}
.controls {
margin: 15px 0;
}
button {
background-color: #3498db;
color: white;
border: none;
padding: 8px 15px;
margin: 0 5px;
border-radius: 4px;
cursor: pointer;
transition: background-color 0.3s;
}
button:hover {
background-color: #2980b9;
}
.note {
font-style: italic;
color: #7f8c8d;
}
.conclusion {
font-weight: bold;
color: #27ae60;
}
</style>
</head>
<body>
<h1>平行线判定定理可视化证明</h1>
<div class="theorem">
<h2>平行线的判定定理</h2>
<p>1. <strong>同位角相等,两直线平行</strong></p>
<p>2. <strong>内错角相等,两直线平行</strong></p>
<p>3. <strong>同旁内角互补,两直线平行</strong></p>
</div>
<div class="interactive">
<h3>交互式演示 - 拖动点改变角度</h3>
<canvas id="parallelCanvas" width="600" height="300"></canvas>
<div class="controls">
<button onclick="showCorresponding()">同位角演示</button>
<button onclick="showAlternate()">内错角演示</button>
<button onclick="showConsecutive()">同旁内角演示</button>
<button onclick="reset()">重置</button>
</div>
<p class="note">拖动红色点改变角度,观察平行线条件</p>
</div>
<div class="proof">
<h2>1. 同位角相等,两直线平行</h2>
<p><strong>已知</strong>:直线l₁和l₂被直线m所截,同位角∠1 = ∠2</p>
<p><strong>证明</strong>:l₁ ∥ l₂</p>
<p>假设l₁不平行于l₂,则两直线必相交于某点P,形成三角形。</p>
<p>根据三角形外角定理,∠2 = ∠1 + ∠P(外角等于不相邻内角之和)</p>
<p>但已知∠1 = ∠2,代入得∠1 = ∠1 + ∠P ⇒ ∠P = 0°</p>
<p>这意味着两直线不相交,即l₁ ∥ l₂。</p>
<p class="conclusion">∴ 同位角相等时,两直线平行。</p>
</div>
<div class="proof">
<h2>2. 内错角相等,两直线平行</h2>
<p><strong>已知</strong>:直线l₁和l₂被直线m所截,内错角∠3 = ∠4</p>
<p><strong>证明</strong>:l₁ ∥ l₂</p>
<p>∵ ∠1 = ∠3(对顶角相等),且∠3 = ∠4(已知)</p>
<p>∴ ∠1 = ∠4</p>
<p>但∠1和∠4是同位角,根据定理1:同位角相等⇒两直线平行</p>
<p class="conclusion">∴ 内错角相等时,两直线平行。</p>
</div>
<div class="proof">
<h2>3. 同旁内角互补,两直线平行</h2>
<p><strong>已知</strong>:直线l₁和l₂被直线m所截,同旁内角∠5 + ∠6 = 180°</p>
<p><strong>证明</strong>:l₁ ∥ l₂</p>
<p>∵ ∠5 + ∠6 = 180°,且∠6 + ∠7 = 180°(邻补角定义)</p>
<p>∴ ∠5 = ∠7</p>
<p>但∠5和∠7是同位角,根据定理1:同位角相等⇒两直线平行</p>
<p class="conclusion">∴ 同旁内角互补时,两直线平行。</p>
</div>
<script>
const canvas = document.getElementById('parallelCanvas');
const ctx = canvas.getContext('2d');
let angle = 60;
let mode = 'corresponding';
let isDragging = false;
let dragPoint = { x: 300, y: 150 };
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 绘制两条平行线
ctx.beginPath();
ctx.moveTo(100, 100);
ctx.lineTo(500, 100);
ctx.moveTo(100, 200);
ctx.lineTo(500, 200);
ctx.strokeStyle = '#3498db';
ctx.lineWidth = 2;
ctx.stroke();
// 绘制截线
ctx.beginPath();
ctx.moveTo(150, 50);
ctx.lineTo(450, 250);
ctx.strokeStyle = '#e74c3c';
ctx.lineWidth = 2;
ctx.stroke();
// 计算角度点
if (mode === 'corresponding') {
dragPoint = {
x: 300 + Math.cos((angle-90) * Math.PI / 180) * 50,
y: 150 + Math.sin((angle-90) * Math.PI / 180) * 50
};
} else {
dragPoint = {
x: 300 + Math.cos((angle) * Math.PI / 180) * 50,
y: 150 + Math.sin((angle) * Math.PI / 180) * 50
};
}
// 绘制角度标记
drawAngle(300, 150, angle);
// 绘制拖拽点
ctx.beginPath();
ctx.arc(dragPoint.x, dragPoint.y, 8, 0, Math.PI * 2);
ctx.fillStyle = 'red';
ctx.fill();
}
function drawAngle(x, y, angle) {
const radius = 30;
// 绘制角度弧线
ctx.beginPath();
ctx.arc(x, y, radius, 0, angle * Math.PI / 180);
ctx.strokeStyle = '#2ecc71';
ctx.lineWidth = 2;
ctx.stroke();
// 绘制角度文本
ctx.font = '16px Arial';
ctx.fillStyle = '#2ecc71';
ctx.fillText(angle + '°', x + radius + 5, y + 5);
// 根据模式绘制不同角度标记
if (mode === 'corresponding') {
// 同位角
drawCorrespondingAngles(x, y, angle);
} else if (mode === 'alternate') {
// 内错角
drawAlternateAngles(x, y, angle);
} else {
// 同旁内角
drawConsecutiveAngles(x, y, angle);
}
}
function drawCorrespondingAngles(x, y, angle) {
ctx.strokeStyle = '#9b59b6';
ctx.lineWidth = 1;
// 第一个同位角
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x + 40, y);
ctx.lineTo(x + 40, y - 40);
ctx.stroke();
// 第二个同位角
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x + 40, y + 100);
ctx.lineTo(x + 40 + 40 * Math.cos(angle * Math.PI / 180),
y + 100 + 40 * Math.sin(angle * Math.PI / 180));
ctx.stroke();
// 标记角度
ctx.font = '14px Arial';
ctx.fillStyle = '#9b59b6';
ctx.fillText('∠1', x + 20, y - 10);
ctx.fillText('∠2', x + 60, y + 80);
}
function drawAlternateAngles(x, y, angle) {
ctx.strokeStyle = '#e67e22';
ctx.lineWidth = 1;
// 内错角1
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x + 40, y);
ctx.lineTo(x + 40, y - 40);
ctx.stroke();
// 内错角2
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x - 40 * Math.cos(angle * Math.PI / 180),
y + 100 - 40 * Math.sin(angle * Math.PI / 180));
ctx.lineTo(x - 40 * Math.cos(angle * Math.PI / 180) - 40,
y + 100 - 40 * Math.sin(angle * Math.PI / 180));
ctx.stroke();
// 标记角度
ctx.font = '14px Arial';
ctx.fillStyle = '#e67e22';
ctx.fillText('∠3', x + 20, y - 10);
ctx.fillText('∠4', x - 50, y + 80);
}
function drawConsecutiveAngles(x, y, angle) {
ctx.strokeStyle = '#1abc9c';
ctx.lineWidth = 1;
// 同旁内角1
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x + 40, y);
ctx.lineTo(x + 40, y - 40);
ctx.stroke();
// 同旁内角2
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x - 40 * Math.cos(angle * Math.PI / 180),
y + 100 - 40 * Math.sin(angle * Math.PI / 180));
ctx.lineTo(x - 40 * Math.cos(angle * Math.PI / 180),
y + 100 - 40 * Math.sin(angle * Math.PI / 180) - 40);
ctx.stroke();
// 标记角度
ctx.font = '14px Arial';
ctx.fillStyle = '#1abc9c';
ctx.fillText('∠5', x + 20, y - 10);
ctx.fillText('∠6', x - 30, y + 60);
ctx.fillText('∠5 + ∠6 = ' + angle + '°', x + 100, y + 120);
}
function showCorresponding() {
mode = 'corresponding';
angle = 60;
draw();
}
function showAlternate() {
mode = 'alternate';
angle = 60;
draw();
}
function showConsecutive() {
mode = 'consecutive';
angle = 120;
draw();
}
function reset() {
angle = 60;
draw();
}
// 鼠标交互
canvas.addEventListener('mousedown', (e) => {
const rect = canvas.getBoundingClientRect();
const mouseX = e.clientX - rect.left;
const mouseY = e.clientY - rect.top;
if (Math.sqrt((mouseX - dragPoint.x) ** 2 + (mouseY - dragPoint.y) ** 2) < 15) {
isDragging = true;
}
});
canvas.addEventListener('mousemove', (e) => {
if (isDragging) {
const rect = canvas.getBoundingClientRect();
const mouseX = e.clientX - rect.left;
const mouseY = e.clientY - rect.top;
const dx = mouseX - 300;
const dy = mouseY - 150;
angle = Math.atan2(dy, dx) * 180 / Math.PI;
if (mode === 'corresponding') {
angle += 90;
}
angle = Math.max(10, Math.min(170, angle));
draw();
}
});
canvas.addEventListener('mouseup', () => {
isDragging = false;
});
canvas.addEventListener('mouseleave', () => {
isDragging = false;
});
// 初始化
showCorresponding();
</script>
</body>
</html>