本文主要介紹:css
名稱: 優美快捷的小清新導航html
技術棧: HTML5,CSS3,JavaScriptreact
功能描述:git
看完上面的預覽圖,是否是有一點興奮,想本身敲出一個屬於本身的小清新導航。下面就開始動手敲代碼吧!web
作一個網站以前,要搞清楚這個網站是什麼?寫一寫,畫一畫,能夠使用用例圖,畫一我的,想一想那我的能夠有什麼操做?用戶進入咱們網站有哪些功能?segmentfault
用戶能夠進行的操做:數組
qq.com
「哈希」先直接使用html打好框架:數據結構
<!DOCTYPE html>
<html lang="zh-Hans">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>小清新導航</title>
<link rel="stylesheet" href="./css/normalize.css">
<link rel="stylesheet" href="./css/style.css">
</head>
<body>
<header>
<ul>
<li>
<a href=""><img src="" alt="google"></a>
</li>
<li>
<a href=""><img src="" alt="百度一下"></a>
</li>
</ul>
<form action="">
<ul>
<li>
<img src="" alt="google">
</li>
<li>
<img src="" alt="百度一下">
</li>
</ul>
<input type="text">
<button></button>
</form>
</header>
<main>
<div id="main" class="wrapper">
<div class="row">
<div class="kbd_wrapper">
<kbd>
<span>q</span>
<img src="" alt="">
<button></button>
</kbd>
</div>
</div>
</div>
</main>
<footer>
<h3>小Tips</h3>
<ul>
<li>1. 按鍵盤上相應字母進入你想要到的網站</li>
<li>2. 字母相關的導航地址可將鼠標懸浮其上查看</li>
<li>3. 鼠標移動到鍵盤的按鍵時,可自行編輯導航網址</li>
<li>4. 編輯後,網址會保留下來,不用擔憂刷新以後不見了</li>
<li>5. '.'表明未設置網站或無favicon</li>
</ul>
</footer>
<script src="./js/main.js"></script>
</body>
</html>
複製代碼
給HTML標籤添加class,並添加圖片。注:僅僅是我的習慣!app
<header>
<ul id="searchEnginPic" class="searchEnginPic">
<li class="active">
<a href="https://www.google.com.hk/" target="_blank"><img src="./image/google.png" alt="google"></a>
</li>
<li>
<a href="https://www.baidu.com/" target="_blank"><img src="./image/baidu.gif" alt="百度一下"></a>
</li>
</ul>
<form action="" id="searchBar" class="searchBar">
<ul id="searchEnginLogo" class="searchEnginLogo">
<li class="active">
<img src="./image/google.svg" alt="google">
</li>
<li>
<img src="./image/baidu.svg" alt="baidu">
</li>
</ul>
<input type="text" id="inputBar">
<button id="searchBtn" class="searchBtn"></button>
</form>
</header>
<main>
<div id="main" class="wrapper">
<div class="row">
<div class="kbd_wrapper">
<kbd class="key">
<span>q</span>
<img src="./image/dot.png" alt="">
<button>e</button>
</kbd>
</div>
</div>
</div>
</main>
<footer class="description">
<h3>小Tips</h3>
<ul class="tips-content">
<li>1. 按鍵盤上相應字母進入你想要到的網站</li>
<li>2. 字母相關的導航地址可將鼠標懸浮其上查看</li>
<li>3. 鼠標移動到鍵盤的按鍵時,可自行編輯導航網址</li>
<li>4. 編輯後,網址會保留下來,不用擔憂刷新以後不見了</li>
<li>5. '.'表明未設置網站或無favicon</li>
</ul>
</footer>
複製代碼
*{margin: 0;padding:0;}
ul{list-style: none;}
.clearfix::after{
content: '';
display: block;
clear: both;
}
/* 注意:這裏圖片路徑是相對路徑 */
body{
background: #ccc url(../image/bg.jpg) no-repeat center center;
background-size: cover;
}
/* header */
header{
width: 720px;
height: 44px;
margin: 100px auto 50px;
}
header .searchEnginPic{
float: left;
width: 120px;
height: 44px;
}
header .searchEnginPic li{
display: none;
}
header .searchEnginPic li.active{
display: inline-block;
}
header .searchEnginPic li:nth-child(1) img{
width: 120px;
padding: 2.5px 0;
}
header .searchEnginPic li:nth-child(2) img{
width: 120px;
height: 44px;
}
header .searchBar{
float: right;
width: 580px;
height: 44px;
border-radius: 24px;
position: relative;
background: #fff;
}
header .searchBar:hover{
box-shadow: 0 1px 6px 0 rgba(32,33,36,0.28);
border-color: rgba(223,225,229,0);
}
header .searchBar .searchEnginLogo{
position: absolute;
left: 10px;
width: 24px;
height: 44px;
cursor: pointer;
}
header .searchBar .searchEnginLogo li{
display: none;
}
header .searchBar .searchEnginLogo li.active{
display: inline-block;
}
.searchBar .searchEnginLogo li img{
width: 24px;
height: 24px;
padding: 10px 0;
}
.searchBar input{
position: absolute;
left: 46px;
top: 10%;
width: 505px;
height: 80%;
border: none;
outline: none;
}
.searchBar .searchBtn{
position: absolute;
right: 6px;
top: 7px;
width: 30px;
height: 30px;
background: url(../image/search-btn.png) center center no-repeat;
cursor: pointer;
border: none;
outline: none;
}
複製代碼
/* main */
.wrapper div{
width: 850px;
margin: 0 auto;
text-align: center;
}
.wrapper .kbd_wrapper{
display: inline-block;
vertical-align: top;
width: 65px;
height: 55px;
border-radius: 7px;
margin: 6px;
box-shadow: 0 4px 3px 0 #3C3C3D, 0 0 1px 0 #3C3C3D;
text-align: center;
}
.wrapper kbd{
position: relative;
display: inline-block;
width: 65px;
height: 50px;
background: linear-gradient(to bottom, #fff 0%,#fff 70%,#f3f3f3 100%);
border-radius: 7px;
box-shadow: 0 5px 0 0 #767d81;
color: #767D81;
font-family: Helvetical;
vertical-align: top;
line-height: 50px;
text-transform: uppercase;
font-weight: bold;
transition: all .2s linear;
}
.wrapper .kbd_wrapper:hover {
cursor: pointer;
animation: shake 0.82s cubic-bezier(.36, .07, .19, .97) both;
transform: translate3d(0, 0, 0);
backface-visibility: hidden;
perspective: 1000px;
}
.wrapper kbd > button{
display: none;
position: absolute;
right: 2px;
bottom: 2px;
font-size: 12px;
width: 16px;
height: 16px;
border-radius: 5px;
border: none;
outline: none;
color: #333;
cursor: pointer;
}
.wrapper kbd:hover > button{
display: inline-block;
}
.wrapper kbd > button:hover{
background: #806605;
color: #fff;
}
.key img{
width: 16px;
height: 16px;
position: absolute;
left: 4px;
bottom: 2px;
}
@keyframes shake {
10%, 90% {
transform: translate3d(-1px, 0, 0);
}
20%, 80% {
transform: translate3d(2px, 0, 0);
}
30%, 50%, 70% {
transform: translate3d(-4px, 0, 0);
}
40%, 60% {
transform: translate3d(4px, 0, 0);
}
}
複製代碼
/* footer */
footer{
width: 390px;
margin: 50px auto 0;
}
footer h3{
margin-bottom: 10px;
}
footer .tips-content li{
padding: 3px 0;
}
複製代碼
初始化數據的時候,須要獲取localStorage裏面的data對應的hash
//1.初始化數據
let hashA = init();
let keys = hashA['keys'];
let hash = hashA['hash'];
// 下面是工具函數
function init(){
let keys = {
0 : ['q','w','e','r','t','y','u','i','o','p'],
1 : ['a','s','d','f','g','h','j','k','l'],
2 : ['z','x','c','v','b','n','m'],
length : 3
}
let hash = {
q : 'qq.com',
w : 'wangdoc.com',
e : undefined,
r : 'react-juejin.foreversnsd.cn',
t : 'tgideas.qq.com/doc/',
y : 'youtube.com',
i : 'iciba.com',
o : undefined,
p : undefined,
a : undefined,
s : 'segmentfault.com',
d : 'dribbble.com',
f : undefined,
g : 'github.com',
h : undefined,
j : 'juejin.im',
k : 'ke.qq.com',
l : undefined,
z : 'zhihu.com',
x : 'xiedaimala.com',
c : 'csdn.net',
v : undefined,
b : 'bilibili.com',
n : undefined,
m : 'mail.163.com'
}
let hasInLocalStorage = getFormLocalStorage('data');
if(hasInLocalStorage){
hash = hasInLocalStorage;
}
return {'keys':keys,'hash':hash}
}
function getFormLocalStorage(name){
return JSON.parse(localStorage.getItem(name) || 'null')
}
複製代碼
記得要把class爲wrapper的div的內容刪掉,用js生成html
//2.生成鍵盤
generateKeyBoard(keys,hash);
function generateKeyBoard(keys, hash) {
for (let index = 0; index < keys['length']; index = index + 1) { //0 1 2
let div = tag('div');
main.appendChild(div);
let row = keys[index];
for (let index2 = 0; index2 < row['length']; index2 = index2 + 1) { //將固定的10換成可控制的
let kbd_wrapper = tag('div');
kbd_wrapper.className = 'kbd_wrapper';
let kbd = tag('kbd');
kbd.className = 'key';
let span = createSpan(row[index2]);
let img = createImage(hash[row[index2]]);
let button = createButton(row[index2]);
// 判斷按鍵是否已經有對應的網址
if (hash[row[index2]] === undefined) {
kbd.setAttribute('title', '未設置網站導航');
} else {
kbd.setAttribute('title', hash[row[index2]]);
}
kbd.onclick = function (e) {
let website = e.currentTarget.getAttribute('title');
if (website === '未設置網站導航') {
alert('請編輯此按鍵的網站再跳轉');
} else {
window.open('http://' + website, "_blank");
}
}
kbd.appendChild(span);
kbd.appendChild(img);
kbd.appendChild(button);
kbd_wrapper.appendChild(kbd);
div.appendChild(kbd_wrapper);
}
}
}
function tag(tagName) {
let element = document.createElement(tagName);
return element;
}
function createSpan(textContent) {
let span = tag('span');
span.textContent = textContent; //第一個數組 第二個數組 第三個數組
span.className = 'text';
return span;
}
function createButton(id) {
let button = tag('button');
button.textContent = 'e';
button.id = id;
button.onclick = function (e) {
//阻止事件冒泡
e.stopPropagation();
let button2 = e['target'];
let img2 = button2.previousSibling;
//獲取當前的id
let key = button2['id'];
//用戶輸入一個網址
let web = prompt('請輸入一個網址:');
//將原來的hash給替換掉
hash[key] = web;
img2.src = 'http://' + web + '/favicon.ico';
console.log(e.target)
img2.onerror = function (e) {
e.target.src = './image/dot.png';
}
localStorage.setItem('data', JSON.stringify(hash));
}
return button;
}
function createImage(domain) { //hash[row[index2]]
let img = tag('img');
if (domain) {
img.src = 'http://' + domain + '/favicon.ico';
} else {
img.src = './image/dot.png';
}
img.onerror = function (e) {
e.target.src = './image/dot.png';
}
return img;
}
複製代碼
//3.監聽用戶動做
listenToUser(hash);
switchSearchEngin();
function listenToUser(hash) {
// ifInputting做爲一個開關
let ifInputting = false;
let inputBar = document.getElementById('inputBar');
let searchBtn = document.querySelector('.searchBtn');
inputBar.addEventListener('focus', function (e) {
ifInputting = true;
e.target.placeholder = '';
})
inputBar.addEventListener('focusout', function (e) {
ifInputting = false;
e.target.placeholder = '點擊左邊圖標切換搜索引擎';
})
searchBtn.onclick = function (e) {
e.preventDefault();
let searchContent = inputBar.value;
// 判斷是什麼搜索引擎
let searchEnginLogo = document.getElementById('searchEnginLogo');
let engin = searchEnginLogo.getAttribute('data-engin');
switch (engin) {
case 'baidu':
window.open("https://www.baidu.com/s?wd=" + searchContent, '_blank');
break;
case 'google':
window.open("https://www.google.com.hk/search?q=" + searchContent, '_blank');
break;
}
}
document.onkeypress = function (e) {
let key = e['key'];
let website = hash[key];
if (!ifInputting) {
if (website === undefined) {
alert('請編輯此按鍵的網站再跳轉')
} else {
window.open('http://' + website, "_blank");
}
}
}
}
// 切換搜索引擎
function switchSearchEngin() {
// 搜索引擎默認是google
let ifSwitch = false;
let searchEnginLogo = document.getElementById('searchEnginLogo');
let googleLogo = document.querySelector('#searchEnginLogo li:nth-child(1)');
let baiduLogo = document.querySelector('#searchEnginLogo li:nth-child(2)');
let googlePic = document.querySelector('#searchEnginPic li:nth-child(1)');
let baiduPic = document.querySelector('#searchEnginPic li:nth-child(2)');
searchEnginLogo.setAttribute('data-engin', 'google');
searchEnginLogo.onclick = function () {
if (!ifSwitch) {
// google --> baidu
googleLogo.classList.remove('active');
baiduLogo.classList.add('active');
googlePic.classList.remove('active');
baiduPic.classList.add('active');
searchEnginLogo.setAttribute('data-engin', 'baidu');
} else {
// baidu --> google
baiduLogo.classList.remove('active');
googleLogo.classList.add('active');
baiduPic.classList.remove('active');
googlePic.classList.add('active');
searchEnginLogo.setAttribute('data-engin', 'google');
}
ifSwitch = !ifSwitch;
}
}
複製代碼
解決辦法:
定義一個變量(boolean類型)做爲一個開關,當input得到焦點,將那個變量變成true,當input失去焦點,將那個變量變成false。同時事件觸發的時候判斷這個變量,來明確用戶是要輸入文字搜索,仍是想按下按鍵跳轉到想去的網頁。更加詳細的代碼,請看上面或者是github上的代碼。
let ifInputting = false;
let inputBar = document.getElementById('inputBar');
let searchBtn = document.querySelector('.searchBtn');
inputBar.addEventListener('focus', function (e) {
ifInputting = true;
e.target.placeholder = '';
})
inputBar.addEventListener('focusout', function (e) {
ifInputting = false;
e.target.placeholder = '點擊左邊圖標切換搜索引擎';
})
document.onkeypress = function (e) {
let key = e['key'];
let website = hash[key];
if (!ifInputting) {
if (website === undefined) {
alert('請編輯此按鍵的網站再跳轉')
} else {
window.open('http://' + website, "_blank");
}
}
}
複製代碼
我以前已經整理的一篇博客深刻理解DOM事件機制涉及到問題2的這些內容,這裏告訴你一個小技巧:ctrl+f,能夠在網頁搜索關鍵詞。
解決辦法:實際上是由於存在事件冒泡,因此致使kbd的click事件被觸發,因此只須要阻止事件冒泡便可