+
38
-

回答

可以使用p5等动画插件写一个html,然后录制动画

800_auto

<!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://cdn.tailwindcss.com"></script>
    <script src="https://cdn.jsdelivr.net/npm/p5@1.5.0/lib/p5.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#165DFF',
                        secondary: '#FF7D00',
                        dark: '#1D2129',
                        light: '#F2F3F5'
                    },
                    fontFamily: {
                        inter: ['Inter', 'system-ui', 'sans-serif'],
                    },
                }
            }
        }
    </script>
    <style type="text/tailwindcss">
        @layer utilities {
            .content-auto {
                content-visibility: auto;
            }
            .text-shadow {
                text-shadow: 0 2px 4px rgba(0,0,0,0.1);
            }
            .transition-all-300 {
                transition: all 300ms ease-in-out;
            }
        }
    </style>
</head>
<body class="bg-gradient-to-br from-light to-gray-100 font-inter text-dark min-h-screen flex flex-col">
    <header class="bg-white shadow-md sticky top-0 z-50">
        <div class="container mx-auto px-4 py-4 flex justify-between items-center">
            <h1 class="text-[clamp(1.5rem,3vw,2.5rem)] font-bold text-primary">
                <i class="fa fa-superscript mr-2"></i>数学可视化:正弦函数
            </h1>
            <div class="flex items-center space-x-4">
                <button id="playPauseBtn" class="bg-primary hover:bg-primary/90 text-white px-4 py-2 rounded-lg shadow transition-all-300 flex items-center">
                    <i class="fa fa-play mr-2" id="playIcon"></i>
                    <span id="playBtnText">播放解说</span>
                </button>
                <button id="fullscreenBtn" class="bg-secondary hover:bg-secondary/90 text-white px-4 py-2 rounded-lg shadow transition-all-300">
                    <i class="fa fa-expand mr-2"></i>全屏
                </button>
            </div>
        </div>
    </header>

    <main class="flex-grow container mx-auto px-4 py-8 grid grid-cols-1 lg:grid-cols-3 gap-8">
        <div class="lg:col-span-2 bg-white rounded-xl shadow-lg overflow-hidden">
            <div class="relative" style="padding-bottom: 56.25%;">
                <div id="p5Container" class="absolute inset-0"></div>
            </div>
        </div>

        <div class="lg:col-span-1 bg-white rounded-xl shadow-lg p-6 flex flex-col">
            <h2 class="text-2xl font-bold mb-4 text-primary border-b pb-2">正弦函数解说</h2>
            
            <div id="transcript" class="flex-grow overflow-y-auto mb-6">
                <div class="mb-4">
                    <p class="text-lg font-semibold text-primary">1. 基本定义</p>
                    <p class="text-dark/80">正弦函数(sin)是三角函数的一种,表示直角三角形中对边与斜边的比值。在单位圆上,正弦值等于点的y坐标。</p>
                </div>
                
                <div class="mb-4">
                    <p class="text-lg font-semibold text-primary">2. 波形特征</p>
                    <p class="text-dark/80">正弦波是周期性的,其形状在时间或空间上重复。它的周期是2π,意味着每经过2π的间隔,波形就会重复一次。</p>
                </div>
                
                <div class="mb-4">
                    <p class="text-lg font-semibold text-primary">3. 关键参数</p>
                    <p class="text-dark/80">振幅(Amplitude)决定了波形的高度,频率(Frequency)决定了波形的密集程度,相位(Phase)决定了波形的起始位置。</p>
                </div>
                
                <div class="mb-4">
                    <p class="text-lg font-semibold text-primary">4. 应用领域</p>
                    <p class="text-dark/80">正弦函数在物理学、工程学、信号处理、音乐等领域有广泛应用,例如描述振动、交流电、声波等。</p>
                </div>
            </div>
            
            <div class="space-y-4">
                <div class="bg-light rounded-lg p-4">
                    <h3 class="font-semibold mb-2">控制参数</h3>
                    <div class="space-y-3">
                        <div>
                            <label class="block text-sm font-medium text-dark/70 mb-1">振幅 (A)</label>
                            <input type="range" id="amplitudeSlider" min="0.1" max="2" step="0.1" value="1" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer accent-primary">
                            <div class="flex justify-between text-xs text-dark/60">
                                <span>0.1</span>
                                <span id="amplitudeValue">1.0</span>
                                <span>2.0</span>
                            </div>
                        </div>
                        
                        <div>
                            <label class="block text-sm font-medium text-dark/70 mb-1">频率 (ω)</label>
                            <input type="range" id="frequencySlider" min="0.1" max="2" step="0.1" value="1" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer accent-primary">
                            <div class="flex justify-between text-xs text-dark/60">
                                <span>0.1</span>
                                <span id="frequencyValue">1.0</span>
                                <span>2.0</span>
                            </div>
                        </div>
                        
                        <div>
                            <label class="block text-sm font-medium text-dark/70 mb-1">相位 (φ)</label>
                            <input type="range" id="phaseSlider" min="0" max="6.28" step="0.1" value="0" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer accent-primary">
                            <div class="flex justify-between text-xs text-dark/60">
                                <span>0</span>
                                <span id="phaseValue">0.0</span>
                                <span>2π</span>
                            </div>
                        </div>
                    </div>
                </div>
                
                <div class="text-center">
                    <button id="resetBtn" class="bg-gray-200 hover:bg-gray-300 text-dark px-4 py-2 rounded-lg shadow transition-all-300">
                        <i class="fa fa-refresh mr-2"></i>重置参数
                    </button>
                </div>
            </div>
        </div>
    </main>

    <footer class="bg-dark text-white py-6 mt-8">
        <div class="container mx-auto px-4">
            <div class="flex flex-col md:flex-row justify-between items-center">
                <div class="mb-4 md:mb-0">
                    <h2 class="text-xl font-bold">数学可视化项目</h2>
                    <p class="text-gray-400 mt-1">让抽象概念变得直观易懂</p>
                </div>
                <div class="flex space-x-4">
                    <a href="#" class="text-gray-400 hover:text-white transition-colors">
                        <i class="fa fa-github text-xl"></i>
                    </a>
                    <a href="#" class="text-gray-400 hover:text-white transition-colors">
                        <i class="fa fa-twitter text-xl"></i>
                    </a>
                    <a href="#" class="text-gray-400 hover:text-white transition-colors">
                        <i class="fa fa-envelope text-xl"></i>
                    </a>
                </div>
            </div>
            <div class="border-t border-gray-700 mt-6 pt-6 text-center text-gray-400">
                © 2025 数学可视化团队. 保留所有权利.
            </div>
        </div>
    </footer>

    <script>
        // 音频解说 - 使用Web Speech API合成
        const synth = window.speechSynthesis;
        let isSpeaking = false;
        let utterance = null;
        
        // 正弦函数参数
        let amplitude = 1;
        let frequency = 1;
        let phase = 0;
        
        // 音频解说文本
        const script = [
            "欢迎来到正弦函数的可视化讲解。正弦函数是数学中最基本的函数之一,在科学和工程领域有广泛应用。",
            "正弦函数可以用单位圆来定义。当一个点在单位圆上运动时,其y坐标随角度的变化就是正弦函数。",
            "正弦波的形状是一条平滑的周期性曲线。它的基本形式是y等于sin x,其中x是角度。",
            "正弦函数有三个重要参数:振幅、频率和相位。让我们依次了解它们的影响。",
            "振幅决定了波形的高度。增大振幅会使波形更高,减小振幅则会使波形更矮。",
            "频率决定了波形的密集程度。频率越高,波形在单位长度内重复的次数就越多。",
            "相位决定了波形的起始位置。改变相位会使波形左右移动,但不会改变其形状和大小。",
            "正弦函数在现实生活中有许多应用,包括交流电、声波、电磁波等周期性现象的描述。",
            "通过调整这些参数,我们可以创建出各种各样的正弦波形,从而模拟不同的物理现象。",
            "感谢观看这个正弦函数的可视化讲解。希望这能帮助你更好地理解这个重要的数学概念。"
        ];
        
        // 播放/暂停解说
        document.getElementById('playPauseBtn').addEventListener('click', () => {
            if (isSpeaking) {
                synth.cancel();
                updatePlayButton(false);
            } else {
                speakScript();
                updatePlayButton(true);
            }
        });
        
        // 全屏切换
        document.getElementById('fullscreenBtn').addEventListener('click', () => {
            const container = document.getElementById('p5Container').parentElement;
            if (!document.fullscreenElement) {
                container.requestFullscreen().catch(err => {
                    console.error(`全屏请求错误: ${err.message}`);
                });
            } else {
                document.exitFullscreen();
            }
        });
        
        // 重置参数
        document.getElementById('resetBtn').addEventListener('click', () => {
            document.getElementById('amplitudeSlider').value = 1;
            document.getElementById('frequencySlider').value = 1;
            document.getElementById('phaseSlider').value = 0;
            
            updateParameters(1, 1, 0);
        });
        
        // 更新播放按钮状态
        function updatePlayButton(isPlaying) {
            isSpeaking = isPlaying;
            const playIcon = document.getElementById('playIcon');
            const playBtnText = document.getElementById('playBtnText');
            
            if (isPlaying) {
                playIcon.className = 'fa fa-pause mr-2';
                playBtnText.textContent = '暂停解说';
            } else {
                playIcon.className = 'fa fa-play mr-2';
                playBtnText.textContent = '播放解说';
            }
        }
        
        // 播放解说脚本
        function speakScript() {
            if (synth.speaking) return;
            
            utterance = new SpeechSynthesisUtterance(script.join(' '));
            utterance.lang = 'zh-CN';
            utterance.rate = 0.9;
            utterance.pitch = 1;
            
            utterance.onend = () => {
                updatePlayButton(false);
            };
            
            utterance.onerror = (event) => {
                console.error('语音合成错误:', event.error);
                updatePlayButton(false);
            };
            
            synth.speak(utterance);
            updatePlayButton(true);
        }
        
        // 参数滑块事件监听
        document.getElementById('amplitudeSlider').addEventListener('input', (e) => {
            const value = parseFloat(e.target.value);
            document.getElementById('amplitudeValue').textContent = value.toFixed(1);
            updateParameters(value, frequency, phase);
        });
        
        document.getElementById('frequencySlider').addEventListener('input', (e) => {
            const value = parseFloat(e.target.value);
            document.getElementById('frequencyValue').textContent = value.toFixed(1);
            updateParameters(amplitude, value, phase);
        });
        
        document.getElementById('phaseSlider').addEventListener('input', (e) => {
            const value = parseFloat(e.target.value);
            document.getElementById('phaseValue').textContent = value.toFixed(1);
            updateParameters(amplitude, frequency, value);
        });
        
        // 更新正弦函数参数
        function updateParameters(amp, freq, ph) {
            amplitude = amp;
            frequency = freq;
            phase = ph;
            
            if (window.drawSineWave) {
                window.drawSineWave(amplitude, frequency, phase);
            }
        }
        
        // P5.js 动画
        const sketch = (p) => {
            let angle = 0;
            let pointOnCircle;
            let wavePoints = [];
            let waveX = 300;
            let waveY = 200;
            let waveAmplitude = 1;
            let waveFrequency = 1;
            let wavePhase = 0;
            
            p.setup = () => {
                const container = document.getElementById('p5Container');
                const canvas = p.createCanvas(container.offsetWidth, container.offsetHeight);
                canvas.parent(container);
                
                // 初始化波形绘制函数
                window.drawSineWave = (amp, freq, ph) => {
                    waveAmplitude = amp;
                    waveFrequency = freq;
                    wavePhase = ph;
                };
            };
            
            p.windowResized = () => {
                const container = document.getElementById('p5Container');
                p.resizeCanvas(container.offsetWidth, container.offsetHeight);
                waveX = p.width * 0.4;
                waveY = p.height / 2;
            };
            
            p.draw = () => {
                p.background(240);
                p.translate(p.width * 0.25, p.height / 2);
                
                // 绘制坐标系
                drawAxes();
                
                // 绘制单位圆
                const radius = 100 * waveAmplitude;
                p.stroke(20, 93, 255, 150);
                p.strokeWeight(2);
                p.noFill();
                p.ellipse(0, 0, radius * 2);
                
                // 计算圆上点的位置
                const x = radius * p.cos(angle * waveFrequency + wavePhase);
                const y = radius * p.sin(angle * waveFrequency + wavePhase);
                pointOnCircle = { x, y };
                
                // 绘制圆上的点
                p.fill(255, 125, 0);
                p.stroke(255, 125, 0);
                p.strokeWeight(2);
                p.ellipse(x, y, 12);
                
                // 绘制从圆心到点的线
                p.stroke(255, 125, 0);
                p.strokeWeight(2);
                p.line(0, 0, x, y);
                
                // 绘制水平线到波形
                p.stroke(20, 93, 255);
                p.strokeWeight(2);
                p.line(x, y, waveX - radius, y);
                
                // 更新波形点
                wavePoints.unshift(y);
                if (wavePoints.length > 400) {
                    wavePoints.pop();
                }
                
                // 绘制波形
                p.push();
                p.translate(waveX, 0);
                
                // 绘制波形坐标系
                drawWaveAxes();
                
                // 绘制波形
                p.beginShape();
                p.noFill();
                p.stroke(20, 93, 255);
                p.strokeWeight(3);
                for (let i = 0; i < wavePoints.length; i++) {
                    p.vertex(i, wavePoints[i]);
                }
                p.endShape();
                
                // 绘制当前点在波形上的位置
                p.fill(255, 125, 0);
                p.stroke(255, 125, 0);
                p.strokeWeight(2);
                p.ellipse(0, wavePoints[0], 12);
                
                // 绘制函数表达式
                p.fill(30);
                p.noStroke();
                p.textSize(18);
                p.textAlign(p.LEFT, p.TOP);
                p.text(`y = ${waveAmplitude.toFixed(1)} sin(${waveFrequency.toFixed(1)}x + ${wavePhase.toFixed(1)})`, -radius, -radius - 30);
                
                p.pop();
                
                // 更新角度
                angle += 0.02;
            };
            
            // 绘制坐标系
            function drawAxes() {
                p.stroke(150);
                p.strokeWeight(1);
                
                // x轴
                p.line(-150, 0, p.width * 0.75, 0);
                // y轴
                p.line(0, -200, 0, 200);
                
                // 标记原点
                p.fill(50);
                p.noStroke();
                p.textSize(14);
                p.textAlign(p.CENTER, p.TOP);
                p.text("O", -10, 5);
                
                // 标记单位圆
                p.textAlign(p.LEFT, p.CENTER);
                p.text("1", 105 * waveAmplitude, 5);
                p.textAlign(p.CENTER, p.BOTTOM);
                p.text("1", 5, -105 * waveAmplitude);
            }
            
            // 绘制波形坐标系
            function drawWaveAxes() {
                p.stroke(150);
                p.strokeWeight(1);
                
                // x轴
                p.line(-100, 0, 400, 0);
                // y轴
                p.line(0, -200, 0, 200);
                
                // 标记刻度
                p.fill(50);
                p.noStroke();
                p.textSize(14);
                p.textAlign(p.CENTER, p.TOP);
                
                // x轴刻度 (π的倍数)
                for (let i = 1; i < 4; i++) {
                    const xPos = i * 100;
                    p.line(xPos, -5, xPos, 5);
                    p.text(`${i}π`, xPos, 10);
                }
                
                for (let i = -1; i >= -1; i--) {
                    const xPos = i * 100;
                    p.line(xPos, -5, xPos, 5);
                    p.text(`${i}π`, xPos, 10);
                }
                
                // y轴刻度
                p.textAlign(p.RIGHT, p.CENTER);
                p.line(-5, 100 * waveAmplitude, 5, 100 * waveAmplitude);
                p.text(`${waveAmplitude.toFixed(1)}`, -10, 100 * waveAmplitude);
                
                p.line(-5, -100 * waveAmplitude, 5, -100 * waveAmplitude);
                p.text(`-${waveAmplitude.toFixed(1)}`, -10, -100 * waveAmplitude);
            }
        };
        
        // 创建p5实例
        new p5(sketch);
    </script>
</body>
</html>
    

网友回复

我知道答案,我要回答