手机版

基于AngularJS实现iOS8计算器

时间:2021-09-07 来源:互联网 编辑:宝哥软件园 浏览:

先不谈创建angularjs的基础项目。最好用yeoman作为脚手架工具直接生成。如果没有这样的环境,也可以自己下载angularjs文件导入项目。

示例的详细说明

Main.js是项目的主js文件。所有的js都写在这个文件中。初始化后,这个文件的JS代码如下

棱角分明。模块(' calculatorApp ',[ 'ngAnimate ',' ngCookies ',' ngResource ',' ngRoute ',' ngSanitize ',' ngTouch' ])。控制器(' MainCtrl ',函数($ scope){ $ scope . result=' ';$scope.data={ '1':['AC ','/',' % ','[],' 2':['7 ',' 8 ',' 9 ',''],' 3':['4 ',' 5 ',' 6 ','-'],' 4':['1 ',' 2 ',' 3 ','+'],' 5':['0 ',','='] };});这里的结果用于双向绑定和显示操作结果,数据是计算器键盘上的数字和符号。

与本项目相关的所有css代码如下:

* { margin:0划水:0;} body { padding-top : 20px;填充-bottom : 20px;} h1 { text-align : center;color: # 3385ff}.main { margin:20px autoborder:1px固体# 202020;border-bottom:无;宽度:60%;高度:600 px;}.结果{ display:块;宽度: 100%;高度:30%;背景: # 202020;盒子尺寸:边框盒子;border:nonepadd : 0;margin : 0;resize:无;color: # ffffont-size : 80px;text-align:右侧;线高: 270 px;飞越:隐藏;背景-clip:边框框;}.行{ height : 14%;背景# d7d8da盒子尺寸:边框盒子;border-bottom: 1px实心# 202020;飞越:隐藏;}.col { height : 100%;盒子尺寸:边框盒子;border-right:1px实心# 202020;向左浮动:color: # 202020font-size : 28px;文本对齐:中心;线高: 83px;}.正常{宽度:25%;}.端号{宽度: 25%;border-right:无;背景# f78e11color: # fff}.零{ width : 50%;}.历史{ background: # 3385ffcolor: # ffffont-size : 22px;文本对齐:中心;}然后html的布局如下:

body ng-app=' calculatorApp ' h1用于IOs 8/h1 HR/p class=' history ' { history . join(')}/pdiv class=' main ' textarea ng-model=' result ' class=' result '/textarea div ng-repeat=' item in data ' class=' row ' div class=' col ' ng-repeat=' A in item ' ng-class=' show class($ index,A ')ng-click=' show result(A)' { { A } }/div/div/body在此处这里用一个textarea作为计算结果的显示屏,主要是为了利用双向绑定的特性。同时,计算器的所有按钮和界面元素都是通过循环遍历数据对象生成的。showClass方法是作用域下的方法,用于获取不规则界面显示元素的Class属性。正如后面将要解释的,showResult方法是响应按钮的主要方法,我们对按下按钮的所有响应都是通过这个方法来的,这将在后面详细解释。

showClass方法的代码如下:

//显示计算器样式$ scope。show class=function (index,a){ if(a==0){ return ' zero ';}返回索引==3||a=='='?end-no': '正常';};该方法主要处理每行的最后一列应该显示为橙色,显示0的键应该占据两个单元格。

到目前为止,计算器的接口已经完全实现

效果图如下:

以下需要实现对按键的响应,包括数字键、操作键和交流键。每次按键都有不同的对应关系,并且按键之间有连接

为了使代码易于解释,采用了分段给出showResult方法的代码,然后详细解释的方法。

首先,这里添加了几个变量用于控制和存储。

//计算中使用的数字堆栈$ scope . num=[];$ scope . history=[];//接受输入$scope.opt=[]的运算符堆栈;//计算器计算结果$ scope.result=//指示是否重新启动显示;如果为真,则不再显示;如果为false,它将清除当前输出,并再次显示数字$ scope.flag=true//表示目前是否可以重新输入运算符,如果可以为真,否则为false $ scope.isOpt=trueNum数组实际上是一个栈,用来接收用户输入的数字。具体用法后面会解释。历史数组是用户输入的所有按键。每次按键时,按键上的符号或数字被放在堆栈上,然后通过绑定实时显示在界面上。Opt数组是另一个栈,用来接收用户输入的运算符。具体用法后面会解释。旗帜是一种标志。当为真时,表示按下的数字是当前显示数字的一部分,需要显示在后面。比如当前界面显示12,按下3,就会判断。如果是真的,会显示123,否则会清空界面,直接显示3.isOpt是另一个标志。主要目的是防止用户在输入过程中非法输入操作符。例如,用户已经相继输入了1/2。当他们在这里输入时,下面输入的应该是一个数字,但是用户已经输入了一个运算符。通过判断这个符号,计算器将忽略这个非法运算符,并保持输入1/2。

下面的代码段显示了连接它们的完整代码。

$ scope . init=function(){ $ scope . num=[];$ scope . opt=[];$ scope . history=[];$ scope.flag=true$ scope.isOpt=true} ;$ scope.showResult=函数(a){ $ scope . history . push(a);var reg=/\d/ig,regDot=/\。/ig,regAbs=/\//ig;//如果单击一个数字if(reg.test(a)) {//解冻if ($ scope)。isopt==false) {$ scope。isopt=真;} if ($scope.result!=0 $scope.flag $scope.result!=' error '){ $ scope . result=a;} else { $ scope . result=a;$ scope.flag=true} }init方法用于初始化一些变量和标志,并将其恢复到原始状态。showResult方法是显示界面以响应用户操作的主要方法。上面的代码是这个方法的一个if分支,意思是如果一个操作符的输入被冻结了(目前不允许操作符的输入,输入后会被忽略),那么在输入数字的时候就会解锁冻结状态,这样下次输入操作符的时候就会进入操作符栈。如果当前显示的结果不是空白,并且现在按下的数字是当前显示的数字的一部分,并且没有错误,那么显示的结果是当前按下的数字连接到当前显示的数字的末尾,否则意味着重新显示,并且下次要输入的数字需要在重新显示时显示在这个数字之后。

Js代码(续)

//如果单击AC else if (a==' AC') {$ scope。结果=0;$ scope . init();}如果点击AC,表示初始化,这样显示结果为0,所有状态清零。

Js代码(续)

//如果单击小数点,否则如果(a==' . '){if ($ scope。结果!=''!regdot . test($ scope . result)){ $ scope . result=a;}}如果点击了小数点,如果当前显示不为空,且当前显示结果中没有小数点,则让小数点连接到当前显示的末尾。

Js代码(续)

//如果单击否定运算符else If(regabas . test(a)){ If($ scope . result 0){ $ scope . result='-' $ scope . result;} else { $ scope . result=Math . ABS($ scope . result);}}如果单击否定操作,当前显示结果将被否定

Js代码(续)

//如果您单击了百分号else if (a=='%') {$ scope。结果=$ scope。格式(数字($范围。结果)/100);}如果单击百分号,将当前显示结果除以100,然后显示。这是一个格式函数

代码如下:

//格式化结果输出$ scope。format=function(num){ varregnum=/。{10,}/ig;if(regNum.test(num)){ if(/\。/.test(num)){ return num . to exponential(3);} else { return num . to exponential();} } else { return num}}它的主要功能是ios8内置的计算器不会无限显示很多数字。如果超过10位(含小数点),则用科学的计算方法显示。在这里,为了简单起见,用科学的计算方法计算含有小数点且超过10位的显示结果时,小数点后会保留3位。

Js代码(连接到showResult)

//如果点击操作符,当前显示结果不为空,则返回error If($ scope . check operator(a)$ scope . result!=''$scope.result!=' error ' $ scope . isopt){ $ scope . flag=false;$ scope . num . push($ scope . result);$ scope . operation(a);//点击一次操作符后,需要忽略再次点击操作符的情况。$ scope.isOpt=false}这个分支是最复杂的分支,也就是说如果输入了一个运算符,就需要执行一个操作。要进入该分支,您需要首先将flag设置为false。效果是下次重新输入数字,而不是输入当前显示的结果。

然后让当前显示的数字先进入数字栈作为计算出来的数字,运算方法就是运算方法。因为这次单击了一个运算符,所以下次单击时,您应该忽略该运算符,并将isOpt设置为false。

操作代码如下

//比较当前输入运算符和运算符堆栈顶部运算符的优先级。//如果顶运算符的优先级较小,则当前运算符将被堆叠而不进行计算。//否则,顶部运算符将被堆叠,数字堆栈将连续堆叠两个元素进行计算。//那么当前操作符将被堆叠。$ scope。operation=function(current){//如果运算符堆栈为空,直接将当前运算符if(!$ scope . opt . length){ $ scope . opt . push(当前);返回;} var运算符,右侧,左侧;var LastOpt=$ scope . opt[$ scope . opt . length-1];//如果当前操作符的优先级大于上一个操作符的优先级,只需推送if ($ scope.ispri (current,last top)){ $ scope . opt . push(current);} else { operator=$ scope . opt . pop();right=$ scope . num . pop();left=$ scope . num . pop();$scope.calculate(左,运算符,右);$scope.operation(当前);} };该方法接受当前输入的运算符作为参数,其核心思想是当前接收到一个运算符,如果运算符栈为空,则将当前运算符放入栈中,然后在这种情况下什么也不做。如果当前操作符栈不为空,弹出当前操作符栈的顶元素,比较当前收到的操作符和顶操作符的优先级(乘除的优先级大于加减法,顶操作符在同等优先级下优先级更高,因为是先进入栈的)。采用IsPri方法判断优先级,接收两个参数,第一个是当前接收的运算符,第二个是栈顶运算符。如果按照上述规则,当前操作员的优先级较高,则直接堆叠该操作员。如果当前操作员的优先级低于顶级操作员的优先级,则需要计算并更改计算器的显示。算术图形栈顶的两个元素依次弹出作为一个运算的两个算术图形,然后弹出运算符栈顶的元素作为这个运算的运算符,调用Calculate方法进行运算

方法代码如下

//负责计算结果函数$ scope。calculate=function(左,运算符,右){switch(运算符){case' ': $ scope。结果=$ scope。格式(数字(左)数字(右));$ scope . num . push($ scope . result);打破;大小写'-' : $ scope . result=$ scope . format(Number(左)- Number(右));$ scope . num . push($ scope . result);打破;case '' : $ scope . result=$ scope . format(Number(左)* Number(右));$ scope . num . push($ scope . result);打破;case ' : if(right==0){ $ scope . result=' error ';$ scope . init();} else { $ scope . result=$ scope . format(Number(左)/Number(右));$ scope . num . push($ scope . result);} breakdefault:break} };该方法接受左操作数、中操作数、右操作数三个参数,根据加减乘除法改变结果显示结果,并将计算结果堆栈到操作数堆栈中。这里需要注意的是,如果运算为除法,除数为0,则出现错误,显示错误,所有状态清零,否则,运算正常。

一次操作后,操作符栈和数字栈中的状态会发生变化,但当前键当前值还没有放入栈中,所以重复上述过程进行优先级比较,然后执行操作,直到操作符栈为空或者当前操作符的优先级高于操作符栈的顶部操作符,是一个递归过程。IsPri方法用于判断运营商的优先级

代码如下:

//判断当前运算符的优先级是否高于最后一个,如果是,则返回true //否则返回false $ scope。ispri=function (current,last){ if(current==last){ return false;} else { if(current==' | | current=='){ if(last==' | | last==')} { return false;} else { return true} } else { return false} } };判决规则已经在前面描述过了。

此外,还有一个checkOperator方法,用于确定输入符号是否是加减乘除运算符号

代码如下:

//确定当前符号是否是操作符号$ scope。check operator=function(opt){ if(opt=' ' | | opt='-' | | opt='' | | opt='){ return true;}返回false}如果是,则返回true,否则返回false。

到目前为止,仍然有一个分支的输入等于数字

代码如下(后跟showResult方法)

//如果单击相等的数字,否则如果(a=='='$scope.result!=''$scope.result!=' error '){ $ scope . flag=false;$ scope . num . push($ scope . result);while($scope.opt.length!=0){ var运算符=$ scope . opt . pop();var right=$ scope . num . pop();var left=$ scope . num . pop();$scope.calculate(左,运算符,右);} } };如果输入等于数字,首先将标志设置为false,允许下次输入数字时再次显示界面,并将当前显示的数字作为算术数字堆叠在数字堆叠上。然后,有必要继续推动堆栈,直到运算符堆栈为空。

摘要

以上是实现的主要代码和过程。由于分支代码较多,且所有分支都是一次给出,无法详细描述,所以将showResult方法分开,可能不太合适。可能有一些bug,因为写的很匆忙,没花多少时间测试。请指出。同时,由于水平有限,这种方法可能不是最好的。欢迎大家给出更好的方案一起交流学习~ ~以上就是本文的全部内容,希望能给大家的学习或者工作带来一些帮助。

版权声明:基于AngularJS实现iOS8计算器是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。