html+css+js 基于逆波兰式 99%还原windows标准计算器

0. 起步

html+css+js 基于逆波兰式 99%还原windows标准计算器_第1张图片
原生计算器
html+css+js 基于逆波兰式 99%还原windows标准计算器_第2张图片
还原计算器

可以看到相差不大,仿站是初级前端的必备技巧,但是也需要熟悉css基本布局

1.html

网页结构由上到下分为 :
【title】
【功能区func】
【show表达式与结果/当前输入显示】
【btn按钮区】
【footer】


    
计算器
标准
@熬一宿

2.css

大体上为流式布局从上到下 宽度都是自适应100% 但是最大不超过540px;
高度是百分比分割 保证不会出现滚动条,毕竟什么计算器是要滚动看的。
剩余各功能区的内部使用flex布局
优点:1.方便垂直居中 align-items:center直接搞定 2.justify-content:space-between;左右分散布局
3.真正方便在于下面6行每行4个的按钮首先flex布局制定每个按钮宽24%在flex-wrap:wrap;快速搞定。
为了方便看less文件

body{
    max-width: 400px;
    height: 100vh;
    margin: 0 auto;
    background-color:#BEBEBE;
}
html{
    background-color: white;
}
@media screen and (max-width:400px){
    body{
        width: 100%;;
    }
}
button{
    border: 0;
}
.title{
    height: 36%/690*100;
    padding: 0% 2%;
    display: flex;
    justify-content: space-between;
    align-items: center;
    .screenFunc{
        display: flex;
        justify-content: space-between;
        width: 30%;
    }
    font-weight: bold;
}
//功能区
.func{
    height: 50%/690*100;
    padding: 0% 2%;
    display: flex;
    justify-content: space-between;
    align-items: center;
    .lFunc{
        display: flex;
        align-items: center;
        height: 100%;
        width: 40%;
        .funcBtn{
            height: 22px;
            width: 27px;
            background: url(./calcSelect.PNG);
            margin-right: 10%;
            
        }
        .funcName{
            font-weight: bold;
            font-size: 1.5em;
        }
    }
    .history{
        background: url(./history.PNG);
        height: 34px;
        width: 34px;
    }
}
//结果区
.show{
    height: 130%/690*100;
    padding: 0% 2%;
    text-align: right;
    .showFormula{
        height: 30%;
    }
    .showResult{
        height: 70%;
        
        font-size: 3em;
        font-weight: bold;
    }
}
//按键区
.btn{
    height: 450%/690*100;
    padding: 1% 1%;
    display: flex;
    justify-content: space-between;
    flex-wrap: wrap;
    align-items: center;
    button{
        background-color: #D8D8D8;
        height: 16.6%;
        border: 0.5px solid #BEBEBE;
        width: 24.8%;
        font-size: 1.5em;
        font-weight: bold;   
        :hover{
            background-color: #6b6b6b;
        } 
    }   
    .num{
        background-color: white;
    }
    .equ{
        background-color: #8CB2D8;
    }
    }
    
.btn-click{
    background-color: #BEBEBE!important;
}    
footer{
    height: 20%/690*100;
    font-size: 12px;
    text-align: center;
}

3.JS

该函数的逻辑是输入数字和表达式在后台formula中保存中缀表达式,然后中缀转后缀表达式【后缀=操作符在操作数后面】,再利用栈先入先出的特性对后缀表达式进行计算

中缀转后缀原则:
1.数字直接输出
2.如果栈顶元素的优先级低于当前入栈元素直接入栈
3.(直接入栈
4.)不入栈但是将站内栈顶到第一个)内部的所有符号出栈包括(只不过(不输入到后缀表达式字符集内
5.如果栈顶元素优先级高于等于当前,那么一直出栈直到栈顶元素优先级小于入栈元素,在将当前元素入栈
6.如果所有中缀表达式都要么入栈要么输出到后缀字符串中,只需将栈内符号依次出栈输出到后缀表达式中
例子:
5+(32+1)
5 3 2 * 1 + +
那怎么使用栈求后缀表达式值 原则是进入一个符号算栈顶元素和栈顶第二个元素并将结果又入栈
比如 5 3 2
到乘法 5 3
2也就是 5 6
到1入栈 5 6 1
到+ 栈就为 5 7
到+ 栈就为 12
那么最终栈内第一个也是唯一个元素就是结果

//显示公式
var formula = "";
//当前正在输入的数字 只有当输入非数字或非正负号或非小数点才push到输入数组
//清空num
var num = "";
//公式显示模块
var f = document.getElementsByClassName('showFormula')[0];
f.innerText = "";
//结果或当前输入显示模块
var r = document.getElementsByClassName('showResult')[0];
r.innerText = "0";
//获取按键或点击事件的符号
var btn = document.getElementsByClassName('btn')[0];
//符号按键
var sym = document.getElementsByClassName('sym');
var oldClass = "";
//所有按键点击事件
btn.addEventListener("mousedown",function (e) {
    var curEle = e.target;
    oldClass = curEle.getAttribute("class");
    curEle.setAttribute("class",oldClass+" btn-click");
});
btn.addEventListener("mouseup",function (e) {
    var curEle = e.target;
    curEle.setAttribute("class",oldClass);
});
btn.addEventListener("touchdown",function (e) {
    var curEle = e.target;
    oldClass = curEle.getAttribute("class");
    curEle.setAttribute("class",oldClass+" btn-click");
});
btn.addEventListener("touchup",function (e) {
    var curEle = e.target;
    curEle.setAttribute("class",oldClass);
});
btn.addEventListener("click",hander);
//点击处理函数
function hander(e){
    

    var cur = e.target.innerText;
    var parseCur = parseInt(cur);

    //解除错误禁用按钮
    if(sym[0].getAttribute("disabled")=="disabled"){
        for(var i=0; i0
        r.innerText = num==""?"0":num;
        return;
    }else if(cur=="back"){//回退公式
        formula = formula.slice(0,formula.length-1);
        f.innerText = formula;
        return;
    }else if(cur=="."){//小数点
        if(num.indexOf(".")==-1){
            if(num==""){
                num="0";
            }
            num+=".";
            r.innerText = num;
        }
        return;
    }else if(cur=="+/-"){//+/-
        if(num!=""){
            if(num[0]=="-"){
                num = num.slice(1);
            }else{
                num = "-" + num;
            }
            r.innerText = num;
        }
       
        return;
    }else if(isNaN(cur)){
        if(num[0]=="-"){
            formula+="(0"+num+")";
        }else{
            formula+=num;
        }
        num="";
        r.innerText="0";
        var lastPos = formula[formula.length-1];
        if(lastPos=="."){
            cur = "0"+cur;
        }else if(isNaN(lastPos) && cur!="(" && cur!=")" && lastPos !=")"){
            alert("请输入数字");
            return;
        }
        formula+=cur;
        f.innerText=formula;
        if(cur=="="){//等号
            computed(formula);
        }
    }else if(!isNaN(cur)){
        num += cur;
        r.innerText = num;
    }
    var rLength = r.innerText.length;
    if(rLength>=4){
        var splitArr = [];
    for(var i=rLength-3; i>=0; i-=3){
        var tmp = r.innerText.substr(i,3);
        splitArr.push(tmp);
        console.log(i);
        if(i<3 && i>0){
            splitArr.push(r.innerText.substr(0,i));
        }
    }
    console.log(splitArr);
    r.innerText=splitArr.reverse().join(',');
    }
    
}
function calc_error(message){
    r.innerText=message;
    var e = new RangeError("");
    f.innerText = formula;
    for(var i=0; i=symPrior[stack[stack.length-1]]){
                    back.push(stack.pop());
                }
                stack.push(cur);
            }
        }
    }
    while(stack.length!=0){
        back.push(stack.pop());
    }
    console.log(back);
    return back;
}

var symPrior = {"(":0,")":0,"%":1,"/":1,"*":1,"+":2,"-":2};//优先级对象数组越小越优先

你可能感兴趣的:(#,web,js,flex,前端)