我正在参加「码上掘金挑战赛」详情请看:码上掘金挑战赛来了!”
前言
最近又实现了一个好玩的虚拟键盘效果,具体效果如下
是不是十分炫酷,代码片段过小,具体效果如下
具体的实现效果有
- 键盘输入,图片上出现按键按压效果。
- 按键上的值出现在屏幕上。
- 鼠标点击效果。
学习前要掌握重点知识
touppercase() 方法
方法含义是将字符串小写转换成大写。
classList 属性
- 这个属性用在元素添加,移除,切换 css类。
- 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>
分析
- 根据页面所需图型,利用div进行大致的划分。
- 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分析
- height: 100vh; vh就是当前屏幕可见高度的1%, height:100vh == height:100%; 但是有个好处是当元素没有内容时候,设置height:100%该元素不会被撑开, 但是设置height:100vh,该元素会被撑开屏幕高度一致。 vw vw就是当前屏幕宽度的1% 当设置width:100%,被设置元素的宽度是按照父元素的宽度来设置, 但是100vw是相对于屏幕可见宽度来设置的,所以会出现50vw大于50%的情况
- 是利用动画效果对页面的背景做出轮播图效果,
background: linear-gradient(
135deg,
rgba(217, 112, 229, 0.475),
rgba(163, 146, 71, 0.475)
);
这是对背景颜色做的一种背景效果,语法: background: linear-gradient(方向,颜色,颜色)
- user-select: none css控制文字不被复制,防止按钮多次点击,形成复制按钮上的文字
- 页面主要由弹性布局构成。
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分析
- index.key.toUpperCase() 你所按按钮上的字符大写,key 事件在按下按键时返回按键的标识符。
- document.body.addEventListener()意思为body添加事件,document.body是获取body的意思。
- 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>
结语
希望这个小案例对大家会有所帮助