|
@@ -0,0 +1,324 @@
|
|
|
+<!DOCTYPE html>
|
|
|
+<html lang="zh-CN">
|
|
|
+
|
|
|
+<head>
|
|
|
+ <meta charset="UTF-8">
|
|
|
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
+ <title>计算器</title>
|
|
|
+ <style>
|
|
|
+ * {
|
|
|
+ margin: 0;
|
|
|
+ padding: 0;
|
|
|
+ box-sizing: border-box;
|
|
|
+ }
|
|
|
+ body {
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ min-height: 100vh;
|
|
|
+ background-color: #f0f0f0;
|
|
|
+ }
|
|
|
+ .calculator {
|
|
|
+ background-color: #fff;
|
|
|
+ border-radius: 10px;
|
|
|
+ box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);
|
|
|
+ padding: 20px;
|
|
|
+ width: 320px;
|
|
|
+ }
|
|
|
+ .box {
|
|
|
+ background-color: #fff;
|
|
|
+ border-radius: 5px;
|
|
|
+ margin-bottom: 15px;
|
|
|
+ padding: 15px;
|
|
|
+ text-align: right;
|
|
|
+ height: 80px;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ justify-content: space-between;
|
|
|
+ }
|
|
|
+ .history {
|
|
|
+ color: #888;
|
|
|
+ font-size: 14px;
|
|
|
+ min-height: 18px;
|
|
|
+ }
|
|
|
+ .input {
|
|
|
+ font-size: 28px;
|
|
|
+ font-weight: bold;
|
|
|
+ overflow-x: auto;
|
|
|
+ }
|
|
|
+ .btnBox {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ width: 320px;
|
|
|
+ margin-left: -20px;
|
|
|
+ }
|
|
|
+ .btnItem {
|
|
|
+ width: 320px;
|
|
|
+ height: 50px;
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-around;
|
|
|
+ margin-top: 10px;
|
|
|
+ }
|
|
|
+ .btn {
|
|
|
+ width: 70px;
|
|
|
+ padding: 10px;
|
|
|
+ border: none;
|
|
|
+ border-radius: 5px;
|
|
|
+ padding: 15px;
|
|
|
+ font-size: 18px;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: all 0.2s ease;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ }
|
|
|
+ .btn:hover {
|
|
|
+ opacity: 0.9;
|
|
|
+ transform: scale(1.02);
|
|
|
+ }
|
|
|
+ .operator {
|
|
|
+ background-color: #ff9500;
|
|
|
+ color: white;
|
|
|
+ }
|
|
|
+ .active {
|
|
|
+ background-color: #999;
|
|
|
+ color: white;
|
|
|
+ }
|
|
|
+ .equals {
|
|
|
+ background-color: #007aff;
|
|
|
+ color: white;
|
|
|
+ }
|
|
|
+ .zero {
|
|
|
+ width: 140px;
|
|
|
+ }
|
|
|
+ </style>
|
|
|
+</head>
|
|
|
+
|
|
|
+<body>
|
|
|
+ <div class="calculator">
|
|
|
+ <div class="box">
|
|
|
+ <div class="history" id="history"></div>
|
|
|
+ <div class="input" id="main">0</div>
|
|
|
+ </div>
|
|
|
+ <div class="btnBox">
|
|
|
+ <div class="btnItem">
|
|
|
+ <div class="btn active" id="clear">C</div>
|
|
|
+ <div class="btn active" id="plus-minus">±</div>
|
|
|
+ <div class="btn active" data-article="%">%</div>
|
|
|
+ <div class="btn operator" data-article="/">÷</div>
|
|
|
+ </div>
|
|
|
+ <div class="btnItem">
|
|
|
+ <div class="btn" data-num="7">7</div>
|
|
|
+ <div class="btn" data-num="8">8</div>
|
|
|
+ <div class="btn" data-num="9">9</div>
|
|
|
+ <div class="btn operator" data-article="*">x</div>
|
|
|
+ </div>
|
|
|
+ <div class="btnItem">
|
|
|
+ <div class="btn" data-num="4">4</div>
|
|
|
+ <div class="btn" data-num="5">5</div>
|
|
|
+ <div class="btn" data-num="6">6</div>
|
|
|
+ <div class="btn operator" data-article="-">-</div>
|
|
|
+ </div>
|
|
|
+ <div class="btnItem">
|
|
|
+ <div class="btn" data-num="1">1</div>
|
|
|
+ <div class="btn" data-num="2">2</div>
|
|
|
+ <div class="btn" data-num="3">3</div>
|
|
|
+ <div class="btn operator" data-article="+">+</div>
|
|
|
+ </div>
|
|
|
+ <div class="btnItem ">
|
|
|
+ <div class="btn zero" data-num="0">0</div>
|
|
|
+ <div class="btn" data-num=".">.</div>
|
|
|
+ <div class="btn equals" id="equals">=</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <script>
|
|
|
+ // DOM元素
|
|
|
+ //内容盒子
|
|
|
+ const main = document.getElementById('main');
|
|
|
+ // 历史盒子
|
|
|
+ const history = document.getElementById('history');
|
|
|
+ // 归零
|
|
|
+ const clearBtn = document.getElementById('clear');
|
|
|
+ // 正负号
|
|
|
+ const plusMinusBtn = document.getElementById('plus-minus');
|
|
|
+ // 等于号
|
|
|
+ const equalsBtn = document.getElementById('equals');
|
|
|
+ // 所有的数字键
|
|
|
+ const numberBtns = document.querySelectorAll('[data-num]');
|
|
|
+ // 所有的功能键
|
|
|
+ const operatorBtns = document.querySelectorAll('[data-article]');
|
|
|
+ // 定义状态
|
|
|
+ // 当前值
|
|
|
+ let currentValue = "0";
|
|
|
+ // 上一个值
|
|
|
+ let previousValue = null;
|
|
|
+ // 当前操作符
|
|
|
+ let currentOperand = null;
|
|
|
+ // 是否归零
|
|
|
+ let resetOnNextInput = false;
|
|
|
+ // 上一个/最后操作符
|
|
|
+ let lastKeyWasOperator = false;
|
|
|
+ // 实时输出
|
|
|
+ function updateMain() {
|
|
|
+ // 赋值
|
|
|
+ main.textContent = currentValue;
|
|
|
+ }
|
|
|
+ // 监听事件
|
|
|
+ function handleBtn() {
|
|
|
+ numberBtns.forEach((item) => {
|
|
|
+ item.addEventListener('click', () => {
|
|
|
+ handleNumber(item.dataset.num)
|
|
|
+ })
|
|
|
+ })
|
|
|
+ // 归零事件
|
|
|
+ clearBtn.addEventListener('click', resetCalculator);
|
|
|
+ // 取反
|
|
|
+ plusMinusBtn.addEventListener('click', togglePlusMinus);
|
|
|
+ // 功能键
|
|
|
+ operatorBtns.forEach(btn => {
|
|
|
+ console.log(btn.dataset.article,'item')
|
|
|
+ btn.addEventListener('click', () => {
|
|
|
+ handleInput(btn.dataset.article);
|
|
|
+ });
|
|
|
+ });
|
|
|
+ // 等号按钮
|
|
|
+ equalsBtn.addEventListener('click', calculateResult);
|
|
|
+ }
|
|
|
+ // 历史记录
|
|
|
+ function updateHistory() {
|
|
|
+ if (previousValue && currentOperator) {
|
|
|
+ // 格式化运算符以匹配显示
|
|
|
+ const operatorMap = {
|
|
|
+ '+': '+',
|
|
|
+ '-': '-',
|
|
|
+ '*': 'x',
|
|
|
+ '/': '÷',
|
|
|
+ '%': '%'
|
|
|
+ };
|
|
|
+ const mainOperator = operatorMap[currentOperator] || currentOperator;
|
|
|
+ history.textContent = `${previousValue} ${mainOperator}`;
|
|
|
+ } else {
|
|
|
+ history.textContent = '';
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 处理运算符输入
|
|
|
+ function handleInput(operator) {
|
|
|
+ // 如果上次输入的是运算符,则替换运算符
|
|
|
+ if (lastKeyWasOperator && previousValue !== null) {
|
|
|
+ currentOperator = operator;
|
|
|
+ updateHistory();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ // 如果有前一个值和运算符,则先计算结果
|
|
|
+ if (previousValue !== null && currentOperator !== null && !resetOnNextInput) {
|
|
|
+ calculateResult();
|
|
|
+ }
|
|
|
+ // 保存当前值和运算符
|
|
|
+ previousValue = currentValue;
|
|
|
+ currentOperator = operator;
|
|
|
+ lastKeyWasOperator = true;
|
|
|
+ resetOnNextInput = true;
|
|
|
+ updateHistory();
|
|
|
+ }
|
|
|
+ // 计算结果
|
|
|
+ function calculateResult() {
|
|
|
+ if (!previousValue || !currentOperator) return;
|
|
|
+ const prev = parseFloat(previousValue);
|
|
|
+ const current = parseFloat(currentValue);
|
|
|
+ let result;
|
|
|
+ try {
|
|
|
+ switch (currentOperator) {
|
|
|
+ case '+':
|
|
|
+ result = prev + current;
|
|
|
+ break;
|
|
|
+ case '-':
|
|
|
+ result = prev - current;
|
|
|
+ break;
|
|
|
+ case '*':
|
|
|
+ result = prev * current;
|
|
|
+ break;
|
|
|
+ case '/':
|
|
|
+ if (current === 0) {
|
|
|
+ main.textContent = '错误';
|
|
|
+ setTimeout(() => {
|
|
|
+ resetCalculator();
|
|
|
+ }, 1000);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ result = prev / current;
|
|
|
+ break;
|
|
|
+ case '%':
|
|
|
+ result = prev % current;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ currentValue = result;
|
|
|
+ previousValue = null;
|
|
|
+ currentOperator = null;
|
|
|
+ resetOnNextInput = true;
|
|
|
+ lastKeyWasOperator = false;
|
|
|
+ updateMain();
|
|
|
+ updateHistory();
|
|
|
+ } catch (error) {
|
|
|
+ main.textContent = '错误';
|
|
|
+ setTimeout(() => {
|
|
|
+ resetCalculator();
|
|
|
+ }, 1000);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 数字处理
|
|
|
+ function handleNumber(val) {
|
|
|
+ console.log(val,'val')
|
|
|
+ // 1.当前值0 / 重置 直接替换 并且传入值不可以是小数点
|
|
|
+ if (resetOnNextInput || currentValue === '0' && val !== '.') {
|
|
|
+ currentValue = val;
|
|
|
+ resetOnNextInput = false;
|
|
|
+ }
|
|
|
+ // 如果输入值有小数点
|
|
|
+ else if (val == '.') {
|
|
|
+ // 如果有多个小数点 忽略
|
|
|
+ if (currentValue.includes(".")) return;
|
|
|
+ // 反之正常拼接
|
|
|
+ currentValue += val
|
|
|
+ }
|
|
|
+ // 正常追加数字
|
|
|
+ else {
|
|
|
+ // 限制输入长度12
|
|
|
+ if (currentValue.length <= 12) {
|
|
|
+ currentValue += val;
|
|
|
+ } else {
|
|
|
+ alert("已超出最大范围!")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ updateMain();
|
|
|
+ }
|
|
|
+ // 清空计算器
|
|
|
+ function resetCalculator() {
|
|
|
+ currentValue = '0';
|
|
|
+ previousValue = null;
|
|
|
+ currentOperator = null;
|
|
|
+ resetOnNextInput = false;
|
|
|
+ lastKeyWasOperator = false;
|
|
|
+ updateMain();
|
|
|
+ }
|
|
|
+ // 取反
|
|
|
+ function togglePlusMinus() {
|
|
|
+ if (currentValue === '0') return;
|
|
|
+ currentValue = currentValue.startsWith('-')
|
|
|
+ ? currentValue.substring(1)
|
|
|
+ : '-' + currentValue;
|
|
|
+ updateMain();
|
|
|
+ }
|
|
|
+ // 实例化计算器
|
|
|
+ function init() {
|
|
|
+ updateMain();
|
|
|
+ handleBtn();
|
|
|
+ }
|
|
|
+ // 加载完成后绘制
|
|
|
+ document.addEventListener('DOMContentLoaded', init)
|
|
|
+ </script>
|
|
|
+
|
|
|
+</body>
|
|
|
+</html>
|