zoukankan      html  css  js  c++  java
  • 原生javascript开发计算器实例

    计算器的主要作用是进行数字运算,开发一个计算器功能的web实例,有助于更好的掌握js基础的数字运算能力。

    本实例详细分析一个js计算器的开发步骤,学习本教程时最好先具备一些基础的js知识。

    计算器包括显示数字区域和按键区域两大部分,先把计算器的这两个区域的html元素编写出来,如下所示:

    <div class="calculator_wrap" id="calculator"><!--计算器外包元素-->
      <div class="show_num"><!--显示数字区域-->
        <div class="num_save" id="numSave"></div><!--计算公式-->
        <div class="num_cur" id="numCur">0</div><!--计算结果-->
        <div class="show_m" id="showM">M</div><!--记忆存储标志-->
      </div>
      <div class="btn_wrap" id="btnWrap"><!--按钮区域-->
        <div class="btn" data-key="MC">MC</div><!--记忆清零-->
        <div class="btn" data-key="MR">MR</div><!--记忆读取-->
        <div class="btn" data-key="MS">MS</div><!--存储记忆-->
        <div class="btn" data-key="MA">M+</div><!--记忆加-->
        <div class="btn" data-key="ML">M-</div><!--记忆减-->
        <div class="btn" data-key="BACK"></div><!--退格-->
        <div class="btn" data-key="CE">CE</div><!--清除当前-->
        <div class="btn" data-key="Clear">C</div><!--清除-->
        <div class="btn" data-key="Negate">±</div><!--正负转换-->
        <div class="btn" data-key="Square">√ ̄</div><!--平方根-->
        <div class="btn" data-key="Num" data-value="7">7</div><!--7-->
        <div class="btn" data-key="Num" data-value="8">8</div><!--8-->
        <div class="btn" data-key="Num" data-value="9">9</div><!--9-->
        <div class="btn" data-key="Base" data-value="/">/</div><!---->
        <div class="btn" data-key="Percentage">%</div><!--百分号-->
        <div class="btn" data-key="Num" data-value="4">4</div><!--4-->
        <div class="btn" data-key="Num" data-value="5">5</div><!--5-->
        <div class="btn" data-key="Num" data-value="6">6</div><!--6-->
        <div class="btn" data-key="Base" data-value="*">*</div><!---->
        <div class="btn" data-key="Reciprocal">1/x</div>  <!--倒数-->
        <div class="btn" data-key="Num" data-value="1">1</div><!--1-->
        <div class="btn" data-key="Num" data-value="2">2</div><!--2-->
        <div class="btn" data-key="Num" data-value="3">3</div><!--3-->
        <div class="btn" data-key="Base" data-value="-">-</div><!---->
        <div class="btn equal" data-key="Equal">=</div><!--等于-->
        <div class="btn zero" data-key="Num" data-value="0">0</div><!--0-->
        <div class="btn" data-key="Point">.</div><!--小数点-->
        <div class="btn" data-key="Base" data-value="+">+</div><!---->
      </div>
    </div>

    读者可以自己编写一些样式,设计一个自己喜欢的计算器效果。本实例的计算器效果如下图所示:

    样式代码:

      .calculator_wrap{width:240px;height:360px;padding:10px;margin:30px auto;border:1px solid #8acceb;background:#d1f1ff;}
      .calculator_wrap .show_num{position:relative;padding:0 8px;height:60px;background:#fff;text-align:right;}
      .calculator_wrap .show_m{position: absolute;left:10px;bottom:3px;display:none;}
      .calculator_wrap .num_save{height:26px;line-height:26px;font-size:12px;white-space:nowrap;}
      .calculator_wrap .num_cur{font-size:28px;height:34px;line-height:34px;}
      .calculator_wrap .btn_wrap{font-size:0px;}
      .calculator_wrap .btn{display:inline-block;width:38px;height:38px;line-height:38px;text-align:center;border:1px solid #ccc;background:#666;color:#fff;font-size:14px;margin:10px 10px 0 0;cursor:pointer;}
      .calculator_wrap .btn:hover{background:#333;}
      .calculator_wrap .btn:nth-child(5n){margin-right:0px;}
      .calculator_wrap .equal{position:absolute;height:90px;line-height:90px;}
      .calculator_wrap .zero{width:90px;}

    对于新手来说,计算器功能看起来好像很复杂,那么多按钮、多种计算方式,不知如何开始。其实任何一个功能,只需要理清楚思路,一步一步编写代码,会发现实现起来都不难。

    1 获取各个html元素

    web前端不论要在页面上做什么,都要先获取页面上的各个DOM元素。看起来整个计算器的按钮较多,实际开发中可以使用事件代理来操作按钮,所以只获取所有按钮的容器元素即可。代码如下:

    //获取外包元素
    var eCalculator = document.getElementById('calculator');
    //保存运算数据(公式)容器
    var eNumSave = document.getElementById('numSave');
    //当前数字容器
    var eNumCur = document.getElementById('numCur');
    //按钮外部容器,用于事件代理
    var eBtnWrap = document.getElementById('btnWrap');
    //记忆存储标志元素
    var eShowM = document.getElementById('showM');

    2 声明相关变量

    在运算过程中,需要一些变量来进行辅助计算、存储结果和判断等,如下所示:

    //运算公式
    var sStep = '';
    //当前数字
    var sCurValue = '0';
    //运算结果
    var nResult = null;
    //运算符
    var sMark = '';
    //MR记忆存储数据
    var nMvalue = 0;
    //输入状态。false:输入数字替换原数字;true:输入数字加到原数字后面;
    var bLogStatus = false;

    3 按键上添加点击事件

    因为整个计算器按键较多,每一个按钮都单独绑定一个事件会显得太多,很繁琐,还会影响性能,且容易出错。所以刚才只获取了按键的外部容器 eCalculator。

    再使用事件代理,就只需要在容器上添加点击事件,判断当前点击的按键是哪一个,再执行对应的计算即可。用鼠标点击按键的时候,可能会因为点得太快而选择了按键上的文字,因此还需要在外包容器上添加一个阻止默认行为的操作,代码如下所示:

    //外包容器添加鼠标按下事件,用于防止选中文字
    eCalculator.addEventListener('mousedown',function(event){
      //阻止鼠标按下时的默认行为,防止点击按钮过快时选中文字
      event.preventDefault();
    });
    
    //按键容器添加点击事件,用于代理所有按键的操作
    eBtnWrap.addEventListener('click',function(event){
    
    });

    3.1 获取点击的按键和值

    通过事件函数传入的event参数,可以获取到鼠标点击的元素。再通过元素上的data-key和data-value属性判断鼠标点击的是哪一个按键以及它的值,如下所示:

    eBtnWrap.addEventListener('click',function(event){
      //获取点击的元素
      var eTarget = event.target;
      //判断按下的键
      var key = eTarget.dataset.key;
      //获取按下的值
      var value = eTarget.dataset.value;
    });

    3.2 判断按键及值,数字键和小数点执行输入操作

    如果按键属性data-key是'Num'表示按下的是数字,'Point'表示小数点。

    这些按键都是执行输入,因为数字有多个,所以把数字输入封装到fnInputNum函数中。再封装fnShowResult函数把数据显示到显示数字区域。如下所示:

    eBtnWrap.addEventListener('click',function(event){
      /**/
    
      //判断点击的是否是按键
      if(key){
        //用switch语句判断不同的按键执行对应的操作
        switch(key){
          //数字键执行操作
          case 'Num':
            fnInputNum(value);
            break;
          //小数点操作
          case 'Point':
            //判断是否有已小数点,用于限制只能输入一个小数点
            if(sCurValue.indexOf('.')==-1){
              sCurValue = sCurValue + '.';
              bLogStatus = true;
            }
            break;
        }
        //显示数据到显示数字区域
        fnShowResult();
      }
    });
    //输入数字
    function fnInputNum(num){
      //根据输入状态判断是替换当前数字还是添加到当前数字后面
      if(bLogStatus){
        sCurValue = sCurValue + num;
      }else{
        //限制第一个数字不能是0
        if(num!=0){
          bLogStatus = true;
        }
        sCurValue = num;
      }
    }
    //显示计算结果
    function fnShowResult(){
      //显示计算公式
      eNumSave.innerHTML = sStep;
      //限制数字总长度
      if(sCurValue.length>14){
        sCurValue = sCurValue.slice(0,14);
      }
      //显示当前数字
      eNumCur.innerHTML = sCurValue;
    }

    这时候已经可以点击数字和小数点,输入到计算器显示屏上,如图所示:

      

    3.3 加减乘除运算

    计算器最基本的就是加减乘除运算。为了实现对数字进行加减乘除并计算结果功能,封装fnCountResult、fnBaseCount和fnEqual三个函数。

    fnCountResult用于根据运算符计算结果;

    fnBaseCount修改计算公式或计算结果;

    fnEqual用于按下=号时计算结果,并重置数据。如下所示:

    eBtnWrap.addEventListener('click',function(event){
      /**/
    
      //判断点击的是否是按键
      if(key){
        //用switch语句判断不同的按键执行对应的操作
        switch(key){
          /**/
          //加减乘除基本运算
          case 'Base':
            fnBaseCount(value);
            break;
          //等于
          case 'Equal':
            fnEqual();
            break;
        }
        //显示数据到显示数字区域
        fnShowResult();
      }
    });
    //计算结果
    function fnCountResult(){
      //判断当前运算符并执行运算
      switch(sMark){
        case '+':
          nResult = nResult===null?+sCurValue:nResult + (+sCurValue);
          break;
        case '-':
          nResult = nResult===null?+sCurValue:nResult - sCurValue;
          break;
        case '*':
          nResult = nResult===null?+sCurValue:nResult * sCurValue;
          break;
        case '/':
          nResult = nResult===null?+sCurValue:nResult / sCurValue;
          break;
        default:
          nResult = +sCurValue;
      }
    }
    //加减乘除基础运算
    function fnBaseCount(key){
      //如果是输入状态,进行运算
      if(bLogStatus){ 
        //修改输入状态
        bLogStatus = false;
        //计算公式
        sStep = sStep + ' ' + sCurValue + ' ' + key;
        //计算结果
        fnCountResult();
        sCurValue = ''+nResult;
      }else{
        //如果公式为空,先加上原始数字
        if(sStep==''){  
          sStep = sCurValue + ' ' + key;
        }else{  //如果已有公式,更改最后的运算符
          sStep = sStep.slice(0,sStep.length-1) + ' ' + key;
        }
      }
      //更改运算符,用于计算
      sMark = key;
    }
    //等于
    function fnEqual(){
      //如果没有运算符,阻止后续操作
      if(sMark=='')return;
      //计算结果
      fnCountResult();
      sCurValue = ''+nResult;
      //重置数据
      sStep = '';
      sMark = '';
      bLogStatus = false;
    }

    现在已经可以在计算器上做加减乘除的计算了,如图所示:

    3.4 再给其他按键添加操作,代码如下所示:

    eBtnWrap.addEventListener('click',function(event){
      /**/
    
      //判断点击的是否是按键
      if(key){
        //用switch语句判断不同的按键执行对应的操作
        switch(key){
          /**/
    
          //清除
          case 'Clear':
            fnClear()
            break;
          //退格
          case 'BACK':
            fnBack();
            break;
          //CE
          case 'CE':
            //清空当前显示数值
            sCurValue = '0';
            bLogStatus = false;
            break;
          //取反
          case 'Negate':
            //当前数值取反
            sCurValue = ''+(-sCurValue);
            break;
          //取平方根
          case 'Square':
            //当前数值取平方根
            nResult = Math.sqrt(+sCurValue);
            //其他数据初始化
            sCurValue = ''+nResult;
            sStep = '';
            sMark = '';
            bLogStatus = false;
            break;
          //倒数
          case 'Reciprocal':
            //当前数值取倒数
            //其他数据初始化
            nResult = 1/sCurValue;
            sCurValue = ''+nResult;
            sStep = '';
            sMark = '';
            bLogStatus = false;
          break;
          //M系列
          case 'MC':
            //记忆数值清零
            nMvalue = 0;
            fnShowM()
            break;
          case 'MR':
            //显示记忆数值
            sCurValue = '' + nMvalue;
            fnShowM()
            break;
          case 'MS':
            //记忆数值改为当前数值
            nMvalue = +sCurValue;
            fnShowM()
            break;
          case 'MA':
            //当前数值加到记忆数值中
            nMvalue += +sCurValue;
            fnShowM()
            break;
          case 'ML':
            //从记忆数值中减去当前数值
            nMvalue -= +sCurValue;
            fnShowM()
            break;
        }
        //显示数据到显示数字区域
        fnShowResult();
      }
    });
    //清除
    function fnClear(){
      //初始化所有数据
      sStep = '';
      sCurValue = '0';
      nResult = null;
      sMark = '';
      bLogStatus = false;
    }
    //退格
    function fnBack(){
      //必须是输入状态才可以退格
      if(bLogStatus){
        //减去数值最后一位数
        sCurValue = sCurValue.slice(0,sCurValue.length-1);
        //如果最后数值为空或负号(-),改为0,重置输入状态为false,不可再退格
        if(sCurValue==''||sCurValue=='-'){
          sCurValue = '0';
          bLogStatus = false;
        }
      }
    }
    //判断是否有M记忆存储
    function fnShowM(){
      bLogStatus = false;
      //判断是否显示记忆存储标志
      eShowM.style.display = nMvalue==0?'none':'block';
    }

    4 绑定键盘事件
    写到这里,计算器已经可以正常使用了。不过只能用鼠标点击按键操作效率不高,为了可以更快的使用计算器,还需要加上键盘事件,当按下对应按键时,执行操作,如下所示:

    //键盘事件
    document.addEventListener('keyup',function(event){
      //获取当前键盘按键
      var key = event.key;
      //获取按键code
      var code = event.keyCode;
      //限制正确的按键才修改显示的数据
      var comply = false;
      //输入数字
      if((code>=48&&code<=57)||(code>=96&&code<=105)){
        fnInputNum(key);
        comply = true;
      }
      //加减乘除
      if( key=='*'||key=='+'||key=='/'||key=='-'){
        fnBaseCount(key);
        comply = true;
      }
      //esc键
      if(code==27){
        fnClear();
        comply = true;
      }
      //回车键
      if(code==13){
        fnEqual();
        comply = true;
      }
      //退格键
      if(code==8){
        fnBack();
        comply = true;
      }
      if(comply){
        //显示数据到计算器屏幕
        fnShowResult();
      }
    });

    一个简单的计算器就完成了,如果以学习为目的话,建议不要直接复制代码,最好直接手动输入代码及注释,加深印象和提高学习效果。

  • 相关阅读:
    IEEE 网址
    知乎上非常棒的机器学习专栏
    怎样认识比你优秀的人并和他们成为朋友?
    影藏铜皮,显示原点与更改
    PCB检查事项,生成钻孔表
    布局-同样模块复用
    制作DIP Package及DIP焊盘制作,不规则焊盘制作
    制作SMD Package及SMD焊盘制作
    导入网络表
    导入DXF文件
  • 原文地址:https://www.cnblogs.com/jiangweiping/p/14418393.html
Copyright © 2011-2022 走看看