有選擇性的重複造一些輪子,未必是件壞事。 Aaron的部落格上加了一個懸浮菜單,看起來看起來很高大上了。雖然這類小把戲也不是頭一次見了,但從未自己寫過。今天就選擇性的拿這個功能寫一寫。以下是這個輪子的開發過程,也可以當作是一篇需求文件的分析與實作過程。
示範網址:http://sandbox.runjs.cn/show/to8wdmuy
原始碼下載:https://github.com/bjtqti/floatmenu
第一步建立dom節構:
AppCarrier
test1
The past can hurt. But you can either run from it or learn from it
過去是痛苦的,但你要麼逃避,要麼從中成長
One meets his destiny on the road he takes to avoid it
常在逃避命運的路上,卻與之不期而遇
Rules are meant to be broken
規則就該被打破。
Years may wrinkle the skin, but to give up enthusiasm wrinkles the soul.
歲月流逝只令容顏蒼老,且激情不再卻使心靈枯萎。
test2
只有不斷地練習學到的知識,而你才能真正掌握它。
Live every day to the fullest.
享有每日。
Keep your eyes on the stars, and your feet on the ground.
志存高遠,且腳踏實地。
Always be up for an unexpected adventure.
隨時準備開始一場意外冒險吧。
Life is full of disappointment. You can't dwell on things. You have to move on.
生活常不如意,且不沉溺往事,且要勇往直前。
I'm a free spirit. I can't be caged.
我的靈魂是自由的,且不該被束縛。
Sometimes the heart sees what is invisible to the eye.
目不見者,且心可感之
The simple things are also the most extraordinary things, and only the wise can see them.
最平凡的事也是最不凡的事,且只有智者才明白。
test3
how many xxxxxx
how many xxxxxx
how many xxxxxx
how many xxxxxx
how many xxxxxx
how many xxxxxx
how many xxxxxx
how many xxxxxx
how many xxxxxx
how many xxxxxx
how many xxxxxx
how many xxxxxx
how many xxxxxx
how many xxxxxx
how many xxxxxx
how many xxxxxx
test4
how many xxxxxx
how many xxxxxx
how many xxxxxx
how many xxxxxx
how many xxxxxx
how many xxxxxx
how many xxxxxx
how many xxxxxx
how many xxxxxx
how many xxxxxx
how many xxxxxx
how many xxxxxx
how many xxxxxx
how many xxxxxx
how many xxxxxx
how many xxxxxx
第二步準備css檔:
ul {
list-style-type: none;
}
a {
text-decoration: none;
}
/*文章內容區*/
#content {
width:400px;
margin: 0 auto;
font-size: 2em;
}
/*懸浮選單*/
.menu {
position: fixed;
top:20%;
right: 0;
width:200px;
border: 1px solid gray;
border-radius: 5px;
}
.menu li {
height: 2em;
line-height: 2em;
}
.red {
color : red;
}
.hide {
display: none;
}
/*隱藏懸浮選單*/
.slideIn {
transform : translate3d(202px, 0, 0);
transition-duration : .5s;
}
/*顯示懸浮選單*/
.slideOut {
transform : translate3d(0, 0, 0);
transition-duration : .5s;
}
.static {
color:#007aff;
text-align: center;
}
/*顯示懸浮球*/
.toShow {
display: block;
width: 4.8em;
height: 2em;
line-height: 2em;
border-radius: .5em;
border:1px solid gray;
transform : translate3d(-5em, 0, 0);
transition-duration : 1s;
}
第三步開始寫js程式碼:
(function(doc){
//收集各章節的連結位置
var pos = [],
//收集選單上的項目
links = doc.getElementsByTagName('a'),
//收集章節的標題
titles = doc.getElementsByTagName('h1'),
//懸浮選單
menu = doc.getElementById('menubar'),
//目前選擇項目
currentItem=null;
//新增紅色樣式
var addClass = function (element){
currentItem && currentItem.removeAttribute('class');
element.setAttribute('class','red');
currentItem = element;
},
//網頁被捲去的高:
getScrollTop = function (){
return Math.ceil(document.body.scrollTop) 1;
},
//計算滾動位置
startScroll = function (){
var scrollTop = getScrollTop(),
len = titles.length,
i = 0;
//第一條
if(scrollTop>=0 && scrollTop
addClass(links[0]);
return;
}
//最後一條
if(scrollTop>=pos[len-1]){
addClass(links[len-1]);
return;
}
//中間
for(;i
if(scrollTop > pos[i] && scrollTop
addClass(links[i]);
break;
}
}
};
//點選清單中的連結變色
menu.onclick=function(e){
var target = e.target || e.srcElement;
if(target.nodeName.toLowerCase() === 'a'){
//清單項目狀態指示
addClass(target);
return;
}
if(target.nodeName.toLowerCase() === 'p'){
if(target.className == 'static'){
//隱藏式選單
this.className = 'menu slideIn';
setTimeout(function(){
target.className = 'static toShow';
target.innerHTML = '顯示';
},1000);
}else{
//顯示選單
target.className = 'static';
target.innerHTML = '隱藏式 ';
this.className = 'menu slideOut';
}
}
}
//計算各章節的初始位置
var ln = titles.length;
while(--ln>-1){
//titles[len].offsetParent.offsetTop = 0;
pos.unshift(titles[ln].offsetTop);
}
startScroll();
//監聽滾動
window.onscroll = function(){
startScroll()
}
})(document);
分析:
1. 實現自動跳到指定節
這一步驟可以利用標籤的錨功能來做,由於html5以後不支援name 屬性(HTML5 不支援。規定錨的名稱。),所以考慮用ID來跳轉。
2. 標識懸浮選單中的項目屬於左邊內容中的哪一個章節。
這一步驟是困難點,並先簡單分析一下:
2.1 第一種狀況,且人為點選選單項目。這個很容易,只要標識點擊的元素就可以了。
2.2 第二種情況,且透過滑鼠中鍵捲動或拖曳捲軸,此時要連結左邊內容及右邊選單項,這是最難的地方。考慮分步實施,先易後難,各各擊破的策略。
2.2.1 先收集標題元素的座標高度。也就是所有的h1標籤的垂直高度。存入數組1.
2.2.2 收集到功能中的a元素,並存入陣列2.
2.2.3 監聽滾動事件,且判斷目前內容物屬於哪一個選單項目。
且做一步的時候,並在稿紙上畫圖下:
A1
****************
* A2
*
****************
* A3
*
****************
*
* A4
*
每滾動一次,就判斷當前滾動的距離是在哪一個區間,如果是0到A1則是第1章,A1到A2則是第2章,以此類推。
關於🎜>
相同的,且滾動條的高度,我也是簡單的用了document.body.scrollTop來獲取,如果換成jquery的話,應當是$(win).scroll;
繪圖的功能是將抽象的問題具體化,並幫助我們思考,找出規律。也許稱為「建模」會顯得高大上一些吧。
所強調的為在陣列1與陣列2中的關係應為一一對應的。如對應的是。
2.3 第三種狀況,且直接進入頁面時的選單狀態指示。例如透過index.html#h3這樣的地址進來,選單中的h3要反白顯示。
3. 實現懸浮選單的顯示與隱藏動畫。
3.1 這一步驟應是較簡單的,且可考慮先做。利用css3的tramsform屬性就可以了,簡單高效,跨瀏覽器的話,注意兼容。
注意transform : translate3d(x軸, y軸, z軸); 用3d是可以利用硬體加速,增加動畫效果,但是功耗會增加,善用!第一個參數是控制左右方向,如果為正,表示向右移動,如果為負則向左移動。這麼說其實是不嚴謹的,實際上要根據參考點來確定,例如元素的靜止時的x座標是0,那麼增加x的值向右,減少為向左,0為重設。
分析完後,就是寫程式了。這沒有什麼好說的。盡情享受敲擊鍵盤產生的樂感。
寫完之後,預覽一下,點選選單,跳入指定章節,同時點選項目變紅色,刷新目前頁面,依賴顯示正確。滑動一下滾輪,選單項目隨著內容的變化而相應的變化,拖曳一下滾動條,也是這樣,最後點擊一下隱藏,選單縮回去,點擊顯示,選單滑出來。這樣懸浮功能就做完了。
以上就是本文的全部內容了,希望大家能夠喜歡。