计算器的主要作用是进行数字运算,开发一个计算器功能的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{//限制第一个数字不能是0if(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;//CEcase \'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;//获取按键codevar 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();}});
一个简单的计算器就完成了,如果以学习为目的话,建议不要直接复制代码,最好直接手动输入代码及注释,加深印象和提高学习效果。