利用ES5原型编程的方式实现js计算器
后面代码更新都会放在我的 GitHub 求个star
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Calculator</title>
<link rel="stylesheet" href="./css/calculator.css">
</head>
<body>
<div id="calculator">
<!-- 显示计算过程与结果的盒子 -->
<div class="show_box">
<!-- 结果 -->
<div class="result">
<span></span>
</div>
<!-- 过程 -->
<div class="show">
<span></span>
</div>
</div>
<!-- 输入按钮 -->
<div class="inputtedBtns">
<ul>
<li>7</li>
<li>8</li>
<li>9</li>
<li>/</li>
</ul>
<ul>
<li>4</li>
<li>5</li>
<li>6</li>
<li>*</li>
</ul>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>+</li>
</ul>
<ul>
<li>0</li>
<li id="clean">c</li>
<li>.</li>
<li>-</li>
</ul>
<!-- 等于按钮 -->
<button class="equals_btn">=</button>
</div>
</div>
<script src="./js/calculator.js"></script>
<script>
new Calculator().init();
</script>
</body>
</html>
*{
margin: 0;
padding: 0;
}
ul{
list-style: none;
}
body{
background-color: #34495e;
}
#calculator{
width: 330px;
height: 480px;
margin: 100px auto;
}
#calculator span{
display: inline-block;
font-size: 32px;
}
#calculator .show_box{
background-color: #fff;
height: 150px;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
display: flex;
flex-direction: column;
}
#calculator .show_box .result,#calculator .show_box .show{
text-align: right;
height: 50%;
margin: 15px;
overflow: hidden;
}
#calculator .show_box .result{
color: salmon;
}
#calculator .inputtedBtns{
position: relative;
cursor: pointer;
border-bottom-left-radius: 5px;
border-bottom-right-radius: 5px;
width: 330px;
height: 330px;
color: #657b8f;
font-size: 25px;
text-align: center;
display: flex;
flex-direction: column;
flex-grow: 1;
background: linear-gradient(to bottom,#e6f5ff 1%,#fff 8%);
/* 设置文本不能选中 */
user-select: none;
}
#calculator .inputtedBtns ul{
display: flex;
flex-grow: 1;
font-size: 25px;
}
#calculator .inputtedBtns li{
width: 25%;
line-height: calc(320px/4);
}
#calculator .inputtedBtns ul li:last-of-type{
color: #58b3ff;
}
#calculator .inputtedBtns ul:last-of-type #clean{
color: #ED4C67;
}
#calculator .inputtedBtns ul:last-of-type li:nth-child(3){
line-height: 70px;
color: #58b3ff;
}
#calculator .equals_btn{
width: 150px;
height: 40px;
border-radius: 5px;
border: none;
background-color: #58b3ff;
color: #fff;
font-size: 30px;
outline: none;
position: absolute;
right: 50%;
bottom: -30px;
transform: translateX(50%);
}
;(function (doc) {
function Calculator() {
//显示计算过程与结果的盒子
this.showBox = doc.getElementsByClassName('show_box')[0];
// 输入按钮
this.inputtedBtns = doc.getElementsByClassName('inputtedBtns')[0];
this.equalsBtn = doc.getElementsByClassName('equals_btn')[0];
this.result = this.showBox.querySelector('.result');
this.resultChild = this.result.querySelector('span');
this.show = this.showBox.querySelector('.show');
this.showChild = this.show.querySelector('span');
this.clean = this.inputtedBtns.querySelector('#clean');
this.ul = this.inputtedBtns.querySelector('ul');
this.fontSizeUl = parseInt(window.getComputedStyle(this.ul).fontSize);
this.flag = true;
}
//初始化方法
Calculator.prototype.init = function () {
this.BindEvent();
}
//事件方法
Calculator.prototype.BindEvent = function () {
this.inputtedBtns.addEventListener('click', this.onClickObtain.bind(this), false);
this.equalsBtn.addEventListener('click', this.onClickResult.bind(this));
this.clean.addEventListener('click', this.onClickClean.bind(this))
}
//利用事件委托,获取点击元素(关于事件委托:https://blog.csdn.net/m0_46217225/article/details/115328572?spm=1001.2014.3001.5501)
Calculator.prototype.onClickObtain = function (e) {
let elemLi = e.target;
//调用字体变化动画方法
Calculator.sizeAnimation(elemLi, this.fontSizeUl);
//调用溢出处理方法
if(this.showChild.clientWidth >= this.show.clientWidth && this.flag){
Calculator.valOverflow(this.show);
this.flag = false;
}
if (elemLi.tagName.toLowerCase() === 'li' && elemLi.id != "clean") {
this.displayProcess(elemLi.innerText);
}
}
//字体变化动画方法(这里造成了回调地狱,可以使用promise来改写)
Calculator.sizeAnimation = function (elem, size) {
let raise = setInterval(() => {
elem.style.fontSize = size + 1 + 'px'
size++;
if (size >= 34) {
clearInterval(raise);
let decline = setInterval(() => {
elem.style.fontSize = size - 1 + 'px';
size--;
if (size <= 25) {
elem.style.fontSize = 25 + 'px';
clearInterval(decline);
}
}, 15);
}
}, 15);
}
// 显示计算过程
Calculator.prototype.displayProcess = function (elem) {
this.showChild.innerText += elem;
}
//点击出结果
Calculator.prototype.onClickResult = function () {
if (this.showChild.innerHTML != "") {
this.resultChild.style.fontSize = this.showChild.style.fontSize;
this.resultChild.innerHTML = eval(this.show.innerText);
}
}
//点击清除
Calculator.prototype.onClickClean = function () {
//清除子元素
let showChild = this.showChild;
showChild.innerText = "";
showChild.style.fontSize = '32px'
this.flag = true;
//清除结果
this.resultChild.innerText = "";
}
//数值溢出处理
Calculator.valOverflow = function (elem) {
//设置观察者的选项,需要观察的 变化(观察目标节点的子节点的新增和删除)
let config = { childList: true, subtree: true }
//设置观察者的回调函数
function callback(records) {//记录变化的数组
let rs = records[0].target;
if (rs.clientWidth > rs.parentNode.clientWidth) {
rs.style.fontSize = parseInt(window.getComputedStyle(rs).fontSize) - 5 + 'px';
//清楚突变观察者
if(parseInt(elem.children[0].style.fontSize) <= 12){
observer.disconnect();
}
}
}
//创建突变观察者MutationObserver的实例对象
let observer = new MutationObserver(callback);
//添加需要观察的 元素 和 变化
observer.observe(elem, config);
}
window.Calculator = Calculator;
})(document);
感兴趣还可以关注我的:
cnsd:m0_46217225
掘金:寸头男生
github:Buzz_cut
微信公众号:web_mycode
知乎:寸头男生
欢迎加入QQ群交流编程知识:
我会持续分享编程干货。