我正在做一个简单的计算器应用程序,使用vanilla JS
而我有 div
元素来显示数字。但当 textContent
的宽度,它开始看起来很丑陋。我想让 font-size
使其始终在宽度范围内。
我是这样给我的显示添加数字的 div
for(let i=0; i<numbers.length; i++){
numbers[i].addEventListener("click", function(){
display.textContent += this.textContent;
})
}
当
textContent
是少它看起来不错
但当
textContent
超出了宽度就不好看了
原代码在这里。
//Selectors
let numbers = document.querySelectorAll(".numbers")
let operators = document.querySelectorAll(".operators")
let equalto = document.querySelector(".equalto")
let clear = document.querySelector(".clear")
let backspace = document.querySelector(".backspace")
let plusMinus = document.querySelector(".plus-minus")
let dot = document.querySelector(".dot")
let display = document.querySelector(".display")
let output = document.querySelector(".output")
let equaltoPressed = false;
//Event Listeners
for(let i=0; i<numbers.length; i++){
numbers[i].addEventListener("click", function(){
if (equaltoPressed){
display.textContent = "";
equaltoPressed = false;
}
//if condition so that if the display has "Infinity" on it, we don't append digits
if ("0123456789.+-×÷".includes(display.textContent[display.textContent.length-1]) || display.textContent == "")
display.textContent += this.textContent;
evaluate();
})
}
for(let i=0; i<operators.length; i++){
operators[i].addEventListener("click", function(){
equaltoPressed = false;
if ("+-×÷".includes(display.textContent[display.textContent.length-1]))
display.textContent = display.textContent.substring(0,display.textContent.length-1) + this.textContent;
else
display.textContent += this.textContent;
})
}
equalto.addEventListener("click", function(){
if (output.textContent !== ""){
display.textContent = output.textContent;
output.textContent = "";
equaltoPressed = true;
}
});
clear.addEventListener("click", function(){
equaltoPressed = false;
display.textContent = "";
output.textContent = "";
})
backspace.addEventListener("click", function(){
equaltoPressed = false;
display.textContent = display.textContent.substr(0,display.textContent.length-1);
evaluate();
})
plusMinus.addEventListener("click", function(){
equaltoPressed = false;
let expression = display.textContent;
let flag = true;
for (let i=expression.length-1; i>=0; i--){
if ("+-×÷".includes(expression[i])){
if (expression[i] !== "-")
expression = expression.substring(0,i+1) + "-" + expression.substring(i+1,expression.length);
flag = false;
break;
}
}
if (flag)
expression = "-"+expression;
display.textContent = expression;
evaluate();
})
dot.addEventListener("click", function(){
if (equaltoPressed)
display.textContent = "";
let start = 0;
for (let i=display.textContent.length-1; i>=0; i--){
if("+-×÷".includes(display.textContent[i])){
start = i+1;
break;
}
}
if (!display.textContent.substring(start,display.textContent.length).includes("."))
display.textContent += ".";
})
//Functions
function evaluate(){
let expression = display.textContent;
for (let i=0; i<expression.length; i++){
if (expression[i] === "×")
expression = expression.substring(0,i) + "*" + expression.substring(i+1,expression.length);
if (expression[i] === "÷")
expression = expression.substring(0,i) + "/" + expression.substring(i+1,expression.length);
}
if("0123456789.".includes(expression[expression.length-1]) && eval(expression) != expression)
output.textContent = eval(expression);
else
output.textContent = "";
}
*{
border:0;
margin:0;
}
body{
min-height: 100vh;
background: black;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-family: arial;
font-size: 1.5rem;
color: #f8f8f8;
}
.row{
display: flex;
}
.light-grey{
display: flex;
align-items: center;
justify-content: center;
background-color: #a6a6a6;
height: 4.2rem;
width: 4.2rem;
border-radius: 50%;
margin: .4rem;
cursor: pointer;
color: black;
}
.dark-grey{
display: flex;
align-items: center;
justify-content: center;
background-color: #333333;
height: 4.2rem;
width: 4.2rem;
border-radius: 50%;
margin: .4rem;
cursor: pointer;
}
.yellow{
display: flex;
align-items: center;
justify-content: center;
background-color: #ff9501;
height: 4.2rem;
width: 4.2rem;
border-radius: 50%;
margin: .4rem;
cursor: pointer;
}
#zero{
width: 9.2rem;
border-radius:0 50px 50px 0;
border-top-right-radius: 50px;
border-bottom-left-radius: 50px;
border-bottom-right-radius: 50px;
border-top-left-radius: 50px;
}
.display{
width: 19.2rem;
height: 3rem;
margin: 0 .4rem 2rem .4rem;
text-align: right;
font-size: 3rem;
}
.output{
width: 19.2rem;
height: 2rem;
margin: 0 .4rem 2rem .4rem;
text-align: right;
font-size: 2rem;
}
i{
font-size: 1.3rem;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.12.0-2/css/all.min.css" integrity="sha256-46r060N2LrChLLb5zowXQ72/iKKNiw/lAmygmHExk/o=" crossorigin="anonymous" />
<div class="display"></div>
<div class="output"></div>
<div class="row">
<div class="light-grey clear">AC</div>
<div class="light-grey plus-minus">+/-</div>
<div class="light-grey operators">÷</div>
<div class="yellow backspace"><i class="fas fa-backspace"></i></div>
</div>
<div class="row">
<div class="dark-grey numbers">7</div>
<div class="dark-grey numbers">8</div>
<div class="dark-grey numbers">9</div>
<div class="yellow operators">×</div>
</div>
<div class="row">
<div class="dark-grey numbers">4</div>
<div class="dark-grey numbers">5</div>
<div class="dark-grey numbers">6</div>
<div class="yellow operators">-</div>
</div>
<div class="row">
<div class="dark-grey numbers">1</div>
<div class="dark-grey numbers">2</div>
<div class="dark-grey numbers">3</div>
<div class="yellow operators">+</div>
</div>
<div class="row">
<div class="dark-grey numbers" id="zero">0</div>
<div class="dark-grey dot">.</div>
<div class="yellow equalto">=</div>
</div>
在这里,更好地查看它在一个 全页. 增加了一个封面元素 .display-font
和 .display-cover
左右 .display
,把它们的样式固定了一下。
然后添加了一个带有 observer
在你的JS的末端,它正在寻找改变在 .display
,然后改变 font-size: n%
的 .display-cover
取决于 .display-font
. 这里我们需要 .display-font
以固定值 font-size
. 虽然我们无法改变 font-size
的 .display
因为我们正在观察它的变化,而且... ... font-size
变化导致圆圈错误。
但用2个盖板块一切正常。请看。
更新了
将以上所有内容添加到 .output
块,第一次尝试就错过了。
更新2
新增 white-space: nowrap;
到 .display-cover
和 .output-cover
以防止文本跳转到下一行。
在代码的部分加入大量的注释和解释,其中在 .display
和 .output
正在观察。
更多关于 突变观察者. 它不是量子力学,也不是高深的编程。昨天第一次使用它,说实话。
更多关于 语句. 用它来检查是否有 .display
和 .output
宽度。
关于你的注释中的四舍五入错误(当你使用一个ling数字,超过17个符号)。
这个错误可以在你的原始代码中重复出现。
这个错误可以在我发现的所有在线计算器中重复出现。如果你设置100000000000000000+68 - 你会得到100000000000000060。这是一些Javascript的四舍五入功能。你可以在这里测试它 https:/www.jqueryscript.netdemoCalculator-App-jQuery-Bootstrap.
//Selectors
let numbers = document.querySelectorAll(".numbers")
let operators = document.querySelectorAll(".operators")
let equalto = document.querySelector(".equalto")
let clear = document.querySelector(".clear")
let backspace = document.querySelector(".backspace")
let plusMinus = document.querySelector(".plus-minus")
let dot = document.querySelector(".dot")
let display = document.querySelector(".display")
let output = document.querySelector(".output")
let equaltoPressed = false;
//Event Listeners
for (let i = 0; i < numbers.length; i++) {
numbers[i].addEventListener("click", function() {
if (equaltoPressed) {
display.textContent = "";
equaltoPressed = false;
}
//if condition so that if the display has "Infinity" on it, we don't append digits
if ("0123456789.+-×÷".includes(display.textContent[display.textContent.length - 1]) || display.textContent == "")
display.textContent += this.textContent;
evaluate();
})
}
for (let i = 0; i < operators.length; i++) {
operators[i].addEventListener("click", function() {
equaltoPressed = false;
if ("+-×÷".includes(display.textContent[display.textContent.length - 1]))
display.textContent = display.textContent.substring(0, display.textContent.length - 1) + this.textContent;
else
display.textContent += this.textContent;
})
}
equalto.addEventListener("click", function() {
if (output.textContent !== "") {
display.textContent = output.textContent;
output.textContent = "";
equaltoPressed = true;
}
});
clear.addEventListener("click", function() {
equaltoPressed = false;
display.textContent = "";
output.textContent = "";
})
backspace.addEventListener("click", function() {
equaltoPressed = false;
display.textContent = display.textContent.substr(0, display.textContent.length - 1);
evaluate();
})
plusMinus.addEventListener("click", function() {
equaltoPressed = false;
let expression = display.textContent;
let flag = true;
for (let i = expression.length - 1; i >= 0; i--) {
if ("+-×÷".includes(expression[i])) {
if (expression[i] !== "-")
expression = expression.substring(0, i + 1) + "-" + expression.substring(i + 1, expression.length);
flag = false;
break;
}
}
if (flag)
expression = "-" + expression;
display.textContent = expression;
evaluate();
})
dot.addEventListener("click", function() {
if (equaltoPressed)
display.textContent = "";
let start = 0;
for (let i = display.textContent.length - 1; i >= 0; i--) {
if ("+-×÷".includes(display.textContent[i])) {
start = i + 1;
break;
}
}
if (!display.textContent.substring(start, display.textContent.length).includes("."))
display.textContent += ".";
})
//Functions
function evaluate() {
let expression = display.textContent;
for (let i = 0; i < expression.length; i++) {
if (expression[i] === "×")
expression = expression.substring(0, i) + "*" + expression.substring(i + 1, expression.length);
if (expression[i] === "÷")
expression = expression.substring(0, i) + "/" + expression.substring(i + 1, expression.length);
}
if ("0123456789.".includes(expression[expression.length - 1]) && eval(expression) != expression)
output.textContent = eval(expression);
else
output.textContent = "";
}
// .display and .output font resizing changing addon
let displayCover = document.querySelector(".display-cover");
let outputCover = document.querySelector(".output-cover");
let displaySize;
let outputSize;
// This part is a config of MutationObserver, options for the observer (which mutations to observe)
let config = {
attributes: true,
childList: true,
characterData: true
};
// Defining new class of the object MutationObserver, which provides the ability to watch for changes being made to the DOM tree. Basically - this class will be executed on every observing changes in '.display'.
let displayObserver = new MutationObserver(function(mutations) {
displaySize = 100; // we will use it like a base 100% font-size later
// set font size to '.display-cover'
displayCover.style.cssText = 'font-size:' + displaySize + '%';
// 'while' statement creates a loop that executes a specified statement as long as the test condition evaluates to true. The condition is evaluated before executing the statement. Each time we set font size -1 - the width of '.display' changes, and we keeping this loop until the width of '.display' will be not more then it's parent '.display-cover'
while(display.offsetWidth > displayCover.offsetWidth) {
displaySize = displaySize - 1; //decrements font size by 1% each loop
displayCover.style.cssText = 'font-size:' + displaySize + '%';
// basically in DOM you see only result of the very last loop of this 'while' statment
}
});
// Start observing the target node (your '.display') for configured mutations (using config)
displayObserver.observe(display, config);
//----------
// everything the same as above, but for '.output'
let outputObserver = new MutationObserver(function(mutations) {
outputSize = 100;
outputCover.style.cssText = 'font-size:' + outputSize + '%';
while(output.offsetWidth > outputCover.offsetWidth) {
outputSize = outputSize - 1;
outputCover.style.cssText = 'font-size:' + outputSize + '%';
}
});
// as you can see, 'config' is the same
outputObserver.observe(output, config);
* {
border: 0;
margin: 0;
}
body {
min-height: 100vh;
background: black;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-family: arial;
font-size: 1.5rem;
color: #f8f8f8;
}
.row {
display: flex;
}
.light-grey {
display: flex;
align-items: center;
justify-content: center;
background-color: #a6a6a6;
height: 4.2rem;
width: 4.2rem;
border-radius: 50%;
margin: .4rem;
cursor: pointer;
color: black;
}
.dark-grey {
display: flex;
align-items: center;
justify-content: center;
background-color: #333333;
height: 4.2rem;
width: 4.2rem;
border-radius: 50%;
margin: .4rem;
cursor: pointer;
}
.yellow {
display: flex;
align-items: center;
justify-content: center;
background-color: #ff9501;
height: 4.2rem;
width: 4.2rem;
border-radius: 50%;
margin: .4rem;
cursor: pointer;
}
#zero {
width: 9.2rem;
border-radius: 0 50px 50px 0;
border-top-right-radius: 50px;
border-bottom-left-radius: 50px;
border-bottom-right-radius: 50px;
border-top-left-radius: 50px;
}
.display-font {
font-size: 3rem;
}
.display-cover {
width: 19.2rem;
height: 3rem;
margin: 0 .4rem 2rem .4rem;
text-align: right;
font-size: 100%;
white-space: nowrap;
}
.display {
font-size: 100%;
display: inline-block;
}
.output-font {
font-size: 2rem;
}
.output-cover {
width: 19.2rem;
height: 2rem;
margin: 0 .4rem 2rem .4rem;
text-align: right;
font-size: 100%;
white-space: nowrap;
}
.output {
font-size: 100%;
display: inline-block;
}
i {
font-size: 1.3rem;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.12.0-2/css/all.min.css" integrity="sha256-46r060N2LrChLLb5zowXQ72/iKKNiw/lAmygmHExk/o=" crossorigin="anonymous" />
<div class="display-font">
<div class="display-cover">
<div class="display"></div>
</div>
</div>
<div class="output-font">
<div class="output-cover">
<div class="output"></div>
</div>
</div>
<div class="row">
<div class="light-grey clear">AC</div>
<div class="light-grey plus-minus">+/-</div>
<div class="light-grey operators">÷</div>
<div class="yellow backspace"><i class="fas fa-backspace"></i></div>
</div>
<div class="row">
<div class="dark-grey numbers">7</div>
<div class="dark-grey numbers">8</div>
<div class="dark-grey numbers">9</div>
<div class="yellow operators">×</div>
</div>
<div class="row">
<div class="dark-grey numbers">4</div>
<div class="dark-grey numbers">5</div>
<div class="dark-grey numbers">6</div>
<div class="yellow operators">-</div>
</div>
<div class="row">
<div class="dark-grey numbers">1</div>
<div class="dark-grey numbers">2</div>
<div class="dark-grey numbers">3</div>
<div class="yellow operators">+</div>
</div>
<div class="row">
<div class="dark-grey numbers" id="zero">0</div>
<div class="dark-grey dot">.</div>
<div class="yellow equalto">=</div>
</div>