首页logo
  •  

jonllen

金龙,目前就职于一家软件公司,从事Java和.Net信息安全开发设计。

个人档案

jonllen
心情闪存 | 给他留言
妮称:jonllen
来自:中国. 湖南. 湘潭
简述:金龙,目前就职于一家软件公司,从事Java和.Net信息安全开发设计。
博客日历

摆脱JQuery—之自定义图片缩略图列表滚动功能。

分类:JavaScript

先来看下我做的相册的例子,详情请见我的博客相册。

1-仙台修炼原图
名  称:1-仙台修炼
上传时间:2009-6-6 16:26:06
浏览次数:20
评论次数:1

自己写了一个JS类,叫Photo,里面提供了照片列表分页的实现,之所以写这个东西,一是因为我广佛项目里面答应了别人要实现这个功能,二个是我自己的博客相册也要实现这个功能,现在算是提前做吧,先看贴下整个JS类的代码:

/**************************************************
Description : Photo Miniature Page List Manage V1.0
Author : Jonllen
Create : 2009-07-04 18:35:21
Update : 2009-08-15 23:04:01
WebSite: http://www.hnonl.com
*************************************************
*/
var Photo = {
pageCount :
0,
pageIndex :
1,
pageSize :
5,
itemWidth :
80,
imgMaxWidth :
66,
imgMaxHeight :
49,
createLi :
true,
createName :
false,
prevId :
"btnPrev",
nextId :
"btnNext",
containerId :
"miniaturelist",
scrollContainerId :
"miniaturescroll",
loadingSrc :
"images/loading.gif",
img : {
id :
"",
alt:
"图片未加载",
title :
"",
src :
"",
href :
"javascript:;",
img : undefined,
isLoad :
false
},
speed :
20,
interval :
40,
timer : undefined,
currImg : {},
list :
new Array(),
push :
function (img){
var item = img;
for(p in this.img)
{
if (item[p] == undefined) item[p]=this.img[p];
}
var container = document.getElementById(this.scrollContainerId);

var linkElem = document.createElement("a");
linkElem.href
= item.href;

var imgElem = document.createElement("img");
//imgElem.src = item.src;
imgElem.alt = item.alt;
imgElem.title
= item.title;
item.img
= imgElem;

linkElem.appendChild(imgElem);

linkElem.onclick
= function () { return Photo.eClick(item); };

if ( this.createLi==true )
{
var liElem = document.createElement("li");
liElem.appendChild(linkElem);

if(this.createName==true)
{
var pElem = document.createElement("p");
pElem.innerHTML
= item.name ? item.name : item.title;
liElem.appendChild(pElem);
}

container.appendChild(liElem);
}
else
{
container.appendChild(linkElem);
}
this.list.push(item);

},
init :
function (){

this.pageCount = Math.ceil(this.list.length/this.pageSize*1.0);
this.setPage();

//set scroll Container width
document.getElementById(this.scrollContainerId).style.width = (this.itemWidth*this.list.length+2) + "px";//2px border
document.getElementById(this.scrollContainerId).style.overflow = "visible";
//set wrap Container width to autoWidth
document.getElementById(this.containerId).style.width = (this.pageCount > 1 ? this.itemWidth*this.pageSize : this.itemWidth*this.list.length)+"px";//2px border
document.getElementById(this.containerId).style.overflow = "hidden";

//set the next page Space in default
this.nextSpace = this.pageSize * this.itemWidth;

if(this.prevId != "")
{
var prevElem = document.getElementById(this.prevId);
if (this.enableMouseDown)
{
//bind onmousedown event
prevElem.onmousedown = function (){Photo.eMouseDown( -Photo.interval )};
prevElem.onmouseup
= function (){Photo.eMouseUp(this)};
}
else
{
//bind click
prevElem.onclick = function (){Photo.ePrev(this)};
}
}
if(this.nextId != "")
{
var nextElem = document.getElementById(this.nextId);

if (this.enableMouseDown)
{
nextElem.onmousedown
= function (){ Photo.eMouseDown(Photo.interval) };
nextElem.onmouseup
= function (){ Photo.eMouseUp(this) };
}
else
{
nextElem.onclick
= function (){Photo.eNext(this)};
}
}
},
setPage :
function ()
{
var pageIndex = arguments.length > 0 ? arguments[0] : this.pageIndex;
if (pageIndex <= 0) pageIndex=1;
if (pageIndex > this.pageCount) pageIndex = this.pageCount;

var list;
if ( pageIndex==1 )
{
list
= this.list.slice(0,( this.list.length > this.pageSize ? this.pageSize : this.list.length ) );
this.eIsFirstPage(document.getElementById(this.prevId));
}
else if ( pageIndex==this.pageCount )
{
list
= this.list.slice( -(this.list.length - (this.pageCount-1)*this.pageSize) );
this.eIsLastPage(document.getElementById(this.nextId));
}
else
{
list
= this.list.slice( (pageIndex-1)*this.pageSize,pageIndex*this.pageSize);
this.eIsMiddlePage(this);
}

for (var i=0;i<list.length;i++)
{
if ( list[i].isLoad==false && list[i].img.src == "" )
{
list[i].img.src
= this.loadingSrc;
this.loadImg(list[i].src,this.imgMaxWidth,this.imgMaxHeight,function (src,width,height,parms){
parms.img.style.width
= width+'px';
parms.img.style.height
= height+'px';
parms.img.src
= parms.src;
if(Photo.imgMaxHeight > height)
parms.img.style.marginTop
= (Photo.imgMaxHeight - height)/2+'px';
},list[i]);
}
}

if (pageIndex==this.pageIndex) return;

//count the scroll space
var space = pageIndex > this.pageIndex ? this.itemWidth*this.pageSize : -this.itemWidth*this.pageSize;
//debugger;
//alert('Move Space:'+space);
//scroll in the container using timer
this.scroll(space);
//last set pageIndex
this.pageIndex = pageIndex;
},
scroll :
function (space)
{
var hasMove = 0;
function enlarge(){
var container = document.getElementById(Photo.containerId);
var interval = space > 0 ? Photo.interval : -Photo.interval;

//if(hasMove==0) alert('Begin scrollLeft:'+container.scrollLeft);

container.scrollLeft
+= interval;
hasMove
+= Math.abs(interval);
if( hasMove >= Math.abs(space) ){
clearInterval(Photo.timer);
//alert('End scrollLeft:'+container.scrollLeft);
};
}
Photo.timer
= setInterval(enlarge,this.speed);
},
isFirstPage :
function ()
{
return this.pageIndex == 1;
},
isLastPage :
function ()
{
return this.pageIndex == this.pageCount;
},
eIsFirstPage :
function (target){},
eIsLastPage :
function (target){},
eIsMiddlePage :
function (target){},
ePrev :
function (target)
{
this.setPage( this.pageIndex-1 );
},
eNext :
function (target)
{
//debugger;
this.setPage( this.pageIndex+1 );
},
enableMouseDown :
false,
isMouseDown :
false,
nextSpace :
82*5,//还差到下一页的距离default:pageSize*itemWidth(init内设置)
scrollSpace : 0,
eMouseDown :
function (interval)
{
//这个方法分页算发还有问题。-_-!!!
var downSpace = 0;//鼠标按下滚动的距离
this.isMouseDown = true;
timer
= setInterval(function (){
if ( Photo.isMouseDown) {

//if ( Photo.scrollSpace< 0 || Photo.scrollSpace > document.getElementById(Photo.containerId).scrollLeft ) return ;
// && document.getElementById(Photo.containerId).scrollLeft>=0 && document.getElementById(Photo.containerId).scrollLeft<parseInt(document.getElementById(Photo.scrollContainerId).style.width)
downSpace += Math.abs(interval);
Photo.scrollSpace
+= interval;
var moveItem = Math.ceil( downSpace/Photo.itemWidth*1.0 );

Photo.nextSpace
+= interval;
var movePage = 0;
if ( Math.abs(Photo.nextSpace) >= Photo.pageSize*Photo.itemWidth)
{
if ( Photo.nextSpace > 0 )
{
Photo.nextSpace
-= Photo.pageSize*Photo.itemWidth;
movePage
=1;
}
else
{
//debugger;
Photo.nextSpace += Photo.pageSize*Photo.itemWidth;
movePage
=-1;
}
}
//var movePage = moveScoll >= (Photo.pageSize*Photo.itemWidth) ? 1 : 0;

Photo.pageIndex
+= movePage;

var list = Photo.list.slice( Photo.pageSize*(Photo.pageIndex-1) , Photo.pageSize*Photo.pageIndex);
for (var i=0;i<list.length;i++)
{
if ( list[i].img.src == "" )
list[i].img.src
= list[i].src;
}

Photo.scroll(interval);

//document.getElementById("test").innerHTML = 'moveItem:' + moveItem;
//document.getElementById("test").innerHTML += ',movePage:' + movePage;
//document.getElementById("test").innerHTML += ',pageIndex:' + Photo.pageIndex;
//document.getElementById("test").innerHTML += ',downSpace:' + downSpace;
//document.getElementById("test").innerHTML += ',scrollSpace:' + Photo.scrollSpace;

}
else clearInterval(timer);

}, Photo.speed);
},
eMouseUp :
function ()
{
//alert("eNextMouseUp");
Photo.isMouseDown = false;
},
eClick :
function (target)
{
this.currImg = target;
return false;
},
loadImg :
function(src,width,height,callback,parms)
{
var imgElem = new Image();
imgElem.style.display
= "none";
imgElem.onload
= function (){
var loadWidth = parseFloat(imgElem.width), loadHeight = parseFloat(imgElem.height);
var zoomWidth = loadWidth, zoomHeight = loadHeight;
if(width && height && (loadWidth>width || loadHeight>height) )
{
if(Math.abs( width-loadWidth) < Math.abs( height-loadHeight) )
{
//宽度不变,等比缩放高度。
zoomWidth = width;
zoomHeight
= (width*loadHeight)/loadWidth;
//高度大于需要高度,继续宽度缩放
if (zoomHeight > height)
{
zoomWidth
= width*height/zoomHeight;
zoomHeight = height;
}
}
else
{
zoomHeight
= height;
zoomWidth
= (height*loadWidth)/loadHeight;
if (zoomWidth>width)
{
zoomHeight
= width*height/zoomWidth;
zoomWidth = width;
}
}
}
if (callback) callback(src,zoomWidth,zoomHeight,parms);
setTimeout(
function (){
imgElem.parentNode.removeChild(imgElem);
imgElem
= null;
},
0);
};
imgElem.src
= src;
imgElem.onabort
= function (){ imgElem.src = imgElem.src; };
//imgElem.onreadystatechange=function(){ if (imgElem.readyState=="complete") {} }
document.body.insertBefore(imgElem,document.body.childNodes[0]);
}
};

上面的JS代码还有点小BUG,就是当设置鼠标点击按住不放的连续的滚动还有点问题,计算出来的距离有误,导致分页算法不正确。这个实现的难点在于要计算总共滚动了多远,然后要算上上次滚动的距离,如果上次滚动了半页,这次没有滚动半页当前pageIndex是不加的,但是如果这次滚动超过了半页pageIndex则加一,而下页只需要滚动一页宽度减去上次滚动1页超过的距离,算起有点晕,昨天我还被搞的稀里糊涂的,最后还是没有准确的算出来,如果是上一页或下一页一页页的距离翻,那到好计算,但是我想实现只滚一张图片的话就只下载这一张图片就有点晕了。总体来说实现了以下功能:

  1. 图片列表JS客户端分页,而且每次只下载显示的张数的图片,点下一页才下载下一页的图片。这样的做法用意就不要说了吧,因为如果图片列表多的话一次性全部下载所有图片有可能会很慢,所以最基本的功能便是用JS来分页,计算原理很简单,在服务器动态输出JS将所有图片对象保存在数组里面,然后就是初始话的分页计算判断很简单了。
  2. 可以自定义分页大小,指定上一页下一页的按钮,将自动绑定CLICK事件,如果设置了enableMouseDown为true的话,将关联mouseout和mouseout事件,实现点击按钮不放连续滚动的功能,这个用定时器来实现也很简单,用了一个全局变量来标识是否正在按下,mouseout的时候设置为false即关闭定时器,就是上面说的要计算当前分页比较棘手...
  3. 自定义点击图片、当前是第一页、中间页、最后一页的回调事件,点击图片事件这个很重要肯定要自定义,比如我们经常点图片列表内小图片的时候设置大图片SRC,加载当前这张图片的评论,上传日期等。我这里做的时候在click事件里面把当前图片的push进数组里面的信息作为参数传入进来,然后好获取这张图片的信息,这个事件里面设置图片路径,显示的上传日期、设置当前图片的样式为选种的样式,实现Ajax请求获取图片评论(这个在我的相册里面没做),第一页、中间页、最后一页的回调事件是用来判断为第一页上一页按钮不可选,最后一页下一页不可选等的。
  4. 增加图片列表的预载功能,并根据图片大小等比缩放,支持相片显示名称创建P元素,调整相关样式。(最新增加)

在引用了Photo那个JS文件后我设置处初试话相册分页的代码如下:

//settings
Photo.pageSize = 7;
Photo.prevId
= "btnPrev";
Photo.nextId
= "btnNext";
Photo.enableMouseDown
= false;
Photo.containerId
= "miniaturelist";
Photo.scrollContainerId
= "miniaturescroll";
Photo.loadingSrc
= "style/default/loading.gif";

Photo.itemWidth
= 80;
Photo.imgMaxWidth
= 66;
Photo.imgMaxHeight
= 49;
Photo.createLi
= true;
Photo.createName
= false;
Photo.speed
= 20;
Photo.interval
= 40;

Photo.eClick
= function (target)
{
//the click callback event
document.getElementById("imgOriginality").href = target.src;
document.getElementById(
"currentName").innerHTML = target.name;
document.getElementById(
"spanName").innerHTML = target.name;
document.getElementById(
"spanTime").innerHTML = target.time;
document.getElementById(
"spanClick").innerHTML = target.click;
document.getElementById(
"spanReviewCount").innerHTML = target.reviewCount;

for(var i=0;i<Photo.list.length;i++)
{
Photo.list[i].img.parentNode.className
= "";
}
target.img.parentNode.className
= "on";
target.img.parentNode.blur();

var imgElem = document.getElementById("imgCurrent");
if(target.isLoad==true && target.img.src != "")
{
imgElem.src
= target.src;
return false;
}

var maxWidth = 730, maxHeight = 500;
imgElem.style.marginTop
= (maxHeight-32)/2+"px";
imgElem.style.width = "32px";
imgElem.style.height
= "32px";
imgElem.src
= "style/default/loading.gif";

this.loadImg(target.src,maxWidth,maxHeight,function (src,width,height,imgElem){
imgElem.style.width
= width+"px";
imgElem.style.height
= height+"px";
imgElem.src
= src;
if(height<maxHeight)
{
imgElem.style.marginTop
= (maxHeight-height)/2+"px";
}else
{
imgElem.style.marginTop
= "0px";
}

},imgElem);

this.currImg = target;
};

Photo.eIsFirstPage
= function (target)
{
target.className
= "prev prevdisabled";
if (Photo.pageCount > 1) document.getElementById(Photo.nextId).className = "next";
};

Photo.eIsLastPage
= function (target)
{
target.className
= "next nextdisabled";
if (Photo.pageCount > 1) document.getElementById(Photo.prevId).className = "prev";
};

Photo.eIsMiddlePage
= function (target)
{
document.getElementById(Photo.prevId).className
= "prev";
document.getElementById(Photo.nextId).className
= "next";
};

<%=photoScript %>
Photo.init();


if (Photo.list.length==0)
{
document.getElementById(
"miniaturebox").style.display="none";
document.getElementById(
"miniaturebody").innerHTML = "暂无照片。";
}
else
{
//init the first is choosed
if( Photo.list.length > 0) Photo.eClick(Photo.list[0]);
document.getElementById(Photo.scrollContainerId).style.width
= parseFloat(document.getElementById(Photo.scrollContainerId).style.width)+2+"px";
//only 1 page
if (Photo.pageCount<=1)
{
document.getElementById(Photo.prevId).disabled
= true;
document.getElementById(Photo.prevId).className
= "prev prevdisabled";
document.getElementById(Photo.nextId).disabled
= true;
document.getElementById(Photo.nextId).className
= "next nextdisabled";
}
//auto center
document.getElementById("miniaturebox").style.width = ( (Photo.pageCount>1?Photo.pageSize:Photo.list.length) *Photo.itemWidth)+23*2+"px";
}

总结:

泼自己一下冷水,从上面调用的看来,这个JavaScript类写的确实很烂,你看还需要自己写这么多的复杂判断的代码,也不够通用,因为上面实现的图片滚动还必须是要是特定的布局,因为图片列表滚动的原理是设置ScrollLeft距离,所以必须有一个最外面大的DIV布局overflox:hidden,里面的里表容器宽度一定是超过外面的DIV的,不然ScrollLeft将无效,只所以用设置ScrollLeft的方法。当然可以使用float,设置里的div容器overflow:visible,而外面的div容器固定宽度并设置overflox:hidden。

标签:JavaScript
  • posted@ 2009-07-04 20:01
  • update@ 2009-11-29 16:19:02
  • 阅读(13394)
  • 评论(0)

相关文章

评论
暂无任何评论。
发表评论
*必填
回复通知我
*必填