【虚拟键盘】仿掘金送的键盘用css画一个虚拟的用一下!

629 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第17天,点击查看活动详情

前言

前段时间在掘金薅了一个键盘,研究了好久,决定用css画一个一(毫)模(不)一(相)样(干)的键盘出来看看。

微信图片_20221017161814.jpg

😛 实物图看起来还不错哦,就是画起来有点不太容易了。

拆分元素

😳 由于这个键盘是61键的,所以就比较简单一点

😳 整体分为五层去实现

<div class="keyboard">
  <div class="row">
    <div class="kbd" tabindex="1" data-key="Esc"></div>
    <div class="kbd" data-key="1" data-alt="!"></div>
    <div class="kbd" data-key="2" data-alt="@"></div>
    <div class="kbd" data-key="3" data-alt="#"></div>
    <div class="kbd" data-key="4" data-alt="$"></div>
    <div class="kbd" data-key="5" data-alt="%"></div>
    <div class="kbd" data-key="6" data-alt="^"></div>
    <div class="kbd" data-key="7" data-alt="&amp;"></div>
    <div class="kbd" data-key="8" data-alt="*"></div>
    <div class="kbd" data-key="9" data-alt="("></div>
    <div class="kbd" data-key="0" data-alt=")"></div>
    <div class="kbd" data-key="-" data-alt="_"></div>
    <div class="kbd" data-key="=" data-alt="+"></div>
    <div class="kbd" data-key="backspace"></div>
  </div>
</div>
  • data-key 表示当前按键的主元素
  • data-alt 表示当前按键的附元素(需要通过shift + 获取的)
.keyboard {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  font-size: 0;
  border-radius: 4px;
  border: 13px solid #777;
  border-top-color: #666;
  border-bottom-color: #888;
  outline: 3px solid rgba(0, 0, 0, 0.2);
  outline-offset: -1px;
  box-shadow: inset 0 1rem 1rem rgba(0, 0, 0, 0.5), 0 2rem 3rem -0.5rem rgba(0, 0, 0, 0.55);
  background-image: radial-gradient(#111, #222);
  padding: 0.25rem;
}

.row {
  height: 40px;
  display: flex;
  justify-content: space-between;
  width: 617.2px;
  padding-top: 1px;
  margin-bottom: 2px;
}

.kbd {
  border-radius: 3px;
  box-sizing: border-box;
  color: rgba(0, 0, 0, 0.75);
  display: inline-block;
  font-family: system-ui, sans-serif;
  font-size: 1rem;
  font-weight: 400;
  line-height: 1.125;
  padding: 0.33em;
  position: relative;
  text-align: center;
  vertical-align: middle;
  width: 40px;
  height: 40px;
  border: 3px solid transparent;
  border-top: 2px solid transparent;
  border-bottom: 6px solid transparent;
  background-color: #e9e8e6;
  border-color: #c3c0bb;
  border-top-color: #eeedeb;
  border-bottom-color: #a6a29a;
  box-shadow: 0 -0.125em 0 -0.063em #a6a29a, 0 0.125em 0 -0.063em rgba(0, 0, 0, 0.5);
  transition: -webkit-transform 100ms;
  transition: transform 100ms;
  transition: transform 100ms, -webkit-transform 100ms;
  outline: 0;
}
  • 按键通过border-color的样式做了一些边框阴影的处理效果
  • 由于部分特殊按键颜色不一致,所以可以单独进行处理
.kbd[data-key=tab], .kbd[data-key=enter], .kbd[data-key=caps], .kbd[data-key=backspace], .kbd[data-key=lshift], .kbd[data-key=rshift], .kbd[data-key=lctrl], .kbd[data-key=rctrl], .kbd[data-key=lalt], .kbd[data-key=ralt], .kbd[data-key=lwin], .kbd[data-key=rwin], .kbd[data-key=rfn] {
  background-color: #CD853F;
  border-color: #A0522D;
  border-top-color: #CD853F;
  border-bottom-color: #A0522D;
  box-shadow: 0 -0.125em 0 -0.063em #A0522D, 0 0.125em 0 -0.063em rgba(0, 0, 0, 0.5);
}
.kbd[data-key=tab]:after, .kbd[data-key=enter]:after, .kbd[data-key=caps]:after, .kbd[data-key=backspace]:after, .kbd[data-key=lshift]:after, .kbd[data-key=rshift]:after, .kbd[data-key=lctrl]:after, .kbd[data-key=rctrl]:after, .kbd[data-key=lalt]:after, .kbd[data-key=ralt]:after, .kbd[data-key=lwin]:after, .kbd[data-key=rwin]:after, .kbd[data-key=rfn]:after {
  font-size: 0.725em;
  top: 0;
  left: 0;
  right: 0;
  line-height: 31.2px;
  position: absolute;
}
.kbd[data-key=tab]::before, .kbd[data-key=enter]::before, .kbd[data-key=caps]::before, .kbd[data-key=backspace]::before, .kbd[data-key=lshift]::before, .kbd[data-key=rshift]::before, .kbd[data-key=lctrl]::before, .kbd[data-key=rctrl]::before, .kbd[data-key=lalt]::before, .kbd[data-key=ralt]::before, .kbd[data-key=lwin]::before, .kbd[data-key=rwin]::before, .kbd[data-key=rfn]::before {
  border-left-color: #D2691E;
  border-right-color: #D2691E;
  border-bottom-color: #A0522D;
  box-shadow: 0 4px 4px -3px rgba(0, 0, 0, 0.15);
  background-image: linear-gradient(to right, #A0522D, #A0522D 5%, transparent 40%, transparent 60%, #A0522D 95%, #A0522D);
}
  • 将所有特殊按键的背景颜色和边框颜色都做一下特殊处理

image.png

填充键盘文字

😕 键盘文字是通过标签属性添加的,并没有直接写在标签之间,所以我们需要通过伪类样式直接处理

.kbd[data-key]::after {
  position: relative;
  z-index: 1;
  content: attr(data-key);
  text-transform: capitalize;
}
.kbd[data-alt]::after {
  white-space: pre;
  content: attr(data-alt) "\a" attr(data-key);
  line-height: 0.95rem;
  font-size: 0.7em;
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  text-align: center;
}
  • content使用attr方法来从页面元素中动态的获取内容(获取的是 data- 中定义的内容)

image.png

特殊按键

🧐 中间的字母按键都一样的处理方式,下面就描述一下空格周边的特殊按键处理方法

<div class="row">
    <div class="kbd" data-key="lctrl"></div>
    <div class="kbd" data-key="lwin"></div>
    <div class="kbd" data-key="lalt"></div>
    <div class="kbd" data-key="space"></div>
    <div class="kbd" data-key="ralt"></div>
    <div class="kbd" data-key="rwin"></div>
    <div class="kbd" data-key="rfn"></div>
    <div class="kbd" data-key="rctrl"></div>
</div>
  • 将空格作为中间键,左右的按键分为 l 和 r (left、right)
  • shift 按键同理(可以在文章结尾码上掘金中查看源码)
.kbd[data-key=lshift]::after, .kbd[data-key=rshift]::after {
  content: 'Shift';
}
.kbd[data-key=lctrl]::after, .kbd[data-key=rctrl]::after {
  content: 'Ctrl';
}
.kbd[data-key=lwin]::after, .kbd[data-key=rwin]::after {
  content: 'Win';
}
.kbd[data-key=lalt]::after, .kbd[data-key=ralt]::after {
  content: 'Alt';
}
.kbd[data-key=space]::after {
  content: none;
}
.kbd[data-key=rfn]::after {
  content: 'fn';
}
.kbd[data-key=lalt]::after, .kbd[data-key=ralt]::after {
  content: 'Alt';
}
  • 针对特殊按键使用伪类添加按键值
.kbd[data-key=tab], .kbd[data-key="\\"] {
  width: 60px;
}
.kbd[data-key=caps] {
  width: 70px;
}
.kbd[data-key=backspace] {
  width: 80px;
}
.kbd[data-key=enter] {
  width: 90px;
}
.kbd[data-key=lshift] {
  width: 90px;
}
.kbd[data-key=rshift] {
  width: 110px;
}
.kbd[data-key=lctrl], .kbd[data-key=rctrl], .kbd[data-key=lalt], .kbd[data-key=ralt], .kbd[data-key=lwin], .kbd[data-key=rwin], .kbd[data-key=rfn] {
  width: 50px;
}
.kbd[data-key=space] {
  width: 250px;
}
  • 针对特殊按键设置不同的宽度值

键盘按下

😏 当某个按键按下时,就给当前按键一个按下的 class

window.addEventListener('keydown', function (e) {
    console.log(e);
    var el = codeToElement[e.code] || $key(e.key.toLowerCase());
    if (el) {
        el.classList.add('pressed');
        e.preventDefault();
    }
});
window.addEventListener('keyup', function (e) {
    var el = codeToElement[e.code] || $key(e.key.toLowerCase());
    if (el) {
        el.classList.remove('pressed');
        e.preventDefault();
    }
});
  • 通过window.addEventListener方法监听键盘事件
.kbd:active, .kbd.pressed {
  -webkit-transform: scale(0.96, 0.96) translate(0, 3px);
          transform: scale(0.96, 0.96) translate(0, 3px);
}
  • 键盘按下事件通过 transform 给一个下沉 和 弹起的效果

码上掘金看效果