Happy coding.
废话不多说直接上代码。
html代码并没有什么好讲的;其中比较重要的点就是根据每个button
的name
中的值来区别一些特别的操作,比如平方、开根号等等,然后为了更好的用户体验,在每个button
用一个a
标签包裹,设置title
属性,用来提醒该button
是什么操作。
<div class="calculator">
<h1>Zhuo Calculatorh1>
<div class="prev-result" id="prev-result">div>
<div class="result" id="result">0div>
<div class="buttons">
<a title="左括号">
<button class="button" value="(" name="normal">(button>
a>
<a title="右括号">
<button class="button" value=")" name="normal">)button>
a>
<a title="平方">
<button class="button" value="sqr" name="special">²button>
a>
<a title="开根号">
<button class="button" value="sqrt" name="special">√ ̄button>
a>
<button class="button" value=" " name="special"> button>
div>
<div class="buttons">
<a title="非运算">
<button class="button" value="~" name="normal">~button>
a>
<a title="或运算">
<button class="button" value="|" name="normal">|button>
a>
<a title="与运算">
<button class="button" value="&" name="normal">&button>
a>
<a title="左移运算">
<button class="button" value="<<" name="normal"><<button>
a>
<a title="右移运算">
<button class="button" value=">>" name="normal">>>button>
a>
div>
<div class="buttons">
<a title="返回上一步">
<button class="button danger" value="AC" name="special">←button>
a>
<a title="全部清除">
<button class="button" value="CE" name="special">CEbutton>
a>
<a title="乘号">
<button class="button" value="*" name="normal">×button>
a>
<a title="除号">
<button class="button" value="/" name="normal">÷button>
a>
<a title="将输入的十进制转换成十六进制数">
<button class="button" value="16" name="special">Hexbutton>
a>
div>
<div class="buttons">
<button class="button" value="7" name="normal">7button>
<button class="button" value="8" name="normal">8button>
<button class="button" value="9" name="normal">9button>
<a title="取余运算,列如:2%4=2">
<button class="button" value="%" name="normal">Modbutton>
a>
<a title="将输入的十进制转换成十进制数">
<button class="button" value="10" name="special">Decbutton>
a>
div>
<div class="buttons">
<button class="button" value="4" name="normal">4button>
<button class="button" value="5" name="normal">5button>
<button class="button" value="6" name="normal">6button>
<a title="加号">
<button class="button" value="+" name="normal">+button>
a>
<a title="将输入的十进制转换成八进制数">
<button class="button" value="8" name="special">Octbutton>
a>
div>
<div class="buttons">
<button class="button" value="1" name="normal">1button>
<button class="button" value="2" name="normal">2button>
<button class="button" value="3" name="normal">3button>
<a title="减号">
<button class="button" value="-" name="normal">-button>
a>
<a title="将输入的十进制转换成二进制数">
<button class="button" value="2" name="special">Binbutton>
a>
div>
<div class="buttons">
<button class="button zero" value="0" name="normal">0button>
<button class="button" value="." name="normal">.button>
<button class="button" value="=" name="special">=button>
<a title="获取上一步的结果">
<button class="button" value="And" name="special">Ansbutton>
a>
div>
div>
CSS给界面增加亮点,添加一些动画,会带来更好的体验。
@charset "UTF-8";
/**
*
* @authors Zhuo ([email protected])
* @date 2018-07-27 15:33:18
* @version 1.0.1
*/
@import url(https://fonts.googleapis.com/css?family=Oleo+Script);
::selection {
background: #fff;
color: #f19953;
}
::-moz-selection {
background: #fff;
color: #f19953;
}
::-webkit-selection {
background: #fff;
color: #f19953;
}
::-webkit-scrollbar {
width: 5px;
height: 5px;
}
::-webkit-scrollbar-track-piece {
background-color: rgba(0, 0, 0, 0.2);
-webkit-border-radius: 6px;
}
::-webkit-scrollbar-thumb:vertical {
height: 5px;
background-color: rgba(125, 125, 125, 0.7);
-webkit-border-radius: 6px;
}
::-webkit-scrollbar-thumb:horizontal {
width: 5px;
background-color: rgba(125, 125, 125, 0.7);
-webkit-border-radius: 6px;
}
@keyframes get-result{
0%{
}
100%{
-webkit-transform-origin: top right;
-moz-transform-origin: top right;
-ms-transform-origin: top right;
-o-transform-origin: top right;
transform-origin: top right;
-webkit-transform: scale(0.5) translate(0, -60px);
-ms-transform: scale(0.5) translate(0, -60px);
-o-transform: scale(0.5) translate(0, -60px);
transform: scale(0.5) translate(0, -60px);
}
}
@keyframes get-prev-result{
0%{
}
100%{
-webkit-transform-origin: top right;
-moz-transform-origin: top right;
-ms-transform-origin: top right;
-o-transform-origin: top right;
transform-origin: top right;
-webkit-transform: scale(1.4) translate(0, 23px);
-ms-transform: scale(1.4) translate(0, 23px);
-o-transform: scale(1.4) translate(0, 23px);
transform: scale(1.4) translate(0, 23px);
}
}
@keyframes bomb{
0%{
-webkit-transform: scale(1);
-ms-transform: scale(1);
-o-transform: scale(1);
transform: scale(1);
}
25%{
-webkit-transform: scaleX(1.2);
-ms-transform: scaleX(1.2);
-o-transform: scaleX(1.2);
transform: scaleX(1.2);
}
50%{
-webkit-transform: scale(0.8, 1.2);
-ms-transform: scale(0.8, 1.2);
-o-transform: scale(0.8, 1.2);
transform: scale(0.8, 1.2);
}
75%{
-webkit-transform: scaleX(1.2);
-ms-transform: scaleX(1.2);
-o-transform: scaleX(1.2);
transform: scaleX(1.2);
}
}
html, body {
background-color: #56351E;
}
h1 {
font-size: 1.25em;
font-family: 'Oleo Script', cursive;
margin: 0 0 10px 0;
color: #F19953;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
user-select: none;
}
button {
height: 50px;
border: none;
outline: none;
}
.calculator {
text-align: center;
width: 307px;
height: 535px;
min-height: 535px;
border-radius: 10px;
margin: auto;
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
background-color: #010101;
padding: 5px;
}
.buttons {
width: 100%;
text-align: center;
margin: 5px auto 0;
font-size: 0;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
user-select: none;
}
.button{
width: 18%;
color: #f19953;
font-size: 16px;
margin: 0 3px;
background: #fff;
cursor: pointer;
border-radius: 40% / 35%;
-webkit-transition: all .2s ease-in-out 0s;
-o-transition: all .2s ease-in-out 0s;
transition: all .2s ease-in-out 0s;
}
.button:hover {
color: #fff;
background: #f19953;
animation: bomb .3s 1;
}
.button:focus {
color: #fff;
background: #f19953;
animation: bomb .3s 1;
}
.zero{
width: 38%;
text-align: left;
text-indent: 1em;
border-radius: 20% / 50%;
}
.danger{
color: #fff;
border-color: #d43f3a;
background-color: #d9534f;
}
.prev-result{
width: 98%;
min-height: 26px;
color: #f1f1f1;
font-size: 20px;
text-align: right;
word-break: break-all;
}
.result {
width: 98%;
min-height: 50px;
max-height: 80px;
font-size: 30px;
margin: 10px 0;
color: #fff;
text-align: right;
word-break: break-all;
overflow-y: auto;
-webkit-transition: all .3s ease-out .1s;
-o-transition: all .3s ease-out .1s;
transition: all .3s ease-out .1s;
/*animation: get-result .5s 1;*/
}
@media (min-width: 992px) {
html, body{
background-color: #56351E;
}
}
@media (min-width: 1px) and (max-width: 400px) {
html, body{
background-color: #010101;
}
.calculator{
width: 95%;
}
}
这里一开始利用了闭包+工厂模式,相当于一个普通的闭包(不理解的可以跳过);
/**
* 修复一些计算的bug
*
* @authors Zhuo ([email protected])
* @date 2018-07-27 15:33:39
* @version 1.0.2
*
*/
(function(global, factory) {
factory(global);
})(typeof window !== 'undefined' ? window : this,
function(window, noGlobal) {
var expression = [], // 用来存储输入的表达式
RESULT = []; // 保存每次运算后的结果
var btnNormal = document.getElementsByName('normal'),
btnSpecial = document.getElementsByName('special'),
result = document.getElementById('result'),
prevResult = document.getElementById('prev-result');
var calculator = function() {
calculator.fn.init();
};
calculator.fn = calculator.prototype = {
constructor: calculator, // 指定构造函数
count: 0,
init: function() {
var _this = this;
var val;
// 给每个按钮添加点击事件
for (let i = 0; i < btnNormal.length; i++) {
btnNormal[i].onclick = function() {
val = this.value;
_this.push(val);
_this.showExp();
};
}
// 这里要给每一个特殊的按钮添加相应的功能
for (let i = 0; i < btnSpecial.length; i++) {
btnSpecial[i].onclick = function() {
val = this.value;
switch (val) {
case 'AC':
_this.delete();
_this.showExp();
break;
case 'CE':
_this.deleteAll();
_this.showExp();
break;
case '=':
_this.showResult(_this.getResult());
break;
case 'And':
_this.getPervResultDown(_this.getPervResult());
break;
case '2':
case '8':
case '10':
case '16':
_this.showExp(_this.toString(val));
break;
case 'sqr':
_this.showResult(_this.pow(2));
break;
case 'sqrt':
_this.showResult(_this.pow(0.5));
break;
case ' ':
_this.eggshell();
console.log(_this.count);
}
};
}
},
// 计算一个数的次方
pow: function(n) {
n = n || 1;
var result = this.getResult() || 0;
result = Math.pow(result, n);
// this.deleteAll();
// RESULT.push(result);
return result;
},
// 转换进制
// 注:这里最好不要用toString的函数名,博猪当时脑袋秀逗了,采用了这个函数名
toString: function(base) {
var result = this.getResult() || 0;
return result.toString(base);
},
// 这是一个可以忽视的功能
eggshell: function() {
var text = '';
if (++this.count === 1) {
text = '别点';
} else if (this.count === 2) {
text = '求别点';
} else if (this.count === 3) {
text = '我只是一个凑数的,不要再点了';
} else {
return;
}
this.showPrevResult(text);
},
// 将输入的数push到expression数组中
push: function(exp) {
expression.push(exp);
},
// 将expression数组pop
pop: function() {
if (expression.length < 1) {
return undefined;
}
expression.pop();
},
// 将上一步输入的数/符号删除
delete: function() {
this.pop();
},
// 将expression中的所有东西删除
deleteAll: function() {
expression = [];
this.showExp(0);
},
// 将上一个结果在RESULT数组中取出,并添加一个从上面跳动到下面的动画
getPervResultDown: function(val) {
var _this = this;
_this.deleteAll();
_this.push(val);
prevResult.style.animation = 'get-prev-result .5s 1';
setTimeout(function() {
_this.showExp(val);
_this.showPrevResult();
prevResult.style.animation = '';
}, 500);
},
// 获取上一个结果的值,并在RESULT中删除
getPervResult: function() {
if (RESULT.length < 1) return 0;
return RESULT.pop();
},
// 获取到expression中合法的表达式中的结果
getResult: function() {
var result;
try {
result = eval(expression.join(''));
} catch (e) {
result = '请正确输入!';
result.value = result;
return result;
}
return result;
},
// 展示上一个结果
showPrevResult: function(val) {
prevResult.innerHTML = val || RESULT[RESULT.length - 1] || 0;
},
// 显示结果,并添加一个动画
showResult: function(val) {
var _this = this,
rst = val || _this.getResult();
RESULT.push(rst);
result.style.animation = 'get-result .5s 1';
setTimeout(function() {
_this.deleteAll();
_this.showPrevResult(val);
result.style.animation = '';
}, 500);
},
showExp: function(rst) {
result.innerHTML = rst || expression.join('');
},
};
// 将calculator.init和calculator.fn(calculator.prototype)联结
calculator.fn.init.prototype = calculator.fn;
return calculator();
}
);