<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>小米计算器</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
-webkit-tap-highlight-color: transparent;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
min-height: 100vh;
display: flex;
justify-content: center;
align-items: center;
padding: 20px;
}
.calculator {
width: 100%;
max-width: 380px;
background: #000;
border-radius: 40px;
padding: 30px 25px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255, 255, 255, 0.1);
}
.display {
background: transparent;
text-align: right;
padding: 20px 10px 40px;
margin-bottom: 20px;
}
.expression {
color: rgba(255, 255, 255, 0.6);
font-size: 28px;
min-height: 36px;
word-break: break-all;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.result {
color: #fff;
font-size: 56px;
font-weight: 300;
min-height: 70px;
word-break: break-all;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
transition: font-size 0.1s;
}
.result.small {
font-size: 40px;
}
.buttons {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 12px;
}
.btn {
width: 100%;
aspect-ratio: 1;
border: none;
border-radius: 50%;
font-size: 28px;
font-weight: 400;
cursor: pointer;
transition: all 0.15s ease;
background: #333;
color: #fff;
display: flex;
align-items: center;
justify-content: center;
user-select: none;
}
.btn:active {
transform: scale(0.92);
}
.btn:disabled {
opacity: 0.3;
cursor: not-allowed;
}
.btn.number {
background: #333;
color: #fff;
}
.btn.number:hover {
background: #444;
}
.btn.operator {
background: #ff9f0a;
color: #fff;
}
.btn.operator:hover {
background: #ffb340;
}
.btn.operator:active {
background: #ff9f0a;
}
.btn.function {
background: #a5a5a5;
color: #000;
}
.btn.function:hover {
background: #bfbfbf;
}
.btn.equals {
background: #ff9f0a;
color: #fff;
grid-column: span 1;
}
.btn.equals:hover {
background: #ffb340;
}
.btn.zero {
grid-column: span 2;
aspect-ratio: auto;
height: calc((100% - 36px) / 4);
border-radius: 35px;
justify-content: flex-start;
padding-left: 30px;
}
.status-indicator {
position: absolute;
top: 15px;
right: 15px;
width: 12px;
height: 12px;
border-radius: 50%;
background: transparent;
transition: all 0.3s ease;
}
.status-indicator.locked {
background: #ff4444;
box-shadow: 0 0 10px #ff4444;
animation: pulse 1.5s infinite;
}
@keyframes pulse {
0%, 100% {
opacity: 1;
transform: scale(1);
}
50% {
opacity: 0.6;
transform: scale(1.2);
}
}
.lock-hint {
color: rgba(255, 255, 255, 0.3);
font-size: 12px;
text-align: center;
margin-top: 15px;
opacity: 0;
transition: opacity 0.3s;
}
.lock-hint.visible {
opacity: 1;
}
/* 适配不同屏幕尺寸 */
@media (max-width: 400px) {
.calculator {
border-radius: 30px;
padding: 20px 15px;
}
.result {
font-size: 48px;
}
.btn {
font-size: 24px;
}
}
</style>
</head>
<body>
<div class="calculator">
<div class="status-indicator" id="statusIndicator"></div>
<div class="display">
<div class="expression" id="expression"></div>
<div class="result" id="result">0</div>
</div>
<div class="buttons">
<button class="btn function" data-action="clear">AC</button>
<button class="btn function" data-action="sign">+/-</button>
<button class="btn function" data-action="percent">%</button>
<button class="btn operator" data-action="divide">÷</button>
<button class="btn number" data-value="7">7</button>
<button class="btn number" data-value="8">8</button>
<button class="btn number" data-value="9">9</button>
<button class="btn operator" data-action="multiply">×</button>
<button class="btn number" data-value="4">4</button>
<button class="btn number" data-value="5">5</button>
<button class="btn number" data-value="6">6</button>
<button class="btn operator" data-action="subtract">-</button>
<button class="btn number" data-value="1">1</button>
<button class="btn number" data-value="2">2</button>
<button class="btn number" data-value="3">3</button>
<button class="btn operator" data-action="add">+</button>
<button class="btn number zero" data-value="0">0</button>
<button class="btn number" data-value=".">.</button>
<button class="btn equals" data-action="equals">=</button>
</div>
<div class="lock-hint" id="lockHint">点击3次等号锁定/解锁</div>
</div>
<script>
class Calculator {
constructor() {
this.currentValue = '0';
this.previousValue = '';
this.operator = null;
this.waitingForNewValue = false;
this.expression = '';
// 锁定状态相关
this.isLocked = false;
this.equalsPressCount = 0;
this.equalsPressTimer = null;
this.lockedValue = ''; // 锁定前显示的值
this.lockTime = null; // 锁定时的时间
this.expressionEl = document.getElementById('expression');
this.resultEl = document.getElementById('result');
this.statusIndicator = document.getElementById('statusIndicator');
this.lockHint = document.getElementById('lockHint');
this.init();
}
init() {
const buttons = document.querySelectorAll('.btn');
buttons.forEach(btn => {
btn.addEventListener('click', () => this.handleButton(btn));
});
// 键盘支持
document.addEventListener('keydown', (e) => this.handleKeyboard(e));
// 显示提示
setTimeout(() => {
this.lockHint.classList.add('visible');
}, 1000);
}
handleButton(btn) {
const action = btn.dataset.action;
const value = btn.dataset.value;
if (this.isLocked) {
// 锁定状态下,只响应等于号来解锁
if (action === 'equals') {
this.handleEqualsInLockedState();
} else {
// 其他按键正常显示,但不影响实际计算
this.displayLockedInput(btn);
}
return;
}
if (action === 'equals') {
this.handleEquals();
} else if (action === 'clear') {
this.clear();
} else if (action === 'sign') {
this.toggleSign();
} else if (action === 'percent') {
this.percent();
} else if (action === 'add') {
this.setOperator('+');
} else if (action === 'subtract') {
this.setOperator('-');
} else if (action === 'multiply') {
this.setOperator('×');
} else if (action === 'divide') {
this.setOperator('÷');
} else if (value) {
this.inputNumber(value);
}
}
handleKeyboard(e) {
const key = e.key;
if (this.isLocked) {
// 锁定状态下,只响应等于号来解锁,其他按键正常显示
if (key === 'Enter' || key === '=') {
e.preventDefault();
this.handleEqualsInLockedState();
} else if (key === 'Escape') {
// ESC显示AC
this.resultEl.textContent = 'AC';
} else if (key === 'Backspace') {
// 退格显示←
this.resultEl.textContent = '←';
} else if (key === '+') {
this.resultEl.textContent = '+';
} else if (key === '-') {
this.resultEl.textContent = '-';
} else if (key === '*') {
this.resultEl.textContent = '×';
} else if (key === '/') {
this.resultEl.textContent = '÷';
} else if (key === '%') {
this.resultEl.textContent = '%';
} else if (key >= '0' && key <= '9' || key === '.') {
this.resultEl.textContent = key;
}
return;
}
if (key === 'Escape') {
this.clear();
} else if (key === 'Enter' || key === '=') {
e.preventDefault();
this.handleEquals();
} else if (key === 'Backspace') {
this.backspace();
} else if (key === '+' || key === '-') {
this.setOperator(key);
} else if (key === '*') {
this.setOperator('×');
} else if (key === '/') {
e.preventDefault();
this.setOperator('÷');
} else if (key === '%') {
this.percent();
} else if (key >= '0' && key <= '9' || key === '.') {
this.inputNumber(key);
}
}
displayLockedInput(btn) {
// 在锁定状态下,显示用户输入的内容作为视觉反馈
const value = btn.dataset.value || btn.textContent;
this.resultEl.textContent = value;
}
handleEquals() {
// 清除之前的计时器
if (this.equalsPressTimer) {
clearTimeout(this.equalsPressTimer);
}
this.equalsPressCount++;
// 检查是否在短时间内连续点击3次
if (this.equalsPressCount >= 3) {
// 进入锁定状态
this.enterLockState();
this.equalsPressCount = 0;
return;
}
// 重置计数器(2秒内没有点击则重置)
this.equalsPressTimer = setTimeout(() => {
this.equalsPressCount = 0;
}, 2000);
// 正常计算
this.calculate();
}
handleEqualsInLockedState() {
if (this.equalsPressTimer) {
clearTimeout(this.equalsPressTimer);
}
this.equalsPressCount++;
if (this.equalsPressCount >= 3) {
// 解除锁定状态,显示时间差
this.exitLockState();
this.equalsPressCount = 0;
return;
}
this.equalsPressTimer = setTimeout(() => {
this.equalsPressCount = 0;
}, 2000);
}
enterLockState() {
this.isLocked = true;
// 保存锁定前的显示值
this.lockedValue = this.resultEl.textContent;
// 保存锁定时的时间
this.lockTime = new Date();
// 视觉反馈
this.statusIndicator.classList.add('locked');
this.lockHint.textContent = '已锁定 - 再按3次=解锁';
}
exitLockState() {
// 获取当前时间
const now = new Date();
const month = now.getMonth() + 1;
const day = now.getDate();
const hour = now.getHours();
const minute = now.getMinutes();
// 构建时间数字:月日小时分钟
const timeNumber = parseInt(`${month}${day}${hour}${minute}`);
// 获取锁定前的数值
const lockedValueNum = parseFloat(this.lockedValue.replace(/,/g, '')) || 0;
// 计算需要显示的运算表达式,让结果正好是当前时间
// 显示:锁定前的值 + (当前时间 - 锁定前的值) = 当前时间
const diff = timeNumber - lockedValueNum;
const operator = diff >= 0 ? '+' : '-';
const absDiff = Math.abs(diff);
// 解除锁定
this.isLocked = false;
this.statusIndicator.classList.remove('locked');
this.lockHint.textContent = '点击3次等号锁定/解锁';
// 显示表达式和结果
this.expression = `${this.lockedValue} ${operator} ${absDiff.toLocaleString()} =`;
this.currentValue = timeNumber.toString();
this.previousValue = '';
this.operator = null;
this.waitingForNewValue = true;
this.updateDisplay();
}
inputNumber(num) {
if (this.waitingForNewValue) {
this.currentValue = num === '.' ? '0.' : num;
this.waitingForNewValue = false;
} else {
if (num === '.' && this.currentValue.includes('.')) return;
if (this.currentValue === '0' && num !== '.') {
this.currentValue = num;
} else {
this.currentValue += num;
}
}
this.updateDisplay();
}
setOperator(op) {
if (this.operator && !this.waitingForNewValue) {
this.calculate();
}
this.previousValue = this.currentValue;
this.operator = op;
this.waitingForNewValue = true;
this.expression = `${this.formatNumber(this.previousValue)} ${op}`;
this.updateDisplay();
}
calculate() {
if (!this.operator || this.previousValue === '') return;
const prev = parseFloat(this.previousValue);
const current = parseFloat(this.currentValue);
let result;
switch (this.operator) {
case '+':
result = prev + current;
break;
case '-':
result = prev - current;
break;
case '×':
result = prev * current;
break;
case '÷':
if (current === 0) {
this.resultEl.textContent = 'Error';
return;
}
result = prev / current;
break;
}
this.expression = `${this.formatNumber(this.previousValue)} ${this.operator} ${this.formatNumber(this.currentValue)} =`;
this.currentValue = this.resultToString(result);
this.operator = null;
this.previousValue = '';
this.waitingForNewValue = true;
this.updateDisplay();
}
resultToString(num) {
if (Number.isInteger(num)) {
return num.toString();
}
// 处理浮点数精度问题
return parseFloat(num.toPrecision(12)).toString();
}
clear() {
this.currentValue = '0';
this.previousValue = '';
this.operator = null;
this.expression = '';
this.waitingForNewValue = false;
this.updateDisplay();
}
backspace() {
if (this.waitingForNewValue) {
this.clear();
return;
}
if (this.currentValue.length > 1) {
this.currentValue = this.currentValue.slice(0, -1);
} else {
this.currentValue = '0';
}
this.updateDisplay();
}
toggleSign() {
if (this.currentValue !== '0') {
this.currentValue = this.currentValue.startsWith('-')
? this.currentValue.slice(1)
: '-' + this.currentValue;
}
this.updateDisplay();
}
percent() {
this.currentValue = (parseFloat(this.currentValue) / 100).toString();
this.updateDisplay();
}
formatNumber(num) {
const n = parseFloat(num);
if (Number.isInteger(n)) {
return n.toLocaleString();
}
return n.toPrecision(12);
}
updateDisplay() {
this.expressionEl.textContent = this.expression;
const num = parseFloat(this.currentValue);
if (this.currentValue.length > 10) {
this.resultEl.classList.add('small');
} else {
this.resultEl.classList.remove('small');
}
// 如果是整数,添加千位分隔符
if (Number.isInteger(num) && !isNaN(num)) {
this.resultEl.textContent = num.toLocaleString();
} else {
this.resultEl.textContent = this.currentValue;
}
}
}
// 初始化计算器
const calc = new Calculator();
</script>
</body>
</html>
请先 登录 后发表评论。
评论
共 0 条