仿pinterest实现瀑布流布局效果
在张鑫旭的博客里,有一片文章介绍 瀑布流 实现的文章,(要查看演示,请单击DEMO)本文是在其基础上进行的二次开发,使其更具实用性。
这里,主要涉及数据从数据库里读取,单击图片可以缩放等。
本文附件附带的源代码,有兴趣可以下载看看
下载的程序打开pic.aspx页面显示图片列表(您需要手动输入测试数据)。
单击图片会出现缩放等,除此外,还可以分页,(排序),以及设置页面大小等。
下面介绍本程序的大致实现。
1.建立数据库
见附件里SQL.txt,为了使得效果更明显,需要输入测试数据,越多越好
2.返回JSON数据 (ajax_getpics.aspx 页面)
返回数据使用了自定义分页,这里使用了SQL2005+上的Row_Number()函数。在GetData里,还有3个参数:orderby设置数据排序方式(一般网站的图片,都会让用户按照最新上传,点击率,回复率排序),预留这个参数就是为了解决这个问题。
pageIndex是通过传递的URL来获取的,也就是用户访问了第几页
pageSize设置页面的大小,在本演示中,设置了200.
public DataTable GetData() { string orderBy = "pic_id"; int pageIndex = int.Parse(Request["pageIndex"]); int pageSize = int.Parse(Request["pageSize"]); string sql = @" declare @startRowIndex int set @pageIndex=@pageIndex-1 set @startRowIndex=@pageIndex*@pageSize+1; WITH PICList AS ( select pic_id,user_id,orginpath,description,thumpath, commpeople, click, ROW_NUMBER() OVER (ORDER BY pic_id DESC) as RowNum FROM love_pics where isapproved=1 ) Select * from PICList WHERE RowNum BETWEEN @startRowIndex AND (@startRowIndex + @pageSize-1) order by " + orderBy + @" desc " ; DataTable ds = new DataTable(); SqlConnection conn = new SqlConnection(System.Web.Configuration.WebConfigurationManager.ConnectionStrings["con"].ConnectionString); SqlCommand dCmd = new SqlCommand(); dCmd.Parameters.AddWithValue("@pageIndex", pageIndex); dCmd.Parameters.AddWithValue("@pageSize", pageSize); dCmd.Parameters.AddWithValue("@orderBy", orderBy); dCmd.CommandText = sql; dCmd.Connection = conn; SqlDataAdapter da = new SqlDataAdapter(); da.SelectCommand = dCmd; da.Fill(ds); return ds; }
3.制作瀑布页面 pic.aspx
在开始前,我们先定义一个页面大小pageSize和自定义分页的实现。关于Pagination可以参考源代码里具体实现。
public int pageindex = 1; protected void Page_Load(object sender, EventArgs e) { if (!string.IsNullOrEmpty(Request.QueryString["currentpage"])) { pageindex = int.Parse(Request.QueryString["currentpage"]); } string sql = " Select count(*) from love_pics where isapproved=1 "; // string i = DBHelper.Instance.ExeScalar(sql).ToString(); string i = "1000"; //执行上面SQL语句,即可返回记录说,这里使用了硬编码,加上是100页 //附带的1=1只是用于演示如何自带参数 litPaging2.Text = litPaging1.Text = Pagination(int.Parse(i), 200, pageindex, "pic.aspx?1=1&"); }
4.获取JSON返回的数据,也就是用JQuery的getJSON,没设么特别的,其中pageindex是我们后台定义的页码。 后面自动跟了一个random是因为
js在请求时,即使你刷新页面,但是如果参数不变那么他自动使用本地缓存,所以加上random使得每次请求参数都是变更的
var pics=new Array() var ids=new Array(); var intros=new Array(); var uids=new Array(); var clicks=new Array(); var comms=new Array(); $.getJSON( 'ajax_getpics.aspx', { pageIndex: <%=pageindex%>, PageSize: "200", random: Math.random() }, function (data) { $.each(data, function (i, entry) { pics[i]=entry['orginpath']; ids[i]=entry["pic_id"]; intros[i]=entry["description"]; uids[i]=entry["user_id"]; clicks[i]=entry["click"]; comms[i]=entry["commpeople"]; }); //do detect
瀑布页码代码,这个代码是在页码加载完毕后加载的,因为刚才说过需要增加单击图片时,弹出预览大图的效果,所以这里使用了highslide插件
因此代码里增加了下图红色的标记
// 页面加载初始创建 create: function () { this.columnNumber = Math.floor(document.body.clientWidth / this.columnWidth); var start = 0, htmlColumn = '', self = this; for (start; start < this.columnNumber; start += 1) { htmlColumn = htmlColumn + '<span id="waterFallColumn_' + start + '" class="column" style="width:' + this.columnWidth + 'px;">' + function () { var html = '', i = 0; for (i = 0; i < 5; i += 1) { self.indexImage = start + self.columnNumber * i; var index = self.getIndex(); html = html + ' <a class="highslide pic_a" onclick="return hs.expand(this)" href='+index+' ><img src=' + index+' /><strong>'+self.getIntro().substring(0,50)+'</strong> <br> <span class=pro> '+self.getClick()+' click '+ self.getComm()+' comment </span> </a><div class="highslide-caption">'+self.getIntro()+' <a target=_blank href=userinfo.aspx?id='+self.getUid()+'>查看用户</a> | <a target=_blank href=picdetail.aspx?pid='+self.getId()+'>查看图片('+self.getClick()+')</a> </div> '; } return html; } () + '</span> '; } htmlColumn += '<span id="waterFallDetect" class="column" style="width:' + this.columnWidth + 'px;"></span>'; this.container.innerHTML = htmlColumn; this.detectLeft = document.getElementById("waterFallDetect").offsetLeft; return this; },
当页码滚动时,动态加载图片
// 滚动载入 append: function (column) { this.indexImage += 1; var html = '', index = this.getIndex(), imgUrl = index; // 图片尺寸 var aEle = document.createElement("div"); aEle.className = "pic_a"; aEle.innerHTML = ' <a class="highslide pic_a" onclick="return hs.expand(this)" href='+imgUrl+'><img src=' + imgUrl + ' /><strong>'+this.getIntro()+'</strong></a>'; column.appendChild(aEle); if (this.indexImage >= 200) { this.loadFinish = true; } return this; },
这样,一个比较完成的例子就完成了。 下载源代码