先看效果:
再看代码(查看更多):
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>计算器title>
<style>
* {
box-sizing: border-box;
}
body {
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
font-size: 10px;
background: #232323;
}
@media (max-width: 576px) {
body {
height: 100h;
}
}
.calc {
width: 50em;
aspect-ratio: 1/1.5;
margin: 2em;
background: #232323;
background: #CED4CA;
background: #EBECE9;
padding: 4em;
border-radius: 1em;
display: flex;
flex-direction: column;
gap: 2em;
box-shadow: rgba(0, 0, 0, 0.15) 0.3em 0.3em 0.8em 0px inset, rgba(0, 0, 0, 0.15) -0.3em 0em 0.8em 0em inset, rgba(0, 0, 0, 0.25) 0.3em 0.3em 0.8em 0px;
}
@media (max-width: 576px) {
.calc {
padding: 2.5em;
}
}
.calc .result {
height: 12em;
background: pink;
width: 100%;
background: linear-gradient(-30deg, rgba(34, 33, 38, 0.1), rgba(34, 33, 38, 0), rgba(34, 33, 38, 0.1)) 100% 0%/100% 100%, #DBE7E5;
box-shadow: rgba(0, 0, 0, 0.2) 0.3em 0.3em 0.6em 0px inset, rgba(0, 0, 0, 0.25) -3px -3px 0.6em 0.1em inset, rgba(0, 0, 0, 0.25) 0px 0em 1.2em 0px inset, rgba(0, 0, 0, 0.25) 0px 0.3em 0.2em 0px inset, rgba(255, 255, 255, 0.85) 0px 0.3em 0.2em 0px;
background-repeat: no-repeat;
padding: 2em;
}
@media (max-width: 576px) {
.calc .result {
height: 10em;
}
}
.calc .result .result__inner {
text-shadow: 0.15em 0.15em rgba(0, 0, 0, 0.25);
display: flex;
justify-content: flex-end;
align-items: flex-end;
color: #2A3027;
height: 100%;
font-family: "PT Mono", monospace;
display: flex;
flex-direction: column;
justify-content: space-evenly;
}
.calc .result .result__inner .prev-operand {
font-size: 2em;
}
.calc .result .result__inner .current-operand {
font-size: 4em;
font-size: clamp(1.25rem, 0.5368rem + 3.17vw, 2.5rem );
font-size: clamp(1.375rem, 0.7338rem + 2.85vw, 2.5rem );
font-size: clamp(1.5625rem, 1.027rem + 2.38vw, 2.5rem );
}
.calc .keys {
width: 100%;
flex-grow: 2;
}
.calc .keys__inner {
height: 100%;
gap: 1.5em;
}
.calc .key {
color: rgba(0, 0, 0, 0.7);
border: unset;
box-shadow: rgba(0, 0, 0, 0.15) 0.03em 0.03em 0.1em 0px, rgba(0, 0, 0, 0.15) 0.01em 0.01em 0.1em 0px, rgba(255, 255, 255, 0.55) 0em 0em 0.5em 10px inset;
font-family: "Rubik", sans-serif;
font-size: 4em;
font-size: clamp(1rem, 0.3228rem + 3.01vw, 2.1875rem );
background: #fff;
background: #EBECE9;
background-repeat: no-repeat;
display: flex;
justify-content: center;
align-items: center;
border-radius: 0.1em;
transition: all 0.25s ease;
}
.calc .key__row {
height: 100%;
display: grid;
width: 100%;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: repeat(5, 1fr);
gap: 1.5em;
}
@media (max-width: 576px) {
.calc .key__row {
gap: 0.8em;
}
}
@media (max-width: 576px) {
.calc .key {
box-shadow: rgba(0, 0, 0, 0.15) 0.03em 0.03em 0.1em 0px, rgba(0, 0, 0, 0.15) 0.01em 0.01em 0.1em 0px, rgba(255, 255, 255, 0.25) 0em 0em 0.5em 10px inset;
}
}
.calc .key:hover {
box-shadow: rgba(0, 0, 0, 0.05) 0.03em 0.03em 0.1em 0px, rgba(0, 0, 0, 0.05) 0.01em 0.01em 0.1em 0px, rgba(255, 255, 255, 0.55) 0em 0em 0.5em 10px inset;
}
.calc .key[data-number] {
font-size: clamp(1.5625rem, 1.027rem + 2.38vw, 2.5rem );
}
.calc .key:nth-of-type(1) {
background-color: #C34F61;
box-shadow: unset;
box-shadow: rgba(0, 0, 0, 0.45) 0.03em 0.03em 0.1em 0px, rgba(0, 0, 0, 0.25) 0.01em 0.01em 0.1em 0px, rgba(225, 167, 176, 0.25) 0em 0em 0.5em 10px inset, rgba(0, 0, 0, 0.15) 0.03em 0.03em 0.1em 0px inset;
color: #fff;
}
.calc .key:nth-of-type(1):hover {
box-shadow: rgba(0, 0, 0, 0.15) 0.03em 0.03em 0.1em 0px, rgba(0, 0, 0, 0.05) 0.01em 0.01em 0.1em 0px, rgba(225, 167, 176, 0.25) 0em 0em 0.5em 10px inset;
}
.calc .key:nth-of-type(16) {
grid-row: 4/6;
grid-column: 4/4;
}
style>
head>
<body>
<div class="calc">
<div class="result">
<div class="result__inner">
<div data-prev-operand class="prev-operand">
div>
<div data-current-operand class="current-operand">
div>
div>
div>
<div class="keys">
<div class="keys__inner">
<div class="key__row">
<button data-clear class="key">ACbutton>
<button data-operator="**" class="key">x<sup>2sup>button>
<button data-operator="/" class="key">÷button>
<button data-operator="*" class="key">Xbutton>
<button data-number class="key">7button>
<button data-number class="key">8button>
<button data-number class="key">9button>
<button data-operator="-" class="key">-button>
<button data-number class="key">4button>
<button data-number class="key">5button>
<button data-number class="key">6button>
<button data-operator="+" class="key">+button>
<button data-number class="key">1button>
<button data-number class="key">2button>
<button data-number class="key">3button>
<button data-equals class="key">=button>
<button data-number class="key">0button>
<button data-number class="key">.button>
<button data-delete class="key">DELbutton>
div>
div>
div>
div>
body>
<script>
class Calculator{
constructor(prevOperandText, currentOperandText){
this.prevOperandText = prevOperandText;
this.currentOperandText = currentOperandText;
this.clear();
}
clear(){
this.prevOperand = ''
this.currentOperand = ''
this.operation = undefined;
}
delete(){
this.currentOperand = this.currentOperand.toString().slice(0,-1);
}
appendNumber(num){
if(num === '.' && this.currentOperand.includes('.')) return;
this.currentOperand = this.currentOperand.toString() + num.toString();
}
selectOperation(operation){
if(this.currentOperand === '') return
if(this.prevOperand !== ''){
this.calculate();
}
this.operation = operation
this.prevOperand = this.currentOperand;
this.currentOperand = ''
}
calculate(){
let calculation ;
const prev = parseFloat(this.prevOperand)
const current = parseFloat(this.currentOperand)
if(isNaN(prev) || isNaN(current)) return;
switch(this.operation){
case '+':
calculation = prev + current;
break;
case '-':
calculation = prev - current;
break;
case '*':
calculation = prev * current;
break;
case '÷':
calculation = prev / current;
break;
case '/':
calculation = prev / current;
break;
case '**':
calculation = prev ** current;
break;
case '^':
calculation = prev ** current;
break;
default:
return;
}
if(calculation.toString().length > 12 && calculation.toString().includes('.')){
this.currentOperand = calculation.toFixed(5);
} else {
this.currentOperand = calculation;
}
this.operation = undefined;
this.prevOperand = '';
}
updateDisplayNumber(num){
const stringNum = num.toString();
const integerDigits = parseFloat(stringNum.split('.')[0]);
const decimalDigits = stringNum.split('.')[1];
let integerDisplay;
if(isNaN(integerDigits)){
integerDisplay = '';
}else{
integerDisplay = integerDigits.toLocaleString('en', {maximumFractionDigits: 0});
}
if(decimalDigits != null){
return `${integerDisplay}.${decimalDigits}`;
} else{
return integerDisplay;
}
}
updateDisplay(){
this.currentOperandText.innerText = this.updateDisplayNumber(this.currentOperand);
let operation;
if(this.operation === "**"){
operation = "^";
} else {
operation = this.operation;
}
if(this.operation != null){
this.prevOperandText.innerText =
`${this.updateDisplayNumber(this.prevOperand)} ${operation}`;
} else {
this.prevOperandText.innerText = '';
}
}
}
const operatorKeys = document.querySelectorAll('.key[data-operator]');
const numberKeys = document.querySelectorAll('.key[data-number]');
const equalButton = document.querySelector('.key[data-equals]')
const prevOperandText = document.querySelector('[data-prev-operand]')
const currentOperandText = document.querySelector('[data-current-operand]')
const clear = document.querySelector('.key[data-clear')
const deleteKey = document.querySelector('.key[data-delete')
const calculator = new Calculator(prevOperandText,currentOperandText);
clear.addEventListener('click', ()=>{
calculator.clear();
calculator.updateDisplay();
})
deleteKey.addEventListener('click', ()=>{
calculator.delete();
calculator.updateDisplay();
})
numberKeys.forEach(key => {
key.addEventListener('click', ()=>{
calculator.appendNumber(key.innerText)
calculator.updateDisplay()
})
})
operatorKeys.forEach(key => {
key.addEventListener('click', ()=>{
calculator.selectOperation(key.dataset.operator)
calculator.updateDisplay()
})
})
equalButton.addEventListener('click', ()=>{
calculator.calculate();
calculator.updateDisplay();
})
document.addEventListener("keydown", (e) => {
let numKeys = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "."];
let operatorKeys = ["+", "-", "*", "/", "^"];
if(numKeys.includes(e.key)){
calculator.appendNumber(e.key)
calculator.updateDisplay()
}
if(e.key == "Enter"){
calculator.calculate();
calculator.updateDisplay();
}
if(e.key == "Backspace" || e.key == "Delete") {
calculator.delete();
calculator.updateDisplay();
}
if(e.key == "Escape"){
calculator.clear();
calculator.updateDisplay();
}
if(operatorKeys.includes(e.key)){
calculator.selectOperation(e.key)
calculator.updateDisplay()
}
});
script>
html>