thelastclass02 / index.html
Lashtw's picture
Update index.html
e2e9940 verified
Raw
History Blame Contribute Delete
24.6 kB
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>最後一堂數學課:你的縮放中心</title>
<style>
:root {
--bg-color: #0f172a;
--text-main: #f8fafc;
--text-muted: #94a3b8;
--accent-cyan: #06b6d4;
--accent-amber: #fbbf24;
--accent-rose: #f43f5e;
--accent-green: #10b981;
--surface: #1e293b;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: "PingFang TC", "Heiti TC", "Microsoft JhengHei", sans-serif;
background-color: var(--bg-color);
color: var(--text-main);
overflow: hidden;
display: flex;
flex-direction: column;
height: 100vh;
}
/* 隱形翻頁感應區 */
.nav-zone {
position: absolute;
top: 0;
bottom: 0;
width: 15vw; /* 佔據畫面左右各 15% 的寬度 */
z-index: 50; /* 確保在圖層上方 */
cursor: pointer;
transition: opacity 0.3s;
opacity: 0; /* 預設完全透明 */
}
.nav-zone.left {
left: 0;
background: linear-gradient(to right, rgba(255,255,255,0.06) 0%, transparent 100%);
}
.nav-zone.right {
right: 0;
background: linear-gradient(to left, rgba(255,255,255,0.06) 0%, transparent 100%);
}
.nav-zone:hover {
opacity: 1; /* 滑鼠靠近邊緣時顯示微光,暗示可點擊 */
}
/* 簡報容器 */
#presentation {
flex: 1;
position: relative;
width: 100%;
height: 100vh;
}
.slide {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
transition: opacity 0.6s ease-in-out, transform 0.6s ease-in-out;
pointer-events: none;
display: flex;
flex-direction: column;
align-items: center;
padding: 20px 40px;
transform: scale(0.98);
}
.slide.active {
opacity: 1;
pointer-events: auto;
transform: scale(1);
}
/* 標題與文字 */
h1 {
font-size: 2.2rem;
margin-bottom: 5px;
text-align: center;
color: var(--accent-cyan);
text-shadow: 0 0 15px rgba(6, 182, 212, 0.4);
}
p.subtitle {
font-size: 1.1rem;
color: var(--text-muted);
margin-bottom: 15px;
text-align: center;
max-width: 800px;
}
/* 控制區 (拉桿與資訊) */
.interactive-controls {
display: flex;
align-items: center;
gap: 20px;
background: var(--surface);
padding: 15px 30px;
border-radius: 50px;
margin-bottom: 20px;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
border: 1px solid rgba(255,255,255,0.1);
z-index: 100; /* 拉高圖層,避免被翻頁區蓋住導致無法拖曳 */
position: relative;
}
.slider-label {
font-size: 1.2rem;
font-weight: bold;
color: var(--accent-amber);
}
input[type=range] {
-webkit-appearance: none;
width: 300px;
background: transparent;
}
input[type=range]::-webkit-slider-thumb {
-webkit-appearance: none;
height: 20px;
width: 20px;
border-radius: 50%;
background: var(--accent-amber);
cursor: pointer;
margin-top: -8px;
box-shadow: 0 0 10px var(--accent-amber);
}
input[type=range]::-webkit-slider-runnable-track {
width: 100%;
height: 4px;
cursor: pointer;
background: #334155;
border-radius: 2px;
}
/* SVG 容器 */
.svg-container {
flex: 1;
width: 100%;
min-height: 0;
display: flex;
justify-content: center;
align-items: center;
}
svg {
width: 100%;
height: 100%;
max-height: 100%;
}
/* 底部導覽列 (只保留點點,並使其懸浮在底部) */
.nav-bar {
position: absolute;
bottom: 15px; /* 往下方挪動,空出上方空間 */
left: 0;
width: 100%;
z-index: 100;
background: transparent;
display: flex;
justify-content: center;
align-items: center;
pointer-events: none; /* 讓滑鼠點擊穿透,不會擋到底部的元素 */
}
.indicators {
display: flex;
gap: 10px;
pointer-events: auto; /* 點點本身依然可以接收事件 */
}
.dot {
width: 12px;
height: 12px;
border-radius: 50%;
background: #334155;
transition: 0.3s;
}
.dot.active {
background: var(--accent-cyan);
box-shadow: 0 0 10px var(--accent-cyan);
}
/* --- 首頁標題專屬樣式 --- */
.title-layout {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
text-align: center;
position: relative;
z-index: 10;
}
.title-main {
font-size: 4.8rem;
color: var(--accent-amber);
font-weight: bold;
margin-bottom: 20px;
text-shadow: 0 0 40px rgba(251, 191, 36, 0.4);
letter-spacing: 6px;
}
.title-sub {
font-size: 3.2rem;
color: var(--accent-cyan);
margin-bottom: 60px;
letter-spacing: 4px;
font-weight: bold;
text-shadow: 0 0 20px rgba(6, 182, 212, 0.3);
}
.title-author {
font-size: 1.4rem;
color: var(--text-muted);
padding-top: 25px;
border-top: 1px solid rgba(255, 255, 255, 0.2);
letter-spacing: 2px;
min-width: 350px;
}
.title-deco {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 700px;
height: 700px;
z-index: 0;
pointer-events: none;
animation: slowPulse 4s infinite alternate ease-in-out;
}
@keyframes slowPulse {
0% { transform: translate(-50%, -50%) scale(0.95); opacity: 0.15; }
100% { transform: translate(-50%, -50%) scale(1.05); opacity: 0.35; }
}
/* --- 總結頁專屬樣式 --- */
.conclusion-box {
background: rgba(15, 23, 42, 0.6);
border: 2px solid var(--accent-amber);
padding: 45px 60px; /* 稍微縮小內距 */
border-radius: 20px;
width: 85%;
max-width: 1050px; /* 縮小最大寬度限制 */
margin-top: 40px;
box-shadow: 0 0 40px rgba(251, 191, 36, 0.15);
z-index: 10;
display: flex;
flex-direction: column;
gap: 25px; /* 稍微縮小行距 */
}
.pulse-bg {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100vw;
height: 100vh;
z-index: 0;
pointer-events: none;
opacity: 0.6;
}
.conclusion-title {
color: var(--accent-cyan);
font-size: 3rem; /* 字體稍微縮小 */
text-align: center;
margin-bottom: 10px;
font-weight: bold;
letter-spacing: 4px;
}
.conclusion-content {
text-align: left;
font-size: 1.4rem; /* 內文字體稍微縮小 */
line-height: 1.8;
color: var(--text-main);
}
.conclusion-point {
margin-bottom: 25px; /* 縮小點與點的間距 */
border-left: 6px solid var(--accent-cyan);
background: rgba(255, 255, 255, 0.02);
padding: 20px 25px; /* 縮小色塊內的留白 */
border-radius: 0 12px 12px 0;
}
.point-title {
color: var(--accent-amber);
font-weight: bold;
display: block;
margin-bottom: 10px;
font-size: 1.8rem; /* 點目標題稍微縮小 */
}
.point-desc {
color: var(--text-main);
display: block;
}
.conclusion-climax {
text-align: center;
color: var(--accent-amber);
font-size: 2.5rem; /* 結語縮小,確保能夠單行顯示 */
font-weight: bold;
margin-top: 25px;
text-shadow: 0 0 30px rgba(251, 191, 36, 0.6);
}
</style>
</head>
<body>
<!-- 隱形左右翻頁感應區 -->
<div class="nav-zone left" id="zone-prev" style="display: none;"></div>
<div class="nav-zone right" id="zone-next"></div>
<div id="presentation">
<!-- Slide 0: 首頁標題 -->
<div class="slide active" id="slide-home">
<svg class="title-deco" viewBox="0 0 500 500">
<polygon points="146,50 354,50 450,146 450,354 354,450 146,450 50,354 50,146" fill="none" stroke="var(--accent-amber)" stroke-width="1"/>
<polygon points="250,80 397,165 397,335 250,420 103,335 103,165" fill="none" stroke="var(--accent-cyan)" stroke-width="2"/>
<circle cx="250" cy="250" r="140" fill="none" stroke="rgba(255,255,255,0.15)" stroke-width="1" stroke-dasharray="5,5"/>
</svg>
<div class="title-layout">
<div class="title-main">國中最後一堂數學課</div>
<div class="title-sub">AI 與縮放中心</div>
<div class="title-author">教師:精華國中 藍星宇</div>
</div>
</div>
<!-- Slide 1: 定義圖形與能力 -->
<div class="slide" id="slide-1">
<h1>每個人都是獨一無二的多邊形</h1>
<p class="subtitle">國中八大領域,構成了你現在的基礎形狀。有人是均衡發展的戰士,有人是具有獨特專長的偏科天才。</p>
<div class="svg-container">
<svg id="svg-slide-1" viewBox="0 0 1000 500"></svg>
</div>
</div>
<!-- Slide 2: 基礎大小的差異 -->
<div class="slide" id="slide-2">
<h1>自身大小的決定性</h1>
<p class="subtitle">如果基本圖形太小,即使擁有相同的縮放中心 (AI),放大後會和人越差越多。充實自我永遠是根本。</p>
<div class="interactive-controls">
<span class="slider-label">AI 放大倍率 (k): <span id="val-s2">1.0</span></span>
<input type="range" id="slider-s2" min="1" max="2.5" step="0.05" value="1">
</div>
<div class="svg-container">
<svg id="svg-slide-2" viewBox="0 0 1000 500"></svg>
</div>
</div>
<!-- Slide 3: 縮放中心的距離 -->
<div class="slide" id="slide-3">
<h1>縮放中心與你的距離</h1>
<p class="subtitle">如果把 AI 當成遠在天邊的代寫工具,AI縮放點距離太遠,放大後會讓你偏離原本的自己。</p>
<div class="interactive-controls">
<span class="slider-label">AI 放大倍率 (k): <span id="val-s3">1.0</span></span>
<input type="range" id="slider-s3" min="1" max="2" step="0.05" value="1">
</div>
<div class="svg-container">
<svg id="svg-slide-3" viewBox="0 0 1000 500"></svg>
</div>
</div>
<!-- Slide 4: 結論 -->
<div class="slide" id="slide-4">
<svg class="pulse-bg" id="svg-slide-4" viewBox="0 0 1000 600"></svg>
<div class="conclusion-box">
<div class="conclusion-title">總結</div>
<div class="conclusion-content">
<div class="conclusion-point">
<span class="point-title">第一:擴張你的八邊形,讓自己沒有極限。</span>
<span class="point-desc">永遠不要停止充實自我,因為你的基礎大小,決定了被放大的結果。</span>
</div>
<div class="conclusion-point">
<span class="point-title">第二:將AI工具內化,才能真正展現自己。</span>
<span class="point-desc">不要只把 AI 當作完成作業的外部工具,要把 AI 內化成你的思考迴路。</span>
</div>
</div>
<div class="conclusion-climax">
讓 AI 在你的腦中,全方位地向外擴張你的潛能!
</div>
</div>
</div>
</div>
<div class="nav-bar">
<div class="indicators" id="indicators">
<div class="dot active"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
<div class="dot"></div>
</div>
</div>
<script>
// === 核心資料設定 ===
const subjects = ["語文", "自然", "科技", "數學", "社會", "健體", "綜合", "藝術"];
const angles = subjects.map((_, i) => i * Math.PI / 4 - Math.PI / 2);
const valFull = [0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85, 0.85];
const valSpecial = [0.3, 0.4, 0.95, 0.3, 0.4, 0.9, 0.85, 0.95];
const valSmall = [0.35, 0.35, 0.35, 0.35, 0.35, 0.35, 0.35, 0.35];
const colors = {
cyan: "#06b6d4",
green: "#10b981",
rose: "#f43f5e",
amber: "#fbbf24",
grid: "#334155",
text: "#cbd5e1"
};
function calcArea(values, radius, k=1) {
let area = 0;
for(let i=0; i<8; i++) {
let next = (i+1)%8;
area += 0.5 * (values[i]*radius*k) * (values[next]*radius*k) * Math.sin(Math.PI/4);
}
return Math.round(area);
}
// === SVG 繪製引擎 ===
function drawOctagon(ctx) {
let { cx, cy, baseRadius, values, aiPoint, k, color, title, showArea, showGrid, hideAI } = ctx;
let svg = '';
let basePoints = [];
let scaledPoints = [];
for(let i=0; i<8; i++) {
let r = values[i] * baseRadius;
let px = cx + r * Math.cos(angles[i]);
let py = cy + r * Math.sin(angles[i]);
basePoints.push({x: px, y: py});
let sx = aiPoint.x + k * (px - aiPoint.x);
let sy = aiPoint.y + k * (py - aiPoint.y);
scaledPoints.push({x: sx, y: sy});
}
if (showGrid !== false) {
for(let step=0.2; step<=1; step+=0.2) {
let gridPts = angles.map(a => `${cx + baseRadius*step*Math.cos(a)},${cy + baseRadius*step*Math.sin(a)}`).join(" ");
svg += `<polygon points="${gridPts}" fill="none" stroke="${colors.grid}" stroke-width="1"/>`;
}
}
if (k > 1 && !hideAI) {
for(let i=0; i<8; i++) {
svg += `<line x1="${aiPoint.x}" y1="${aiPoint.y}" x2="${scaledPoints[i].x}" y2="${scaledPoints[i].y}"
stroke="${color}" stroke-dasharray="4" stroke-opacity="0.5" stroke-width="2"/>`;
}
}
svg += `<polygon points="${basePoints.map(p=>`${p.x},${p.y}`).join(" ")}"
fill="${color}" fill-opacity="0.15" stroke="${color}" stroke-width="2" stroke-dasharray="3" />`;
svg += `<polygon points="${scaledPoints.map(p=>`${p.x},${p.y}`).join(" ")}"
fill="${color}" fill-opacity="0.3" stroke="${color}" stroke-width="3" style="filter: drop-shadow(0 0 8px ${color});" />`;
if (showGrid !== false) {
for(let i=0; i<8; i++) {
let lx = cx + (baseRadius + 30) * Math.cos(angles[i]);
let ly = cy + (baseRadius + 30) * Math.sin(angles[i]);
svg += `<text x="${lx}" y="${ly}" fill="${colors.text}" font-size="16" text-anchor="middle" dominant-baseline="middle">${subjects[i]}</text>`;
}
}
if (!hideAI) {
svg += `<circle cx="${aiPoint.x}" cy="${aiPoint.y}" r="6" fill="${colors.amber}" style="filter: drop-shadow(0 0 10px ${colors.amber});"/>`;
svg += `<text x="${aiPoint.x+12}" y="${aiPoint.y-12}" fill="${colors.amber}" font-size="16" font-weight="bold">AI (縮放中心)</text>`;
}
if (title) {
svg += `<text x="${cx}" y="${cy - baseRadius - 60}" fill="#fff" font-size="22" font-weight="bold" text-anchor="middle">${title}</text>`;
}
if (showArea) {
let areaValue = calcArea(values, baseRadius, k);
svg += `<text x="${cx}" y="${cy + baseRadius + 70}" fill="${color}" font-size="18" text-anchor="middle">當前能力總面積: ${areaValue}</text>`;
}
return svg;
}
// === 各頁面渲染邏輯 ===
function renderSlide1() {
let svg = '';
svg += drawOctagon({
cx: 250, cy: 260, baseRadius: 150, values: valFull,
aiPoint: {x: 250, y: 260}, k: 1, color: colors.cyan,
title: "均衡型(八邊形戰士)", hideAI: true, showArea: false
});
svg += drawOctagon({
cx: 750, cy: 260, baseRadius: 150, values: valSpecial,
aiPoint: {x: 750, y: 260}, k: 1, color: colors.green,
title: "專長型(偏科學生)", hideAI: true, showArea: false
});
document.getElementById('svg-slide-1').innerHTML = svg;
}
function renderSlide2() {
const k = parseFloat(document.getElementById('slider-s2').value);
document.getElementById('val-s2').innerText = k.toFixed(2);
let svg = '';
svg += drawOctagon({
cx: 200, cy: 230, baseRadius: 140, values: valFull,
aiPoint: {x: 200, y: 230}, k: k, color: colors.cyan,
title: "均衡型(基礎面積大)", showArea: false
});
svg += drawOctagon({
cx: 800, cy: 230, baseRadius: 140, values: valSpecial,
aiPoint: {x: 800, y: 230}, k: k, color: colors.green,
title: "專長型(基礎面積小)", showArea: false
});
let baseDiff = 92;
let areaDiff = Math.round(baseDiff * k * k);
let dynamicFontSize = Math.round(32 + (k - 1) * 20); // 收斂字體放大的極限,避免過大
// 文字顯示座標再次往上移,留出更大的底部空間
svg += `<text x="500" y="380" fill="${colors.text}" font-size="20" text-anchor="middle">雙方能力總面積的差距</text>`;
svg += `<text x="500" y="425" fill="${colors.rose}" font-size="${dynamicFontSize}" font-weight="bold" text-anchor="middle" dominant-baseline="middle">${areaDiff}</text>`;
document.getElementById('svg-slide-2').innerHTML = svg;
}
function renderSlide3() {
const k = parseFloat(document.getElementById('slider-s3').value);
document.getElementById('val-s3').innerText = k.toFixed(2);
let svg = '';
svg += drawOctagon({
cx: 250, cy: 250, baseRadius: 130, values: valFull,
aiPoint: {x: 420, y: 350}, k: k, color: colors.rose,
title: "AI 在外部(產生嚴重偏移)", showArea: false
});
if(k > 1) {
svg += `<circle cx="250" cy="250" r="4" fill="#fff" opacity="0.5"/>
<text x="250" y="270" fill="#fff" opacity="0.5" font-size="12" text-anchor="middle">原自我中心</text>`;
}
svg += drawOctagon({
cx: 750, cy: 250, baseRadius: 130, values: valFull,
aiPoint: {x: 750, y: 250}, k: k, color: colors.cyan,
title: "AI 在內部(全方位原地擴張)", showArea: false
});
document.getElementById('svg-slide-3').innerHTML = svg;
}
let s4AnimFrame;
let s4Time = 0;
function renderSlide4Loop() {
s4Time += 0.02;
let k = 1.3 + 0.2 * Math.sin(s4Time);
let svg = drawOctagon({
cx: 500, cy: 300, baseRadius: 260,
values: valFull,
aiPoint: {x: 500, y: 300}, k: k, color: colors.amber,
showArea: false, showGrid: false, title: "", hideAI: true
});
document.getElementById('svg-slide-4').innerHTML = svg;
s4AnimFrame = requestAnimationFrame(renderSlide4Loop);
}
// === 互動與導覽邏輯 ===
document.getElementById('slider-s2').addEventListener('input', renderSlide2);
document.getElementById('slider-s3').addEventListener('input', renderSlide3);
let currentSlide = 0;
const slides = document.querySelectorAll('.slide');
const totalSlides = slides.length;
const dots = document.querySelectorAll('.dot');
// 取得新的隱形翻頁區元素
const zonePrev = document.getElementById('zone-prev');
const zoneNext = document.getElementById('zone-next');
function updateSlide() {
slides.forEach((s, i) => {
if (i === currentSlide) {
s.classList.add('active');
} else {
s.classList.remove('active');
}
});
dots.forEach((d, i) => {
d.classList.toggle('active', i === currentSlide);
});
// 根據目前頁數,決定是否隱藏左側或右側的翻頁區
zonePrev.style.display = currentSlide === 0 ? 'none' : 'block';
zoneNext.style.display = currentSlide === totalSlides - 1 ? 'none' : 'block';
// 因為首頁加入,總結頁變成了 index 4
if (currentSlide === 4) {
if(!s4AnimFrame) renderSlide4Loop();
} else {
if(s4AnimFrame) {
cancelAnimationFrame(s4AnimFrame);
s4AnimFrame = null;
}
}
}
// 設定翻頁區的點擊事件
zonePrev.addEventListener('click', () => {
if (currentSlide > 0) {
currentSlide--;
updateSlide();
}
});
zoneNext.addEventListener('click', () => {
if (currentSlide < totalSlides - 1) {
currentSlide++;
updateSlide();
}
});
// 保留原本的鍵盤左右鍵控制
window.addEventListener('keydown', (e) => {
if (e.key === 'ArrowRight' && currentSlide < totalSlides - 1) {
currentSlide++;
updateSlide();
} else if (e.key === 'ArrowLeft' && currentSlide > 0) {
currentSlide--;
updateSlide();
}
});
// 初始渲染
renderSlide1();
renderSlide2();
renderSlide3();
updateSlide();
</script>
</body>
</html>