AI 生成: 一个简洁美观的网页计算器,支持加、减、乘、除和清除功能,使用纯 HTML/CSS/JavaScript 实现。
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
# Simple Calculator Web
|
||||
|
||||
一个简洁美观的网页计算器,支持加、减、乘、除和清除功能。
|
||||
|
||||
## 功能
|
||||
|
||||
- 数字 0-9 输入
|
||||
- 小数点输入
|
||||
- 加法(+)、减法(-)、乘法(×)、除法(÷)
|
||||
- 等号(=)计算结果
|
||||
- 清除(C)重置计算器
|
||||
|
||||
## 目录结构
|
||||
|
||||
```
|
||||
simple-calculator-web/
|
||||
├── index.html # 主页面
|
||||
├── style.css # 样式文件
|
||||
├── script.js # 计算逻辑
|
||||
└── README.md # 说明文档
|
||||
```
|
||||
|
||||
## 使用方法
|
||||
|
||||
1. 下载或克隆本项目到本地。
|
||||
2. 直接用浏览器打开 `index.html` 即可使用。
|
||||
3. 无需安装任何依赖。
|
||||
|
||||
## 技术栈
|
||||
|
||||
- HTML5
|
||||
- CSS3(Flexbox + Grid 布局)
|
||||
- 原生 JavaScript(ES6)
|
||||
|
||||
## 预览
|
||||
|
||||
界面采用深色主题,按钮带有悬停和点击反馈效果,操作直观。
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>简易计算器</title>
|
||||
<link rel="stylesheet" href="style.css" />
|
||||
</head>
|
||||
<body>
|
||||
<main class="calculator">
|
||||
<!-- 显示区域 -->
|
||||
<div class="display" id="display">0</div>
|
||||
|
||||
<!-- 按键区域 -->
|
||||
<div class="keys">
|
||||
<button class="key key-clear" data-action="clear">C</button>
|
||||
<button class="key key-op" data-action="operator" data-op="÷">÷</button>
|
||||
<button class="key key-op" data-action="operator" data-op="×">×</button>
|
||||
<button class="key key-op" data-action="operator" data-op="-">−</button>
|
||||
|
||||
<button class="key" data-action="number" data-value="7">7</button>
|
||||
<button class="key" data-action="number" data-value="8">8</button>
|
||||
<button class="key" data-action="number" data-value="9">9</button>
|
||||
<button class="key key-op" data-action="operator" data-op="+">+</button>
|
||||
|
||||
<button class="key" data-action="number" data-value="4">4</button>
|
||||
<button class="key" data-action="number" data-value="5">5</button>
|
||||
<button class="key" data-action="number" data-value="6">6</button>
|
||||
<button class="key key-equals" data-action="equals" rowspan="2">=</button>
|
||||
|
||||
<button class="key" data-action="number" data-value="1">1</button>
|
||||
<button class="key" data-action="number" data-value="2">2</button>
|
||||
<button class="key" data-action="number" data-value="3">3</button>
|
||||
|
||||
<button class="key key-zero" data-action="number" data-value="0">0</button>
|
||||
<button class="key" data-action="decimal">.</button>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<script src="script.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,190 @@
|
||||
// ===== 计算器状态 =====
|
||||
let currentInput = '0'; // 当前输入的数字字符串
|
||||
let previousValue = null; // 上一个操作数
|
||||
let currentOperator = null; // 当前运算符
|
||||
let shouldResetInput = false; // 下次输入是否覆盖当前值
|
||||
|
||||
// ===== DOM 元素 =====
|
||||
const display = document.getElementById('display');
|
||||
|
||||
/**
|
||||
* 更新显示区域
|
||||
*/
|
||||
function updateDisplay() {
|
||||
display.textContent = currentInput;
|
||||
}
|
||||
|
||||
/**
|
||||
* 输入数字
|
||||
* @param {string} num
|
||||
*/
|
||||
function inputNumber(num) {
|
||||
if (shouldResetInput) {
|
||||
currentInput = num;
|
||||
shouldResetInput = false;
|
||||
} else {
|
||||
// 避免出现多个前导 0
|
||||
currentInput = currentInput === '0' ? num : currentInput + num;
|
||||
}
|
||||
updateDisplay();
|
||||
}
|
||||
|
||||
/**
|
||||
* 输入小数点
|
||||
*/
|
||||
function inputDecimal() {
|
||||
if (shouldResetInput) {
|
||||
currentInput = '0.';
|
||||
shouldResetInput = false;
|
||||
} else if (!currentInput.includes('.')) {
|
||||
currentInput += '.';
|
||||
}
|
||||
updateDisplay();
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行计算
|
||||
* @param {number} a
|
||||
* @param {number} b
|
||||
* @param {string} op
|
||||
* @returns {number}
|
||||
*/
|
||||
function calculate(a, b, op) {
|
||||
switch (op) {
|
||||
case '+': return a + b;
|
||||
case '-': return a - b;
|
||||
case '×': return a * b;
|
||||
case '÷':
|
||||
if (b === 0) return NaN; // 除零处理
|
||||
return a / b;
|
||||
default: return b;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 选择运算符
|
||||
* @param {string} op
|
||||
*/
|
||||
function chooseOperator(op) {
|
||||
const inputValue = parseFloat(currentInput);
|
||||
|
||||
// 连续按运算符时,先计算前一步
|
||||
if (previousValue !== null && currentOperator && !shouldResetInput) {
|
||||
const result = calculate(previousValue, inputValue, currentOperator);
|
||||
if (isNaN(result)) {
|
||||
currentInput = '错误';
|
||||
previousValue = null;
|
||||
currentOperator = null;
|
||||
shouldResetInput = true;
|
||||
updateDisplay();
|
||||
return;
|
||||
}
|
||||
previousValue = result;
|
||||
currentInput = formatNumber(result);
|
||||
} else {
|
||||
previousValue = inputValue;
|
||||
}
|
||||
|
||||
currentOperator = op;
|
||||
shouldResetInput = true;
|
||||
updateDisplay();
|
||||
}
|
||||
|
||||
/**
|
||||
* 按等号计算结果
|
||||
*/
|
||||
function pressEquals() {
|
||||
if (previousValue === null || currentOperator === null) return;
|
||||
|
||||
const inputValue = parseFloat(currentInput);
|
||||
const result = calculate(previousValue, inputValue, currentOperator);
|
||||
|
||||
if (isNaN(result)) {
|
||||
currentInput = '错误';
|
||||
} else {
|
||||
currentInput = formatNumber(result);
|
||||
}
|
||||
|
||||
previousValue = null;
|
||||
currentOperator = null;
|
||||
shouldResetInput = true;
|
||||
updateDisplay();
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除所有状态
|
||||
*/
|
||||
function clearAll() {
|
||||
currentInput = '0';
|
||||
previousValue = null;
|
||||
currentOperator = null;
|
||||
shouldResetInput = false;
|
||||
updateDisplay();
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化数字,避免过长的小数
|
||||
* @param {number} num
|
||||
* @returns {string}
|
||||
*/
|
||||
function formatNumber(num) {
|
||||
if (!isFinite(num)) return '错误';
|
||||
// 保留最多 10 位有效数字,去掉多余的 0
|
||||
return parseFloat(num.toPrecision(12)).toString();
|
||||
}
|
||||
|
||||
// ===== 事件绑定 =====
|
||||
document.querySelector('.keys').addEventListener('click', (e) => {
|
||||
const btn = e.target.closest('button');
|
||||
if (!btn) return;
|
||||
|
||||
const action = btn.dataset.action;
|
||||
|
||||
switch (action) {
|
||||
case 'number':
|
||||
inputNumber(btn.dataset.value);
|
||||
break;
|
||||
case 'decimal':
|
||||
inputDecimal();
|
||||
break;
|
||||
case 'operator':
|
||||
chooseOperator(btn.dataset.op);
|
||||
break;
|
||||
case 'equals':
|
||||
pressEquals();
|
||||
break;
|
||||
case 'clear':
|
||||
clearAll();
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// ===== 键盘支持 =====
|
||||
document.addEventListener('keydown', (e) => {
|
||||
const key = e.key;
|
||||
|
||||
if (/^[0-9]$/.test(key)) {
|
||||
inputNumber(key);
|
||||
} else if (key === '.') {
|
||||
inputDecimal();
|
||||
} else if (key === '+' || key === '-' || key === '*' || key === '/') {
|
||||
const map = { '*': '×', '/': '÷', '+': '+', '-': '-' };
|
||||
chooseOperator(map[key]);
|
||||
} else if (key === 'Enter' || key === '=') {
|
||||
e.preventDefault();
|
||||
pressEquals();
|
||||
} else if (key === 'Escape' || key.toLowerCase() === 'c') {
|
||||
clearAll();
|
||||
} else if (key === 'Backspace') {
|
||||
// 退格删除
|
||||
if (currentInput.length > 1 && currentInput !== '错误') {
|
||||
currentInput = currentInput.slice(0, -1);
|
||||
} else {
|
||||
currentInput = '0';
|
||||
}
|
||||
updateDisplay();
|
||||
}
|
||||
});
|
||||
|
||||
// ===== 初始化 =====
|
||||
updateDisplay();
|
||||
@@ -0,0 +1,132 @@
|
||||
/* ===== 全局重置 ===== */
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
font-family: 'Segoe UI', 'Helvetica Neue', Arial, sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: linear-gradient(135deg, #1e1e2f 0%, #2d2d44 100%);
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
/* ===== 计算器容器 ===== */
|
||||
.calculator {
|
||||
width: 100%;
|
||||
max-width: 360px;
|
||||
background: #2a2a3d;
|
||||
border-radius: 20px;
|
||||
padding: 24px;
|
||||
box-shadow: 0 20px 50px rgba(0, 0, 0, 0.45),
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
|
||||
/* ===== 显示区域 ===== */
|
||||
.display {
|
||||
background: #1b1b2a;
|
||||
color: #f5f5f5;
|
||||
font-size: 2.4rem;
|
||||
font-weight: 300;
|
||||
text-align: right;
|
||||
padding: 20px 18px;
|
||||
border-radius: 12px;
|
||||
margin-bottom: 20px;
|
||||
min-height: 80px;
|
||||
word-wrap: break-word;
|
||||
word-break: break-all;
|
||||
overflow: hidden;
|
||||
box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.5);
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
/* ===== 按键网格 ===== */
|
||||
.keys {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
/* ===== 按键基础样式 ===== */
|
||||
.key {
|
||||
border: none;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
font-size: 1.4rem;
|
||||
font-weight: 500;
|
||||
color: #eaeaea;
|
||||
background: #3a3a52;
|
||||
border-radius: 12px;
|
||||
padding: 18px 0;
|
||||
transition: transform 0.08s ease, background 0.2s ease, box-shadow 0.2s ease;
|
||||
user-select: none;
|
||||
box-shadow: 0 4px 0 #26263a;
|
||||
}
|
||||
|
||||
.key:hover {
|
||||
background: #45456a;
|
||||
}
|
||||
|
||||
.key:active {
|
||||
transform: translateY(2px);
|
||||
box-shadow: 0 2px 0 #26263a;
|
||||
}
|
||||
|
||||
/* ===== 运算符按钮 ===== */
|
||||
.key-op {
|
||||
background: #4a4a78;
|
||||
color: #ffd166;
|
||||
font-weight: 600;
|
||||
box-shadow: 0 4px 0 #2e2e4d;
|
||||
}
|
||||
|
||||
.key-op:hover {
|
||||
background: #5a5a92;
|
||||
}
|
||||
|
||||
/* ===== 清除按钮 ===== */
|
||||
.key-clear {
|
||||
background: #e63946;
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
box-shadow: 0 4px 0 #a8232e;
|
||||
}
|
||||
|
||||
.key-clear:hover {
|
||||
background: #ff4d5a;
|
||||
}
|
||||
|
||||
/* ===== 等号按钮(跨两行) ===== */
|
||||
.key-equals {
|
||||
grid-row: span 2;
|
||||
background: linear-gradient(180deg, #06d6a0, #04b184);
|
||||
color: #fff;
|
||||
font-weight: 700;
|
||||
font-size: 1.6rem;
|
||||
box-shadow: 0 4px 0 #028a66;
|
||||
}
|
||||
|
||||
.key-equals:hover {
|
||||
background: linear-gradient(180deg, #0be0aa, #05c492);
|
||||
}
|
||||
|
||||
/* ===== 0 按钮跨两列 ===== */
|
||||
.key-zero {
|
||||
grid-column: span 2;
|
||||
}
|
||||
|
||||
/* ===== 响应式 ===== */
|
||||
@media (max-width: 400px) {
|
||||
.display {
|
||||
font-size: 1.9rem;
|
||||
padding: 16px 14px;
|
||||
}
|
||||
.key {
|
||||
font-size: 1.2rem;
|
||||
padding: 15px 0;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user