仿淘宝UED导航菜单
昨天在淘宝UED网站上看到导航菜单很不错,于是自己动手写了一个。
效果如下:
顺便做了一种变体,实际上只是改变了CSS和一点HTML而已:
代码如下:
var SlideNavi = Class.create({
initialize:function(naviItems,currentClassName,slider){
var self = this;
this.naviItems = naviItems;
this.currentClassName = currentClassName;
this.slider = slider;
this.currentIndex = 0;
var currentTab = function(){
return self.naviItems[self.currentIndex];
}
this.timeInterval = new Object();
var getStep = function(target,current){
var step = (target - current)/5;
if(Math.abs(step)<1 && step != 0){
step = (target-current)>0?1:-1;
}
return Math.round(step);
}
var tabHover = function(item){
//更改slider的位置和长短
clearInterval(self.timeInterval);
var initLeft = parseInt(self.slider.getStyle("left"));
var initRight = initLeft + self.slider.getWidth();
var targetLeft = parseInt(item.positionedOffset().left);
var targetRight = targetLeft + item.getWidth();
if(initLeft == targetLeft)
return;
var leftToRight = true;
if(initLeft > targetLeft)
leftToRight = false;
if(leftToRight){
newTargetLeft = targetLeft + Math.round((targetLeft - initLeft) * 0.1);
newTargetRight = targetRight + Math.round((targetRight - initRight) * 0.05);
}else{
newTargetLeft = targetLeft + Math.round((targetLeft - initLeft) * 0.05);
newTargetRight = targetRight + Math.round((targetRight - initRight) * 0.1);
}
function slide(){
var stepLeft = getStep(newTargetLeft,initLeft);
var stepRight = getStep(newTargetRight,initRight);
if(stepLeft != 0){
initLeft += stepLeft;
}
if(stepRight != 0){
initRight += stepRight;
}
self.slider.setStyle({
left:initLeft + "px",
width:initRight - initLeft + "px"
});
if(stepLeft == 0 && stepRight == 0){
function moveBack(){
var newStepLeft = getStep(targetLeft,newTargetLeft);
var newStepRight = getStep(targetRight,newTargetRight);
if(newStepLeft != 0){
newTargetLeft += newStepLeft;
}
if(newStepRight != 0){
newTargetRight += newStepRight;
}
self.slider.setStyle({
left:newTargetLeft + "px",
width:newTargetRight - newTargetLeft + "px"
});
if(newStepLeft == 0 && newStepRight == 0)
clearInterval(self.timeInterval);
}
clearInterval(self.timeInterval);
self.timeInterval = setInterval(moveBack,10);
}
}
self.timeInterval = setInterval(slide,10);
}
var changeTab = function(item){
if(item != currentTab()){
currentTab().removeClassName(self.currentClassName);
item.addClassName(self.currentClassName);
self.currentIndex = item.index;
}
tabHover(item);
}
var tabBack = function(event){
tabHover(currentTab());
}
changeTab(currentTab());
this.naviItems.each(function(item,index){
item.index = index;
item.observe("mouseover",tabHover.bind(item,item));
item.observe("mouseout",tabBack);
item.firstDescendant().observe("click",changeTab.bind(item,item));
});
}
});
initialize:function(naviItems,currentClassName,slider){
var self = this;
this.naviItems = naviItems;
this.currentClassName = currentClassName;
this.slider = slider;
this.currentIndex = 0;
var currentTab = function(){
return self.naviItems[self.currentIndex];
}
this.timeInterval = new Object();
var getStep = function(target,current){
var step = (target - current)/5;
if(Math.abs(step)<1 && step != 0){
step = (target-current)>0?1:-1;
}
return Math.round(step);
}
var tabHover = function(item){
//更改slider的位置和长短
clearInterval(self.timeInterval);
var initLeft = parseInt(self.slider.getStyle("left"));
var initRight = initLeft + self.slider.getWidth();
var targetLeft = parseInt(item.positionedOffset().left);
var targetRight = targetLeft + item.getWidth();
if(initLeft == targetLeft)
return;
var leftToRight = true;
if(initLeft > targetLeft)
leftToRight = false;
if(leftToRight){
newTargetLeft = targetLeft + Math.round((targetLeft - initLeft) * 0.1);
newTargetRight = targetRight + Math.round((targetRight - initRight) * 0.05);
}else{
newTargetLeft = targetLeft + Math.round((targetLeft - initLeft) * 0.05);
newTargetRight = targetRight + Math.round((targetRight - initRight) * 0.1);
}
function slide(){
var stepLeft = getStep(newTargetLeft,initLeft);
var stepRight = getStep(newTargetRight,initRight);
if(stepLeft != 0){
initLeft += stepLeft;
}
if(stepRight != 0){
initRight += stepRight;
}
self.slider.setStyle({
left:initLeft + "px",
width:initRight - initLeft + "px"
});
if(stepLeft == 0 && stepRight == 0){
function moveBack(){
var newStepLeft = getStep(targetLeft,newTargetLeft);
var newStepRight = getStep(targetRight,newTargetRight);
if(newStepLeft != 0){
newTargetLeft += newStepLeft;
}
if(newStepRight != 0){
newTargetRight += newStepRight;
}
self.slider.setStyle({
left:newTargetLeft + "px",
width:newTargetRight - newTargetLeft + "px"
});
if(newStepLeft == 0 && newStepRight == 0)
clearInterval(self.timeInterval);
}
clearInterval(self.timeInterval);
self.timeInterval = setInterval(moveBack,10);
}
}
self.timeInterval = setInterval(slide,10);
}
var changeTab = function(item){
if(item != currentTab()){
currentTab().removeClassName(self.currentClassName);
item.addClassName(self.currentClassName);
self.currentIndex = item.index;
}
tabHover(item);
}
var tabBack = function(event){
tabHover(currentTab());
}
changeTab(currentTab());
this.naviItems.each(function(item,index){
item.index = index;
item.observe("mouseover",tabHover.bind(item,item));
item.observe("mouseout",tabBack);
item.firstDescendant().observe("click",changeTab.bind(item,item));
});
}
});
基本原理还是很简单,看代码就能明白,但是为了达到缓冲效果还是有一点麻烦,首先要判断slider向左还是向右滑动,根据不同的方向来决定slider的left和width属性,然后还要往回移动,这个就需要再用一次setInterval就可以达到效果。出于学习,我还是使用了prototype1.6。