随手开发一个鸿蒙版仿苹果计算器

百家 作者:51CTO技术栈 2021-09-28 18:11:13

众所周知鸿蒙 JS 框架是非常轻量级的 MVVM 模式。通过使用和 Vue2 相似的属性劫持技术实现了响应式系统。


学习鸿蒙很长时间了,想写一个 demo 进行练练手,就选择开发这个仿苹果计算器程序。


先看效果图:


话不多说,上代码


hml:
<div class="container">
    <div class="header">
        <text class="{{outputClassName}}">{{output}}</text>
    </div>
    <div class="keyboard">
        <block for="{{keyArr}}">
            <div if="{{$item == '0'}}" class="zeroKeys" onclick="onclickNubmer({{$item}})">
                <text>
                    {{$item}}
                </text>
            </div>
            <div elif="{{$item == 'AC' || $item == '+/-' || $item == '%'}}" class="operatorKeys-top" onclick="onclickOper({{$item}})">
                <text>
                    {{$item}}
                </text>
            </div>
            <div elif="{{$item == '÷' || $item == '×' || $item == '-' || $item == '+' || $item == '='}}" class="operatorKeys-right" onclick="onclickOper({{$item}})">
                <text>
                    {{$item}}
                </text>
            </div>
            <div else class="keys keys-nubmer" onclick="onclickNubmer({{$item}})">
                <text>
                    {{$item}}
                </text>
            </div>
        </block>
    </div>
</div>


css:

.container {
    flex-direction: column;
    background-color#010101;
    height:100%;
    width:100%;
}

.header{
    height:36%;
    width:100%;
    align-items: flex-end;
    padding:2px 20px 2px 10px;
}
.keyboard{
    height:64%;
    width:100%;
    padding:2px 10px;
    flex-wrap: wrap;
}
.outputText,.outputTextSmall{
    width:100%;
    height:100px;
    color:#FFFFFF;
    text-align: end;
}
.outputText{
    font-size:80px;
}
.outputTextSmall{
    font-size:58px;
}
.keys,.zeroKeys,.operatorKeys-top,.operatorKeys-right{
    width:74px;
    height:74px;
    justify-content: center;
    align-items: center;
    border-radius:74px;
    margin:10px 5px;
}
.keys-nubmer,.zeroKeys{
    background-color:#333333;
}
.zeroKeys{
    width:158px;
}
.operatorKeys-top{
    background-color#a4a4a4;
}
.operatorKeys-right{
    background-color#f79f31;
}
.keys:active,.zeroKeys:active{
    background-color#737373;
}
.keys text,.zeroKeys text,.operatorKeys-right text{
    font-size:42px;
    color#FFFFFF;
}
.operatorKeys-top text{
    font-size:36px;
    color#010101;
}
.operatorKeys-top:active{
    background-color#d9d9d9;
}
.operatorKeys-right:active{
    background-color#f5c891;
}

js:

import {math} from "../../common/js/utils.js";
export default {
  data: {
    output:"0",
    outputClassName:"outputText",
    cache:[],//记录输入内容
    keyArr:["AC","+/-","%","÷","7","8","9","×","4","5","6","-","1","2","3","+","0",".","="],
    reOper:"",//记录点击的运算符
    reStr1:"",//记录第一次输入内容
    reStr2:"",//记录点击运算符后的内容
    bool:false//防止第二次输入内容时内容清空
  },
  onInit(){
    this.$watch("output","watchOutPut")
  },
  onclickOper(item){
    if(item == "AC"){
      this.clearComput();
    } else if(item == "+" || item == "-" || item == "×" || item == "÷"){
      this.reOper = item;
      this.reStr1 = this.output;
      if(this.cache.length > 0){
        this.startCompute();
      }
      this.cache.push(this.reStr1);
    } else if(item == "+/-"){
      this.output = "-"+this.output;
    } else if(item == "%"){
      this.output = math.accDiv(this.output,100);
    } else if(item == "="){
      this.reStr2 = this.output;
      this.cache.push(this.reStr2);
      this.startCompute();
    }
  },
  onclickNubmer(item){
    if(this.cache.length > 0 && !this.bool){
      this.output = "0";
      this.bool = true;
    }
    if(this.output == "0" && item != "."){
      this.output = item;
    } else if(item == "."){
      if(this.output.indexOf(".") == -1){
        if(this.output == "0"){
          this.output = "0."
        } else {
          this.output += item;
        }
      }
    } else {
      if(this.output.length < 10){
        this.output += item;
      }
    }
  },
  watchOutPut(nVal){
    if(nVal.length > 7 && nVal.length< 10){
      this.outputClassName = "outputTextSmall";
    } else {
      this.outputClassName = "outputText";
    }
  },
  startCompute(){
    switch (this.reOper) {
      case "+":
        this.output = math.accAdd(this.reStr1,this.reStr2);
        this.reStr1 = this.output;
        break;
      case "-":
        this.output = math.accSub(this.reStr1,this.reStr2);
        this.reStr1 = this.output;
        break;
      case "×":
        this.output = math.accMul(this.reStr1,this.reStr2);
        this.reStr1 = this.output;
        break;
      case "÷":
        this.output = math.accDiv(this.reStr1,this.reStr2);
        this.reStr1 = this.output;
        break;
      default:
        break;
    }
  },
  clearComput(){
    this.output = "0";
    this.reOper = "";
    this.reStr1 = "";
    this.reStr2 = "";
    this.cache = [];
    this.bool = false;
  }
}

utils.js:

class MathCalss {
  //js精准除法函数
  accDiv(arg1, arg2){
    let t1 = 0,
       t2 = 0,
       r1,
       r2;
     try {
       t1 = arg1.toString().split('.')[1].length;
     } catch (e) {}
     try {
       t2 = arg2.toString().split('.')[1].length;
     } catch (e) {}
     r1 = Number(arg1.toString().replace('.'''));
     r2 = Number(arg2.toString().replace('.'''));
     return (r1 / r2) * Math.pow(10, t2 - t1);
  }

  //js精准加法函数
  accAdd(arg1, arg2) {
    var r1, r2, m, c;
    try {
      r1 = arg1.toString().split(".")[1].length;
    }
    catch (e) {
      r1 = 0;
    }
    try {
      r2 = arg2.toString().split(".")[1].length;
    }
    catch (e) {
      r2 = 0;
    }
    c = Math.abs(r1 - r2);
    m = Math.pow(10Math.max(r1, r2));
    if (c > 0) {
      var cm = Math.pow(10, c);
      if (r1 > r2) {
        arg1 = Number(arg1.toString().replace("."""));
        arg2 = Number(arg2.toString().replace(".""")) * cm;
      } else {
        arg1 = Number(arg1.toString().replace(".""")) * cm;
        arg2 = Number(arg2.toString().replace("."""));
      }
    } else {
      arg1 = Number(arg1.toString().replace("."""));
      arg2 = Number(arg2.toString().replace("."""));
    }
    return (arg1 + arg2) / m;
  }
  //js精准减法函数
  accSub(arg1, arg2) {
    let r1, r2, m, n;
    try {
      r1 = arg1.toString().split('.')[1].length;
    } catch (e) {
      r1 = 0;
    }
    try {
      r2 = arg2.toString().split('.')[1].length;
    } catch (e) {
      r2 = 0;
    }
    m = Math.pow(10Math.max(r1, r2));
    //动态控制精度长度
    n = r1 >= r2 ? r1 : r2;
    return (arg1 * m - arg2 * m) / m;
  }
  //js精准乘法函数
  accMul(arg1, arg2) {
    var m = 0, s1 = arg1.toString(), s2 = arg2.toString();
    try {
      m += s1.split(".")[1].length;
    }
    catch (e) {
    }
    try {
      m += s2.split(".")[1].length;
    }
    catch (e) {
    }
    return Number(s1.replace(".""")) * Number(s2.replace(".""")) / Math.pow(10, m);
  }
}

export var math = new MathCalss();


为了解决浮点数计算失准问题,我使用一些解决计算失准的函数可供大家参考。


预约 OpenHarmony 线上见面会

关注公众号:拾黑(shiheibook)了解更多

[广告]赞助链接:

四季很好,只要有你,文娱排行榜:https://www.yaopaiming.com/
让资讯触达的更精准有趣:https://www.0xu.cn/

公众号 关注网络尖刀微信公众号
随时掌握互联网精彩
赞助链接