html+css+js实现炫酷的虚拟键盘效果

1,333 阅读4分钟

我正在参加「码上掘金挑战赛」详情请看:码上掘金挑战赛来了!

前言

最近又实现了一个好玩的虚拟键盘效果,具体效果如下

是不是十分炫酷,代码片段过小,具体效果如下

虚拟键盘.gif 具体的实现效果有

  1. 键盘输入,图片上出现按键按压效果。
  2. 按键上的值出现在屏幕上。
  3. 鼠标点击效果。

学习前要掌握重点知识

touppercase() 方法

方法含义是将字符串小写转换成大写。

classList 属性

  1. 这个属性用在元素添加,移除,切换 css类。
  2. classList 属性是只读的,但你可以使用 add() 和 remove() 方法修改它。

for..of..循环

数据类型:String、Array、Map 和 Set,注意不包含 Object 数据类型(即 {}),注意在默认的情况下,对象是不可迭代的。

for循环

优点:在对数组循环具有较大的优势。 劣势:需要对计算器和退出条件进行跟踪。

案例

const ts = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
for (let i = 0; i < ts.length; i++){ 
console.log(ts[i]);
}

for..in..循环

案例

const ts = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
for (let index in ts){ 
console.log(ts[index]);

需要依靠index作为索引进行循环,但是对其添加方法和对象时;将会变得十分麻烦,因为for..in..循环循环循环访问所有可枚举的属性,所以向数组的原型中添加任何其他属性,这些属性也会出现在循环中。

for..of..循环

for..of..循环弥补了两种的缺陷,同时也可以随时停止或退出 for...of 循环。可以忽略索引

案例

for (const digit of digits){ 
if (digit % 2 === 0)
{ 
continue;
}
console.log(digit); }

forEach()

forEach() 是数组方法,只能用在数组中。也无法停止或退出 forEach 循环。forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数。

注意:  forEach() 对于空数组是不会执行回调函数的。

array.forEach(function(currentValue, index, arr), thisValue)

参数

参数描述
function(currentValue, index, arr)必需。 数组中每个元素需要调用的函数。 函数参数:参数描述
-----------------------------
currentValue必需。当前元素
index可选。当前元素的索引值。
arr可选。当前元素所属的数组对象。
thisValue可选。传递给函数的值一般用 "this" 值。 如果这个参数为空, "undefined" 会传递给 "this" 值

技术细节

返回值:undefined
JavaScript 版本:ECMAScript 3

slice()

这个方法是通过索引位置去获取一个新的数组,但不会去改变数组,只是返回一个子数组。

用法:arrayObj.slice(start,end)

start - 必填;

设定新数组的起始位置;如果是负数,则表示从数组尾部开始算起(-1 指最后一个元素,-2 指倒数第二个元素,以此类推)。

end - 可选;

设定新数组的结束位置;如果不填写该参数,默认到数组结尾;如果是负数,则表示从数组尾部开始算起(-1 指最后一个元素,-2 指倒数第二个元素,以此类推)

项目分析

页面制作

html

<!DOCTYPE html>
<html lang="en">
  <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>虚拟键盘1</title>
  </head>
  <body>
    <div class="tou"></div>
    <div class="keyword">
      <div class="row">
        <div class="row1">
          <button>0</button>
          <button>1</button>
          <button>2</button>
          <button>3</button>
          <button>4</button>
          <button>5</button>
          <button>6</button>
          <button>7</button>
          <button>8</button>
          <button>9</button>
        </div>
        <div class="row2">
          <button>Q</button>
          <button>W</button>
          <button>E</button>
          <button>R</button>
          <button>T</button>
          <button>Y</button>
          <button>U</button>
          <button>I</button>
          <button>O</button>
          <button>P</button>
        </div>
        <div class="row3">
          <button>A</button>
          <button>S</button>
          <button>D</button>
          <button>F</button>
          <button>G</button>
          <button>H</button>
          <button>J</button>
          <button>K</button>
          <button>L</button>
        </div>
        <div class="row4">
          <button>Z</button>
          <button>X</button>
          <button>C</button>
          <button>V</button>
          <button>B</button>
          <button>N</button>
          <button>M</button>
        </div>
        <div class="row5">
          <div class="space" id="space">space</div>
          <div class="backspace" id="backspace">backspace</div>
        </div>
      </div>
    </div>
  </body>
</html>


分析

  1. 根据页面所需图型,利用div进行大致的划分。
  2. space(空格),backspace(删除)这两个按钮与其他按钮功能不同,需要另行设计。

css

body {
      display: flex;
      overflow: hidden;
      height: 100vh;//1
      justify-content: center;
      flex-direction: column;
      align-items: center;
      background: linear-gradient(
        135deg,
        rgba(217, 112, 229, 0.475),
        rgba(163, 146, 71, 0.475)
      );
      animation: toggle 2s ease-in infinite;
    }
    @keyframes toggle {//2
      0% {
        background: linear-gradient(
          135deg,
          rgba(217, 112, 229, 0.475),
          rgba(163, 146, 71, 0.475)
        );
      }
      50% {
        background: linear-gradient(
          45deg,
          rgba(217, 112, 229, 0.475),
          rgba(116, 190, 236, 0.475)
        );
      }
      100% {
        background: linear-gradient(
          655deg,
          rgba(217, 112, 229, 0.475),
          rgba(98, 229, 89, 0.475)
        );
      }
    }
    .tou {
      width: 600px;
      height: 50px;
      margin-bottom: 30px;
      text-align: center;
      line-height: 50px;
      font-size: 25px;
    }
    .keyword .row {
      display: flex;
      overflow: hidden;
      justify-content: center;
      flex-direction: column;
      align-items: center;
      width: 870px;
    }
    .tou,
    .keyword {
      box-shadow: -3px -3px 5px rgb(63, 63, 63), 3px 3px 5px black;
      border-radius: 5px;
    }
    button {
      margin: 10px;
      width: 60px;
      height: 60px;
      display: block;
      user-select: none;//3
      box-shadow: -2px -2px 4px rgb(63, 63, 63), 2px 2px 4px black;
      border-radius: 5px;
      background: linear-gradient(
        135deg,
        rgba(217, 112, 229, 0.475),
        rgba(163, 146, 71, 0.475)
      );
      color: aqua;
      font-size: 25px;
      animation: toggle 5s ease-in;
    }
    .row1,
    .row2,
    .row3,
    .row4,
    .row5 {
      display: flex;
      overflow: hidden;
      justify-content: center;
      flex-direction: row;
      align-items: center;
    }
    button:active {
      box-shadow: inset -2px -2px 4px rgb(63, 63, 63), inset 2px 2px 4px black;
      color: yellow;
    }
    .space,
    .backspace {
      margin: 10px 10px 10px 20px;
      height: 60px;
      display: block;
      user-select: none;
      text-align: center;
      line-height: 60px;
      box-shadow: -2px -2px 4px rgb(63, 63, 63), 2px 2px 4px black;
      border-radius: 5px;
      background: linear-gradient(
        135deg,
        rgba(217, 112, 229, 0.475),
        rgba(163, 146, 71, 0.475)
      );
      color: aqua;
      font-size: 25px;
      animation: toggle 5s ease-in;
    }
    .space {
      width: 280px;
    }
    .backspace {
      width: 130px;
    }
    .space:active,//伪元素 ,空格点击的效果
    .backspace:active {
      box-shadow: inset -2px -2px 4px rgb(63, 63, 63), inset 2px 2px 4px black;
      color: yellow;
    }
    .active {//5
      box-shadow: inset -2px -2px 4px rgb(63, 63, 63), inset 2px 2px 4px black;
      color: yellow;
    }

css分析

  1. height: 100vh; vh就是当前屏幕可见高度的1%, height:100vh == height:100%; 但是有个好处是当元素没有内容时候,设置height:100%该元素不会被撑开, 但是设置height:100vh,该元素会被撑开屏幕高度一致。 vw vw就是当前屏幕宽度的1% 当设置width:100%,被设置元素的宽度是按照父元素的宽度来设置, 但是100vw是相对于屏幕可见宽度来设置的,所以会出现50vw大于50%的情况
  2. 是利用动画效果对页面的背景做出轮播图效果,
  background: linear-gradient(
          135deg,
          rgba(217, 112, 229, 0.475),
          rgba(163, 146, 71, 0.475)
        );

这是对背景颜色做的一种背景效果,语法: background: linear-gradient(方向,颜色,颜色)

  1. user-select: none css控制文字不被复制,防止按钮多次点击,形成复制按钮上的文字
  2. 页面主要由弹性布局构成。

js

let buttons = document.querySelectorAll("button");
      let tou = document.querySelector(".tou");
      let space = document.querySelector("#space");
      let Backspace = document.querySelector("#backspace");
      document.body.addEventListener("keydown", function (index) {
        for (let i = 0; i < buttons.length; i++) {
          if (buttons[i].innerHTML == index.key.toUpperCase()) {
            buttons[i].classList.add("active");
          }
        }
        t.innerHTML += index.key;
        if (index.key == "Backspace") {
          tou.innerHTML = tou.innerHTML.slice(0, -10);
        }
      });
      document.body.addEventListener("keyup", function (index) {
        for (let j = 0; j < buttons.length; j++) {
          if (buttons[j].innerHTML == index.key.toUpperCase()) {
            buttons[j].classList.remove("active");
          }
        }
      });
      for (let i of buttons) {
        i.addEventListener("mousedown", function () {
          i.className = "action";
          tou.innerHTML += i.innerHTML;
        });
      }
      for (let j of buttons) {
        j.addEventListener("mouseup", function () {
          j.className = "";
        });
      }
      space.addEventListener("mousedown", function () {
        space.classList.add("active");
         tou.innerHTML+=" ";
      });
      space.addEventListener("mouseup", function () {
        space.classList.remove("active");
      });

    Backspace.addEventListener('mouseup',function(){
        Backspace.classList.add('active');
        tou.innerHTML=tou.innerHTML.slice(0,-1);
    })

      Backspace.onmouseup = function () {
        Backspace.classList.remove("active");
      };

js分析

  1. index.key.toUpperCase() 你所按按钮上的字符大写,key 事件在按下按键时返回按键的标识符。
  2. document.body.addEventListener()意思为body添加事件,document.body是获取body的意思。
  3. space.classList.remove("active");表示space移除active样式。

完整代码

<!DOCTYPE html>
<html lang="en">
  <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>虚拟键盘1</title>
  </head>
  <style>
    body {
      display: flex;
      overflow: hidden;
      height: 100vh;
      justify-content: center;
      flex-direction: column;
      align-items: center;
      background: linear-gradient(
        135deg,
        rgba(217, 112, 229, 0.475),
        rgba(163, 146, 71, 0.475)
      );
      animation: toggle 2s ease-in infinite;
    }
    @keyframes toggle {
      0% {
        background: linear-gradient(
          135deg,
          rgba(217, 112, 229, 0.475),
          rgba(163, 146, 71, 0.475)
        );
      }
      50% {
        background: linear-gradient(
          45deg,
          rgba(217, 112, 229, 0.475),
          rgba(116, 190, 236, 0.475)
        );
      }
      100% {
        background: linear-gradient(
          655deg,
          rgba(217, 112, 229, 0.475),
          rgba(98, 229, 89, 0.475)
        );
      }
    }
    .tou {
      width: 600px;
      height: 50px;
      margin-bottom: 30px;
      text-align: center;
      line-height: 50px;
      font-size: 25px;
    }
    .keyword .row {
      display: flex;
      overflow: hidden;
      justify-content: center;
      flex-direction: column;
      align-items: center;
      width: 870px;
    }
    .tou,
    .keyword {
      box-shadow: -3px -3px 5px rgb(63, 63, 63), 3px 3px 5px black;
      border-radius: 5px;
    }
    button {
      margin: 10px;
      width: 60px;
      height: 60px;
      display: block;
      user-select: none;
      box-shadow: -2px -2px 4px rgb(63, 63, 63), 2px 2px 4px black;
      border-radius: 5px;
      background: linear-gradient(
        135deg,
        rgba(217, 112, 229, 0.475),
        rgba(163, 146, 71, 0.475)
      );
      color: aqua;
      font-size: 25px;
      animation: toggle 5s ease-in;
    }
    .row1,
    .row2,
    .row3,
    .row4,
    .row5 {
      display: flex;
      overflow: hidden;
      justify-content: center;
      flex-direction: row;
      align-items: center;
    }
    button:active {
      box-shadow: inset -2px -2px 4px rgb(63, 63, 63), inset 2px 2px 4px black;
      color: yellow;
    }
    .space,
    .backspace {
      margin: 10px 10px 10px 20px;
      height: 60px;
      display: block;
      user-select: none;
      text-align: center;
      line-height: 60px;
      box-shadow: -2px -2px 4px rgb(63, 63, 63), 2px 2px 4px black;
      border-radius: 5px;
      background: linear-gradient(
        135deg,
        rgba(217, 112, 229, 0.475),
        rgba(163, 146, 71, 0.475)
      );
      color: aqua;
      font-size: 25px;
      animation: toggle 5s ease-in;
    }
    .space {
      width: 280px;
    }
    .backspace {
      width: 130px;
    }
    .space:active,
    .backspace:active {
      box-shadow: inset -2px -2px 4px rgb(63, 63, 63), inset 2px 2px 4px black;
      color: yellow;
    }
    .active {
      box-shadow: inset -2px -2px 4px rgb(63, 63, 63), inset 2px 2px 4px black;
      color: yellow;
    }
  </style>
  <body>
    <div class="tou"></div>
    <div class="keyword">
      <div class="row">
        <div class="row1">
          <button>0</button>
          <button>1</button>
          <button>2</button>
          <button>3</button>
          <button>4</button>
          <button>5</button>
          <button>6</button>
          <button>7</button>
          <button>8</button>
          <button>9</button>
        </div>
        <div class="row2">
          <button>Q</button>
          <button>W</button>
          <button>E</button>
          <button>R</button>
          <button>T</button>
          <button>Y</button>
          <button>U</button>
          <button>I</button>
          <button>O</button>
          <button>P</button>
        </div>
        <div class="row3">
          <button>A</button>
          <button>S</button>
          <button>D</button>
          <button>F</button>
          <button>G</button>
          <button>H</button>
          <button>J</button>
          <button>K</button>
          <button>L</button>
        </div>
        <div class="row4">
          <button>Z</button>
          <button>X</button>
          <button>C</button>
          <button>V</button>
          <button>B</button>
          <button>N</button>
          <button>M</button>
        </div>
        <div class="row5">
          <div class="space" id="space">space</div>
          <div class="backspace" id="backspace">backspace</div>
        </div>
      </div>
    </div>
    <script>
      let buttons = document.querySelectorAll("button");
      let tou= document.querySelector(".tou");
      let space = document.querySelector("#space");
      let Backspace = document.querySelector("#backspace");
      document.body.addEventListener("keydown", function (index) {
        for (let i = 0; i < buttons.length; i++) {
          if (buttons[i].innerHTML == index.key.toUpperCase()) {
            buttons[i].classList.add("active");
          }
        }
        tou.innerHTML += index.key;
        if (index.key == "Backspace") {
          tou.innerHTML = tou.innerHTML.slice(0, -10);
        }
      });
      document.body.addEventListener("keyup", function (index) {
        for (let j = 0; j < buttons.length; j++) {
          if (buttons[j].innerHTML == index.key.toUpperCase()) {
            buttons[j].classList.remove("active");
          }
        }
      });
      for (let i of buttons) {
        i.addEventListener("mousedown", function () {
          i.className = "action";
          tou.innerHTML += i.innerHTML;
        });
      }
      for (let j of buttons) {
        j.addEventListener("mouseup", function () {
          j.className = "";
        });
      }
      space.addEventListener("mousedown", function () {
        space.classList.add("active");
         tou.innerHTML+=" ";
      });
      space.addEventListener("mouseup", function () {
        space.classList.remove("active");
      });

    Backspace.addEventListener('mouseup',function(){
        Backspace.classList.add('active');
        tou.innerHTML=tou.innerHTML.slice(0,-1)
    })

      Backspace.onmouseup = function () {
        Backspace.classList.remove("active");
      };
    </script>
  </body>
</html>

结语

希望这个小案例对大家会有所帮助