From fd8be8473b889a87f62331edc2689f7c2018266d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8B=8F=E6=9C=A8?= <mc183otpa@163.com> Date: Thu, 17 Apr 2025 21:34:11 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=96=87=E4=BB=B6=E8=87=B3?= =?UTF-8?q?=20/?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 数学函数图像生成.html | 557 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 557 insertions(+) create mode 100644 数学函数图像生成.html diff --git a/数学函数图像生成.html b/数学函数图像生成.html new file mode 100644 index 0000000..b8a23b3 --- /dev/null +++ b/数学函数图像生成.html @@ -0,0 +1,557 @@ +<!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.jsdelivr.net/npm/chart.js"></script> + <script src="https://cdn.jsdelivr.net/npm/mathjs@11.6.0/lib/browser/math.js"></script> + <style> + :root { + --primary-color: #4361ee; + --secondary-color: #3f37c9; + --accent-color: #4895ef; + --light-color: #f8f9fa; + --dark-color: #212529; + --success-color: #4cc9f0; + --warning-color: #f72585; + } + + * { + margin: 0; + padding: 0; + box-sizing: border-box; + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + } + + body { + background-color: #f5f7fa; + color: var(--dark-color); + line-height: 1.6; + padding: 20px; + min-width: 900px; + } + + .container { + max-width: 1400px; + min-width: 900px; + margin: 0 auto; + padding: 30px; + background-color: white; + border-radius: 12px; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.08); + } + + header { + text-align: center; + margin-bottom: 30px; + padding-bottom: 20px; + border-bottom: 1px solid rgba(0, 0, 0, 0.1); + } + + h1 { + color: var(--primary-color); + font-weight: 700; + margin-bottom: 10px; + font-size: 2.5rem; + } + + .subtitle { + color: #6c757d; + font-size: 1.1rem; + margin-bottom: 15px; + } + + .intro-box { + background-color: #f8f9fa; + padding: 20px; + border-radius: 8px; + margin-bottom: 30px; + border-left: 4px solid var(--accent-color); + } + + .intro-box h3 { + color: var(--primary-color); + margin-bottom: 10px; + } + + .intro-box ul { + padding-left: 20px; + } + + .intro-box li { + margin-bottom: 5px; + } + + .app-container { + display: grid; + grid-template-columns: 1fr 2fr; + gap: 30px; + } + + .control-panel { + background-color: #f8f9fa; + padding: 25px; + border-radius: 10px; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05); + min-width: 350px; + } + + .form-group { + margin-bottom: 20px; + } + + label { + display: block; + margin-bottom: 8px; + font-weight: 600; + color: var(--dark-color); + } + + input, select { + width: 100%; + padding: 12px 15px; + border: 1px solid #ced4da; + border-radius: 6px; + font-size: 1rem; + transition: all 0.3s; + } + + input:focus, select:focus { + outline: none; + border-color: var(--primary-color); + box-shadow: 0 0 0 3px rgba(67, 97, 238, 0.2); + } + + button { + background-color: var(--primary-color); + color: white; + border: none; + padding: 12px 20px; + border-radius: 6px; + cursor: pointer; + font-size: 1rem; + font-weight: 600; + transition: all 0.3s; + width: 100%; + margin-top: 10px; + } + + button:hover { + background-color: var(--secondary-color); + transform: translateY(-2px); + } + + .chart-container { + position: relative; + height: 500px; + background-color: white; + border-radius: 10px; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05); + padding: 15px; + min-width: 500px; + } + + .examples-panel { + margin-top: 25px; + padding-top: 20px; + border-top: 1px solid rgba(0, 0, 0, 0.1); + } + + .examples-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 15px; + cursor: pointer; + } + + .examples-header h3 { + color: var(--primary-color); + margin: 0; + } + + .examples-content { + display: none; + padding: 10px; + background-color: white; + border-radius: 6px; + } + + .examples-content.show { + display: block; + } + + .example-list { + list-style: none; + } + + .example-list li { + margin-bottom: 10px; + padding: 10px; + background-color: white; + border-radius: 6px; + border-left: 4px solid var(--accent-color); + cursor: pointer; + transition: all 0.2s; + } + + .example-list li:hover { + background-color: #e9ecef; + transform: translateX(5px); + } + + .error-message { + color: var(--warning-color); + margin-top: 10px; + font-size: 0.9rem; + display: none; + } + + .footer { + text-align: center; + margin-top: 40px; + color: #6c757d; + font-size: 0.9rem; + } + + .toggle-icon { + transition: transform 0.3s; + } + + .toggle-icon.rotated { + transform: rotate(180deg); + } + + .real-time-btn { + background-color: var(--accent-color); + } + + .real-time-btn.active { + background-color: var(--success-color); + } + + .button-group { + display: flex; + gap: 10px; + } + + .button-group button { + margin-top: 0; + } + </style> +</head> +<body> + <div class="container"> + <header> + <h1>数学函数图像生成器</h1> + <p class="subtitle">拥有基本运算,输入框不支持更高级参数填入</p> + </header> + + <div class="intro-box"> + <h3>使用说明</h3> + <p>手机请缩小屏幕,输入数学函数表达式,设置参数范围,即可生成精美的函数图像。</p> + <h3>支持的运算符和函数:</h3> + <ul> + <li>基本运算: +, -, *, /, ^ (幂)</li> + <li>三角函数: sin, cos, tan, asin, acos, atan</li> + <li>对数函数: log, log10, ln</li> + <li>其他函数: sqrt, abs, ceil, floor, round</li> + <li>常数: pi, e</li> + </ul> + <h3>注意事项:</h3> + <ul> + <li>使用 x 作为变量,区分大小写</li> + <li>不支持隐式乘法,必须使用 * 运算符</li> + <li>不支持分段函数和条件表达式</li> + <li>程序预留有示例方案</li> + <li>某些函数在特定区间可能无定义(如log(0))</li> + <li>复数结果将显示为NaN</li> + <li>无法生成创意图案,因为输入框限制,而且这个不是直角系</li> + <li>千万不要把所有数值输入过大和过小,否则会卡</li> + </ul> + </div> + + <div class="app-container"> + <div class="control-panel"> + <div class="form-group"> + <label for="function-input">函数表达式 (使用 x 作为变量)</label> + <input type="text" id="function-input" placeholder="例如: sin(x), x^2 + 2*x + 1" value="sin(x)"> + </div> + + <div class="form-group"> + <label for="x-min">X 最小值</label> + <input type="number" id="x-min" value="-10" step="0.1"> + </div> + + <div class="form-group"> + <label for="x-max">X 最大值</label> + <input type="number" id="x-max" value="10" step="0.1"> + </div> + + <div class="form-group"> + <label for="step">步长 (精度)</label> + <input type="number" id="step" value="0.1" step="0.01" min="0.01"> + </div> + + <div class="form-group"> + <label for="line-color">线条颜色</label> + <select id="line-color"> + <option value="#4361ee">蓝色</option> + <option value="#f72585">粉色</option> + <option value="#4cc9f0">青色</option> + <option value="#7209b7">紫色</option> + <option value="#3a0ca3">深蓝</option> + </select> + </div> + + <div class="button-group"> + <button id="plot-button">绘制函数图像</button> + <button id="real-time-btn" class="real-time-btn">实时生成图像</button> + </div> + <div id="error-message" class="error-message"></div> + + <div class="examples-panel"> + <div class="examples-header" id="examples-toggle"> + <h3>示例函数</h3> + <svg class="toggle-icon" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> + <polyline points="6 9 12 15 18 9"></polyline> + </svg> + </div> + <div class="examples-content" id="examples-content"> + <ul class="example-list"> + <li onclick="useExample('sin(x)')">正弦函数: sin(x)</li> + <li onclick="useExample('cos(x)')">余弦函数: cos(x)</li> + <li onclick="useExample('tan(x)')">正切函数: tan(x)</li> + <li onclick="useExample('x^2')">二次函数: x^2</li> + <li onclick="useExample('x^3 - 3*x')">三次函数: x^3 - 3*x</li> + <li onclick="useExample('sqrt(x)')">平方根函数: sqrt(x)</li> + <li onclick="useExample('log(x)')">自然对数: log(x)</li> + <li onclick="useExample('log10(x)')">常用对数: log10(x)</li> + <li onclick="useExample('exp(x)')">指数函数: exp(x)</li> + <li onclick="useExample('abs(x)')">绝对值函数: abs(x)</li> + <li onclick="useExample('sin(x)/x')">sinc函数: sin(x)/x</li> + <li onclick="useExample('1/x')">反比例函数: 1/x</li> + </ul> + </div> + </div> + </div> + + <div class="chart-container"> + <canvas id="function-chart"></canvas> + </div> + </div> + + <div class="footer"> + <p>© 2023 高级数学可视化工具 | 使用 Chart.js 和 Math.js 构建 | 支持缩放和平移功能</p> + </div> + </div> + + <script> + // 初始化图表 + const ctx = document.getElementById('function-chart').getContext('2d'); + let chart = new Chart(ctx, { + type: 'line', + data: { + datasets: [{ + label: '函数图像(支持横向触摸图像有信息跟踪)', + borderColor: '#4361ee', + borderWidth: 3, + pointRadius: 0, + fill: false, + tension: 0.1 + }] + }, + options: { + responsive: true, + maintainAspectRatio: false, + scales: { + x: { + title: { + display: true, + text: 'X轴', + font: { + size: 14, + weight: 'bold' + } + }, + grid: { + color: 'rgba(0, 0, 0, 0.05)' + } + }, + y: { + title: { + display: true, + text: 'Y轴', + font: { + size: 14, + weight: 'bold' + } + }, + grid: { + color: 'rgba(0, 0, 0, 0.05)' + } + } + }, + plugins: { + legend: { + position: 'top', + labels: { + font: { + size: 14 + } + } + }, + tooltip: { + mode: 'index', + intersect: false, + callbacks: { + label: function(context) { + return `f(${context.parsed.x.toFixed(2)}) = ${context.parsed.y.toFixed(4)}`; + } + } + }, + zoom: { + zoom: { + wheel: { + enabled: true, + }, + pinch: { + enabled: true + }, + mode: 'xy', + }, + pan: { + enabled: true, + mode: 'xy', + } + } + } + } + }); + + // 实时生成状态 + let isRealTime = false; + let inputElements = [ + document.getElementById('function-input'), + document.getElementById('x-min'), + document.getElementById('x-max'), + document.getElementById('step'), + document.getElementById('line-color') + ]; + + // 防抖函数,避免频繁更新 + function debounce(func, wait) { + let timeout; + return function() { + const context = this; + const args = arguments; + clearTimeout(timeout); + timeout = setTimeout(() => { + func.apply(context, args); + }, wait); + }; + } + + // 绘制函数 + function plotFunction() { + const funcInput = document.getElementById('function-input').value; + const xMin = parseFloat(document.getElementById('x-min').value); + const xMax = parseFloat(document.getElementById('x-max').value); + const step = parseFloat(document.getElementById('step').value); + const lineColor = document.getElementById('line-color').value; + + const errorElement = document.getElementById('error-message'); + errorElement.style.display = 'none'; + + try { + // 生成x值数组 + const xValues = []; + for (let x = xMin; x <= xMax; x += step) { + xValues.push(x); + } + + // 计算y值 + const yValues = []; + const scope = {}; + + for (let i = 0; i < xValues.length; i++) { + scope.x = xValues[i]; + try { + const y = math.evaluate(funcInput, scope); + yValues.push(y); + } catch (e) { + // 对于某些x值可能无法计算(如log(0)) + yValues.push(NaN); + } + } + + // 更新图表 + chart.data.labels = xValues; + chart.data.datasets[0].data = yValues.map((y, i) => ({x: xValues[i], y: y})); + chart.data.datasets[0].borderColor = lineColor; + chart.update(); + + } catch (error) { + errorElement.textContent = `错误: ${error.message}`; + errorElement.style.display = 'block'; + } + } + + // 使用示例函数 + function useExample(func) { + document.getElementById('function-input').value = func; + if (isRealTime) { + plotFunction(); + } + } + + // 切换实时生成模式 + function toggleRealTime() { + const realTimeBtn = document.getElementById('real-time-btn'); + isRealTime = !isRealTime; + + if (isRealTime) { + realTimeBtn.classList.add('active'); + realTimeBtn.textContent = '实时生成中...'; + // 立即绘制一次 + plotFunction(); + } else { + realTimeBtn.classList.remove('active'); + realTimeBtn.textContent = '实时生成图像'; + } + } + + // 设置输入框监听 + function setupInputListeners() { + const debouncedPlot = debounce(plotFunction, 500); + + inputElements.forEach(element => { + element.addEventListener('input', () => { + if (isRealTime) { + debouncedPlot(); + } + }); + }); + } + + // 切换示例面板 + document.getElementById('examples-toggle').addEventListener('click', function() { + const content = document.getElementById('examples-content'); + const icon = this.querySelector('.toggle-icon'); + content.classList.toggle('show'); + icon.classList.toggle('rotated'); + }); + + // 事件监听 + document.getElementById('plot-button').addEventListener('click', plotFunction); + document.getElementById('real-time-btn').addEventListener('click', toggleRealTime); + + // 设置输入监听 + setupInputListeners(); + + // 初始绘制 + plotFunction(); + </script> +</body> +</html>