📜  使用带有 Neumorphism EffectSoft UI 的 JavaScript 设计计算器(1)

📅  最后修改于: 2023-12-03 15:06:56.199000             🧑  作者: Mango

使用带有 Neumorphism EffectSoft UI 的 JavaScript 设计计算器

Neumorphism EffectSoft UI 是一种流行的设计趋势,以其柔和的表现形式和现实感而受到欢迎。它为用户界面添加了深度和层次感,使其看起来更加逼真。

在这个项目中,我们将利用 JavaScript 和 Neumorphism EffectSoft UI 设计一个计算器。

项目概述

我们将创建一个基本的计算器,它将具有以下功能:

  • CE (清空)
  • C (清除)
  • +/- (正负值)
  • . (小数点)
  • 数字 0-9

我们将使用 HTML、CSS 和 JavaScript 及 EffectSoft UI 来创建计算器。

HTML 结构

我们将使用以下 HTML 结构来创建我们的计算器:

<div class="calculator">
  <div class="display">
    <div class="operand"></div>
    <div class="operator"></div>
    <div class="operand"></div>
  </div>
  <div class="keys">
    <button class="key ce">CE</button>
    <button class="key c">C</button>
    <button class="key operator">/</button>
    <button class="key operator">*</button>
    <button class="key number">7</button>
    <button class="key number">8</button>
    <button class="key number">9</button>
    <button class="key operator">-</button>
    <button class="key number">4</button>
    <button class="key number">5</button>
    <button class="key number">6</button>
    <button class="key operator">+</button>
    <button class="key number">1</button>
    <button class="key number">2</button>
    <button class="key number">3</button>
    <button class="key plus-minus">+/-</button>
    <button class="key number">0</button>
    <button class="key decimal">.</button>
    <button class="key equal">=</button>
  </div>
</div>

此结构包含带有操作数和运算符的显示器以及键盘。

  • .calculator:整个计算器的容器
  • .display:显示器的容器。 在其中,我们将有一个类名为 operand 和另一个类名为 operator 的 div。
  • .keys:键盘的容器。 它将包含 19 个按钮。
CSS 样式

我们将使用 CSS 和 EffectSoft UI 来制作双拐角计算器。 在这里,我们将使用 EffectSoft UI 中的按钮和容器。

<link rel="stylesheet" href="https://unpkg.com/softui/css/softui.min.css" />
<link rel="stylesheet" href="style.css" />

在这里,我们引入 EffectSoft UI CSS 文件以及自定义样式表。 以下是样式规则:

.calculator {
  display: inline-block;
  border-radius: 30px;
  padding: 20px;
  background-color: #eceff4;
  box-shadow: 10px 10px 30px #d9d9d9, -10px -10px 30px #ffffff;
}

.display {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  background-color: #a8a8a8;
  border-radius: 20px;
  height: 150px;
}

.operand {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  padding-right: 10px;
  font-size: 36px;
}

.operator {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 72px;
}

.keys {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-gap: 15px;
  margin-top: 20px;
}

.key {
  font-size: 24px;
  padding: 10px;
  border-radius: 50px;
}

.operator {
  background-color: #eceff4;
}

.number {
  background-color: #f0f6ff;
}

.decimal {
  background-color: #d9d9d9;
}

.equal {
  background-color: #ffcc33;
  justify-self: stretch;
  grid-column: 3 / span 2;
}

.plus-minus {
  background-color: #d9d9d9;
  font-size: 20px;
}

.ce,
.c {
  background-color: #d9d9d9;
}

.c {
  grid-column: 4;
}

我们使用了许多 Flexbox 属性,例如 flex-direction、justify-content 等。 我们还使用了 grid 属性来定义网格布局。

JavaScript 代码

我们将使用 JavaScript 来实现计算器的逻辑。 算法包含以下步骤:

  • 监听键按下。
  • 每个键都有特定的数据编号,该编号指定数字、操作符等。
  • 按下键时,可以将键的数据编号添加到字符串中。
  • 按下操作符时,要将操作数和运算符添加到操作数和运算符的 div 中。
  • 按下等号时,计算结果并将其显示在操作数 div 中。
  • 按下 CE 时,清除最后一个数字或操作符。
  • 按下 C 时,清除所有。

以下是完整的 JavaScript 代码:

const DISPLAY_OPERAND = document.querySelectorAll(".operand");
const DISPLAY_OPERATOR = document.querySelector(".operator");
const KEYS = document.querySelectorAll(".key");

let firstOperand = "";
let lastOperand = "";
let operator = null;
let dot = false;

function appendOperand(number) {
  if (firstOperand.includes(".") && number === ".") return;
  if (firstOperand.length === 1 && firstOperand === "0" && number !== ".") {
    firstOperand = "";
  }
  firstOperand += number;
  DISPLAY_OPERAND[0].textContent = firstOperand;
}

function appendOperator(selectedOperator) {
  if (operator !== null || firstOperand === "") return;
  operator = selectedOperator;
  DISPLAY_OPERATOR.textContent = operator;
  lastOperand = firstOperand;
  firstOperand = "";
}

function calculate() {
  if (operator === null || firstOperand === "") return;
  const a = parseFloat(lastOperand);
  const b = parseFloat(firstOperand);
  let result;
  switch (operator) {
    case "+":
      result = a + b;
      break;
    case "-":
      result = a - b;
      break;
    case "*":
      result = a * b;
      break;
    case "/":
      result = a / b;
      break;
    default:
      return;
  }
  result = parseFloat(result.toFixed(2));
  DISPLAY_OPERAND[0].textContent = result;
  operator = null;
  lastOperand = result;
  firstOperand = "";
}

function clear() {
  firstOperand = "";
  lastOperand = "";
  operator = null;
  DISPLAY_OPERAND[0].textContent = "0";
  DISPLAY_OPERATOR.textContent = "";
}

function clearLastEntry() {
  if (firstOperand === "") {
    operator = null;
    DISPLAY_OPERATOR.textContent = "";
    return;
  }
  firstOperand = firstOperand.slice(0, -1);
  DISPLAY_OPERAND[0].textContent = firstOperand;
}

function togglePositiveNegative() {
  if (firstOperand === "" || firstOperand === "0") return;
  if (firstOperand.charAt(0) === "-") {
    firstOperand = firstOperand.slice(1);
  } else {
    firstOperand = "-" + firstOperand;
  }
  DISPLAY_OPERAND[0].textContent = firstOperand;
}

KEYS.forEach(function (key) {
  key.addEventListener("click", function () {
    const action = this.dataset.action;
    const value = this.textContent;

    if (!action) {
      appendOperand(value);
    }
    if (action === "decimal") {
      if (dot) return;
      dot = true;
      appendOperand(value);
    }
    if (
      action === "add" ||
      action === "subtract" ||
      action === "multiply" ||
      action === "divide"
    ) {
      appendOperator(value);
      dot = false;
    }
    if (action === "calculate") {
      calculate();
      dot = false;
    }
    if (action === "clear") {
      clear();
      dot = false;
    }
    if (action === "clear-last-entry") {
      clearLastEntry();
      dot = false;
    }
    if (action === "toggle-positive-negative") {
      togglePositiveNegative();
    }
  });
});

document.addEventListener("keydown", function (event) {
  const key = event.key;

  if (/\d/.test(key)) appendOperand(key);
  if (key === ".") {
    if (dot) return;
    dot = true;
    appendOperand(key);
  }
  if (
    key === "+" ||
    key === "-" ||
    key === "*" ||
    key === "/" ||
    key === "="
  ) {
    appendOperator(key);
    dot = false;
  }
  if (key === "Enter" || key === "=") {
    calculate();
    dot = false;
  }
  if (key === "Escape") {
    clear();
    dot = false;
  }
  if (key === "Backspace") {
    clearLastEntry();
    dot = false;
  }
  if (key === "n") {
    togglePositiveNegative();
  }
});

首先,我们定义了一个常量表示数字和操作符的 div。 然后,我们定义变量 firstOperand、lastOperand、operator 和 dot。

appendOperand() 函数用于将数字添加到 firstOperand 中。 如果 firstOperand 包含小数点并且数字是小数点,则返回,否则继续将数字添加到 firstOperand 中。 如果 firstOperand 的长度为 1 且它是“0”,则返回,否则将其设置为空字符串。

appendOperator() 函数用于将操作符添加到 operator 和 operator div。 如果 operator 不为空,则返回。 否则,将 selectedOperator 添加到 operator 中,然后将 firstOperand 赋给 lastOperand,将 firstOperand 设置为空。

calculate() 函数用于计算 firstOperand 和 lastOperand。 如果其任何一个为空,则返回。 然后根据运算符执行相应的操作,并将结果保存在变量 result 中。 最后,将结果舍入到小数点后两位,并将其显示在 operand div 中。

clear() 函数用于清除所有变量和 div 中的内容。

clearLastEntry() 函数用于删除最后一个输入。

togglePositiveNegative() 用于将 firstOperand 切换为正数或负数。

最后,我们使用“点击”事件和键盘事件来侦听用户输入,并执行相应的操作。