上传文件至 /
This commit is contained in:
parent
4f3659edf0
commit
fd8be8473b
557
数学函数图像生成.html
Normal file
557
数学函数图像生成.html
Normal file
@ -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>
|
Loading…
x
Reference in New Issue
Block a user