分享一个计算器

先看效果:

再看代码(查看更多):

html 复制代码
<!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">AC</button>
                <button data-operator="**" class="key">x<sup>2</sup></button>
                <button data-operator="/" class="key">&#247;</button>
                <button data-operator="*" class="key">X</button>
                <button data-number class="key">7</button>
                <button data-number class="key">8</button>
                <button data-number class="key">9</button>
                <button data-operator="-" class="key">-</button>
                <button data-number class="key">4</button>
                <button data-number class="key">5</button>
                <button data-number class="key">6</button>
                <button data-operator="+" class="key">+</button>
                <button data-number class="key">1</button>
                <button data-number class="key">2</button>
                <button data-number class="key">3</button>
                <button data-equals class="key">=</button>
                <button data-number class="key">0</button>

                <button data-number class="key">.</button>
                <button data-delete class="key">DEL</button>
            </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>
相关推荐
猿榜41 分钟前
魔改编译-永久解决selenium痕迹(二)
javascript·python
阿幸软件杂货间1 小时前
阿幸课堂随机点名
android·开发语言·javascript
我要让全世界知道我很低调1 小时前
记一次 Vite 下的白屏优化
前端·css
threelab1 小时前
three案例 Three.js波纹效果演示
开发语言·javascript·ecmascript
1undefined21 小时前
element中的Table改造成虚拟列表,并封装成hooks
前端·javascript·vue.js
用户7579419949702 小时前
基于JavaScript的简易Git
javascript
gzzeason2 小时前
使用Vite创建React初始化项目
前端·javascript·react.js
又双叒叕7782 小时前
React19 新增Hooks:useOptimistic
前端·javascript·react.js
归于尽2 小时前
V8 引擎是如何给 JS"打扫房间"的 ?
前端·javascript
自由逐风2 小时前
JS 处理长整型数字的坑:从雪花 ID 精度丢失说起
javascript