计算器.html 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>计算器</title>
  7. <style>
  8. * {
  9. margin: 0;
  10. padding: 0;
  11. box-sizing: border-box;
  12. }
  13. body {
  14. display: flex;
  15. justify-content: center;
  16. align-items: center;
  17. min-height: 100vh;
  18. background-color: #f0f0f0;
  19. }
  20. .calculator {
  21. background-color: #fff;
  22. border-radius: 10px;
  23. box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);
  24. padding: 20px;
  25. width: 320px;
  26. }
  27. .box {
  28. background-color: #fff;
  29. border-radius: 5px;
  30. margin-bottom: 15px;
  31. padding: 15px;
  32. text-align: right;
  33. height: 80px;
  34. display: flex;
  35. flex-direction: column;
  36. justify-content: space-between;
  37. }
  38. .history {
  39. color: #888;
  40. font-size: 14px;
  41. min-height: 18px;
  42. }
  43. .input {
  44. font-size: 28px;
  45. font-weight: bold;
  46. overflow-x: auto;
  47. }
  48. .btnBox {
  49. display: flex;
  50. flex-wrap: wrap;
  51. width: 320px;
  52. margin-left: -20px;
  53. }
  54. .btnItem {
  55. width: 320px;
  56. height: 50px;
  57. display: flex;
  58. justify-content: space-around;
  59. margin-top: 10px;
  60. }
  61. .btn {
  62. width: 70px;
  63. padding: 10px;
  64. border: none;
  65. border-radius: 5px;
  66. padding: 15px;
  67. font-size: 18px;
  68. cursor: pointer;
  69. transition: all 0.2s ease;
  70. display: flex;
  71. align-items: center;
  72. justify-content: center;
  73. }
  74. .btn:hover {
  75. opacity: 0.9;
  76. transform: scale(1.02);
  77. }
  78. .operator {
  79. background-color: #ff9500;
  80. color: white;
  81. }
  82. .active {
  83. background-color: #999;
  84. color: white;
  85. }
  86. .equals {
  87. background-color: #007aff;
  88. color: white;
  89. }
  90. .zero {
  91. width: 140px;
  92. }
  93. </style>
  94. </head>
  95. <body>
  96. <div class="calculator">
  97. <div class="box">
  98. <div class="history" id="history"></div>
  99. <div class="input" id="main">0</div>
  100. </div>
  101. <div class="btnBox">
  102. <div class="btnItem">
  103. <div class="btn active" id="clear">C</div>
  104. <div class="btn active" id="plus-minus">±</div>
  105. <div class="btn active" data-article="%">%</div>
  106. <div class="btn operator" data-article="/">÷</div>
  107. </div>
  108. <div class="btnItem">
  109. <div class="btn" data-num="7">7</div>
  110. <div class="btn" data-num="8">8</div>
  111. <div class="btn" data-num="9">9</div>
  112. <div class="btn operator" data-article="*">x</div>
  113. </div>
  114. <div class="btnItem">
  115. <div class="btn" data-num="4">4</div>
  116. <div class="btn" data-num="5">5</div>
  117. <div class="btn" data-num="6">6</div>
  118. <div class="btn operator" data-article="-">-</div>
  119. </div>
  120. <div class="btnItem">
  121. <div class="btn" data-num="1">1</div>
  122. <div class="btn" data-num="2">2</div>
  123. <div class="btn" data-num="3">3</div>
  124. <div class="btn operator" data-article="+">+</div>
  125. </div>
  126. <div class="btnItem ">
  127. <div class="btn zero" data-num="0">0</div>
  128. <div class="btn" data-num=".">.</div>
  129. <div class="btn equals" id="equals">=</div>
  130. </div>
  131. </div>
  132. </div>
  133. <script>
  134. // DOM元素
  135. //内容盒子
  136. const main = document.getElementById('main');
  137. // 历史盒子
  138. const history = document.getElementById('history');
  139. // 归零
  140. const clearBtn = document.getElementById('clear');
  141. // 正负号
  142. const plusMinusBtn = document.getElementById('plus-minus');
  143. // 等于号
  144. const equalsBtn = document.getElementById('equals');
  145. // 所有的数字键
  146. const numberBtns = document.querySelectorAll('[data-num]');
  147. // 所有的功能键
  148. const operatorBtns = document.querySelectorAll('[data-article]');
  149. // 定义状态
  150. // 当前值
  151. let currentValue = "0";
  152. // 上一个值
  153. let previousValue = null;
  154. // 当前操作符
  155. let currentOperand = null;
  156. // 是否归零
  157. let resetOnNextInput = false;
  158. // 上一个/最后操作符
  159. let lastKeyWasOperator = false;
  160. // 实时输出
  161. function updateMain() {
  162. // 赋值
  163. main.textContent = currentValue;
  164. }
  165. // 监听事件
  166. function handleBtn() {
  167. numberBtns.forEach((item) => {
  168. item.addEventListener('click', () => {
  169. handleNumber(item.dataset.num)
  170. })
  171. })
  172. // 归零事件
  173. clearBtn.addEventListener('click', resetCalculator);
  174. // 取反
  175. plusMinusBtn.addEventListener('click', togglePlusMinus);
  176. // 功能键
  177. operatorBtns.forEach(btn => {
  178. console.log(btn.dataset.article,'item')
  179. btn.addEventListener('click', () => {
  180. handleInput(btn.dataset.article);
  181. });
  182. });
  183. // 等号按钮
  184. equalsBtn.addEventListener('click', calculateResult);
  185. }
  186. // 历史记录
  187. function updateHistory() {
  188. if (previousValue && currentOperator) {
  189. // 格式化运算符以匹配显示
  190. const operatorMap = {
  191. '+': '+',
  192. '-': '-',
  193. '*': 'x',
  194. '/': '÷',
  195. '%': '%'
  196. };
  197. const mainOperator = operatorMap[currentOperator] || currentOperator;
  198. history.textContent = `${previousValue} ${mainOperator}`;
  199. } else {
  200. history.textContent = '';
  201. }
  202. }
  203. // 处理运算符输入
  204. function handleInput(operator) {
  205. // 如果上次输入的是运算符,则替换运算符
  206. if (lastKeyWasOperator && previousValue !== null) {
  207. currentOperator = operator;
  208. updateHistory();
  209. return;
  210. }
  211. // 如果有前一个值和运算符,则先计算结果
  212. if (previousValue !== null && currentOperator !== null && !resetOnNextInput) {
  213. calculateResult();
  214. }
  215. // 保存当前值和运算符
  216. previousValue = currentValue;
  217. currentOperator = operator;
  218. lastKeyWasOperator = true;
  219. resetOnNextInput = true;
  220. updateHistory();
  221. }
  222. // 计算结果
  223. function calculateResult() {
  224. if (!previousValue || !currentOperator) return;
  225. const prev = parseFloat(previousValue);
  226. const current = parseFloat(currentValue);
  227. let result;
  228. try {
  229. switch (currentOperator) {
  230. case '+':
  231. result = prev + current;
  232. break;
  233. case '-':
  234. result = prev - current;
  235. break;
  236. case '*':
  237. result = prev * current;
  238. break;
  239. case '/':
  240. if (current === 0) {
  241. main.textContent = '错误';
  242. setTimeout(() => {
  243. resetCalculator();
  244. }, 1000);
  245. return;
  246. }
  247. result = prev / current;
  248. break;
  249. case '%':
  250. result = prev % current;
  251. break;
  252. default:
  253. return;
  254. }
  255. currentValue = result;
  256. previousValue = null;
  257. currentOperator = null;
  258. resetOnNextInput = true;
  259. lastKeyWasOperator = false;
  260. updateMain();
  261. updateHistory();
  262. } catch (error) {
  263. main.textContent = '错误';
  264. setTimeout(() => {
  265. resetCalculator();
  266. }, 1000);
  267. }
  268. }
  269. // 数字处理
  270. function handleNumber(val) {
  271. console.log(val,'val')
  272. // 1.当前值0 / 重置 直接替换 并且传入值不可以是小数点
  273. if (resetOnNextInput || currentValue === '0' && val !== '.') {
  274. currentValue = val;
  275. resetOnNextInput = false;
  276. }
  277. // 如果输入值有小数点
  278. else if (val == '.') {
  279. // 如果有多个小数点 忽略
  280. if (currentValue.includes(".")) return;
  281. // 反之正常拼接
  282. currentValue += val
  283. }
  284. // 正常追加数字
  285. else {
  286. // 限制输入长度12
  287. if (currentValue.length <= 12) {
  288. currentValue += val;
  289. } else {
  290. alert("已超出最大范围!")
  291. }
  292. }
  293. updateMain();
  294. }
  295. // 清空计算器
  296. function resetCalculator() {
  297. currentValue = '0';
  298. previousValue = null;
  299. currentOperator = null;
  300. resetOnNextInput = false;
  301. lastKeyWasOperator = false;
  302. updateMain();
  303. }
  304. // 取反
  305. function togglePlusMinus() {
  306. if (currentValue === '0') return;
  307. currentValue = currentValue.startsWith('-')
  308. ? currentValue.substring(1)
  309. : '-' + currentValue;
  310. updateMain();
  311. }
  312. // 实例化计算器
  313. function init() {
  314. updateMain();
  315. handleBtn();
  316. }
  317. // 加载完成后绘制
  318. document.addEventListener('DOMContentLoaded', init)
  319. </script>
  320. </body>
  321. </html>