NOTICE:你能看懂全文的话,你就会做了,是真正的会,不是拿来主义!
to be continue……
目的:做个仿照淘宝的图片放大镜!图片是根据选择的记录动态加载的,而不是单纯静态图放大镜效果!
过程:是曲折的!搜索了如何做,如何处理图片,然后尝试了N个JQuery插件,均没有理想的效果。最后得了一个比较理想的具有OO思想的JS(qsoft.PopBigImage.v0.35.js)。
认识:图片放大的算法,是不变的。变化的是显示放大图片的形式:在原图左or右?上or下?漂浮or内嵌?结合EXTor不用框架?
方法:使用qsoft.PopBigImage.v0.35.js(作者
[email protected],是位很好的大牛!昨天抱着试试看的态度,跟这位哥们求助,他居然回复我了,而且回答的很有建议和启发性,向您表示致敬!后面我把您的这个JS改了,但改动还未优化,希望你老人家别见怪,呵呵 by the way,希望我没侵权呀。。。)
要求描述:
界面是用Ext,从下部的记录区域里,选择一条记录,把该记录对应的图片放在黄色区域里(Ext.Panel)。
鼠标移动到黄色小图区域里,左侧弹出蓝色的大图区域,鼠标移开,蓝色区域消失。
神马,你听不懂?蹲墙角思过去~~~
问题难点:
1)点击查询出来的记录,获取记录的ImgUrl字段值,这是easy的,ext有很好的获取方法。
2)然后在选择记录的事件里,完成黄色区域的图片绑定、蓝色区域的图片对象预加载功能(图片很大,先获取图片的大小给蓝色区域的mask用。为啥获取这两个参数给mask用?这个主要是看了qsoft的处理思路想到的。。。。一切为了速度吧!mask是啥?我也不懂~~~,JS只是拿来主义,翻书。。。。哈哈)。
PS:黄色区域是个,EXT的,希望你能看懂~~ var picDisplay = ''; this.panel = new Ext.Panel({ border : false, frame : false, width : 200, height : 200, html : picDisplay }); 绑定的时候,只需要在点击选择记录的事件里添加上src的绑定就可以了。
document.getElementById("smallPic").src = rowArray[rowArray.length-1].get('picURL');
黄色区域是有图片了,但是,但是,蓝色区域却没有对象呀。。。
很多人的做法是:黄色区域是个小图,蓝色区域是个大图,两张图片,gameover!
我这里就不行了,我这里黄色区域的图片是根据选择的记录动态加载的、蓝色区域的图片是获取黄色区域的图片(关键:大图小图皆一张图no 大图小图),它们的mother一样,那他俩怎么一个黄一个蓝?纠结。。。OMG
幸好发现了qsoft.PopBigImage,它给我带来了福音,于是我的点击记录事件的方法这样写的(好吧,贴代码): this.pPpGrid.selModel.on('selectionchange', function(selModel) { var rowArray = selModel.getSelections();//选择的记录 if(rowArray.length == 0) { document.getElementById("smallPic").src = "/image/nopic.jpg"; imgIsSelected = false;//新加变量,false为关闭放大镜功能。神马?为什么关?不选择记录,你开神马放大镜效果呀,神经病! .... } else { document.getElementById("smallPic").src = rowArray[rowArray.length-1].get('picURL'); imgIsSelected = true;//选择记录时,图片放大镜要打开了 if(picMaxObject == null)//这个对象是为了万恶的放大图 { picMaxObject = new qsoft.PopBigImage("smallPic",-561,0,1,1);//看看qsoft,真佩服作者写成了OO方法,俺直接调用 picMaxObject.render();//这个很神。。。。 } else { picMaxObject.resize("smallPic");//新写的方法 } ... } }); 但也带来了新的问题,to be continue……
3)选择记录,黄色区域显示图片了。于是鼠标移动到黄色区域,这个就有onmouseover事件了。
细心看的话,我没有在smallPic上添加onmouseover事件!
qsoft里面已经实现了,作者同学,你自己写的代码很犀利很神呀!哈哈哈哈
onmouseover事件触发了放大镜效果,主要完成:放大区域显示、放大区域图片显示、放大区域与黄色原图区域的对应。(详见提到N遍的这个JS吧)
静态图时,qsoft实现了三个中的三个。这也是我用她的原因,不想去了解什么JQueryZoom\XXXZoom那些插件!!
这里,是动态加载的图,qsoft实现不了放大区域的图片加载!悲呼~~于是email作者,作者说今天晚上给搞搞,今天晚上你在搞这个问题吗?忙一天了,别搞了,我下午搞出来了,忘记给你说了,我太不厚道了,,,只因太忙,都是公司逼的!中间10086MM来电又搞了很久,OMG匆忙的一天过去了~~~
贴代码吧,你能读懂,你就来读,反正是对的,但可以优化,太晚了,忙。。。困。。。。有空再优化吧 var imgIsSelected = false;//set this function should open or not var picMaxObject;//put original img to this var,then produce a big one for mask var im = new Image();//to get original img.height and img.weight for mask.This is important,because we must know the height and width first to build mask. var qsoft = { version : 1.0, isIE : document.all ? true : false, prefx : 'qsoft', __id : 0, nextId : function() { return this.prefx + this.__id++; } } qsoft.PopBigImage = function(origImage, dx, dy, mx, my) { var type = typeof (origImage); if (type.toLowerCase() == "string") this.oim = document.getElementById(origImage); else this.oim = origImage; if (typeof (this.oim.pbi) != "undefined") return this.oim.pbi; //以下不解释,自己学学图片放大镜算法,不会的方法插JS API this.id = qsoft.nextId(); this.oim.__maskid = this.id; this.oim.style.cursor = "crosshair"; this.ow = this.oim.width; this.oh = this.oim.height; this.detaX = (typeof (dx) == "undefined") ? 30 : dx; this.detaY = (typeof (dy) == "undefined") ? 0 : dy; var getPos = function(o) // for chrome { var x = 0, y = 0; do { x += o.offsetLeft; y += o.offsetTop; } while ((o = o.offsetParent)); return { left : x, top : y }; } this.getPosition = function(o) { return document.documentElement.getBoundingClientRect && o.getBoundingClientRect() || getPos(o); } var rect = this.getPosition(this.oim); this.ol = rect.left + this.detaX + this.ow - (qsoft.isIE ? 2 : 0); this.ot = rect.top + this.detaY - (qsoft.isIE ? 2 : 0); this.src = this.oim.src; this.getImageSize = function(img) { var flagLoaded;//值得一提的BT下载判断还有新加的BT不下载完不让走while语句 if (img.readyState == "uninitialized") {//图片还没加载进来? while (img.readyState == "complete") {//使劲给我load!完成了再放你continue flagLoaded = true; break; } } if (flagLoaded) {//下载完成了,设置吧 var size = {}; size.width = img.width; size.height = img.height; return size; } else {//没下载完,客户又等不起,先这么搞吧 var size = {}; size.width = 1600;//这里写死了,其实是不对的,但是业务需要先这样搞 size.height = 1260;//不过确实挺犀利,谁用谁知道! return size; } } var rsize = this.getImageSize(this.oim); this.w = rsize.width; this.h = rsize.height; this.maskX = (typeof (mx) == "undefined") ? this.ow : mx; this.maskY = (typeof (my) == "undefined") ? this.oh : my; if (this.maskX this.w ? this.w : this.maskX; this.maskY = this.maskY > this.h ? this.h : this.maskY; var qObj = this; this.createMask = function() { if (typeof (this.mask) == "undefined") { this.mask = document.createElement("div"); this.mask.id = this.oim.__maskid + "_mask"; this.mask.style.position = "absolute"; this.mask.style.width = this.maskX + "px"; this.mask.style.height = this.maskY + "px"; this.mask.style.left = this.ol + "px"; this.mask.style.top = this.ot + "px"; this.mask.style.backgroundImage = "url(" + this.src + ")"; this.mask.style.backgroundRepeat = "no-repeat"; this.mask.style.display = "none"; this.mask.style.zIndex = 1000; document.body.appendChild(this.mask); } } this.regEvent = function() { this.oim.onmousemove = function() { var e = arguments[0] || window.event; var ct = e.target || e.srcElement; var sz = qObj.getPosition(ct); var ox = qsoft.isIE ? e.offsetX : (e.pageX - sz.left); var oy = qsoft.isIE ? e.offsetY : (e.pageY - sz.top); var x = Math.ceil(ox * qObj.w / qObj.ow) - qObj.maskX / 2; var y = Math.ceil(oy * qObj.h / qObj.oh) - qObj.maskY / 2; if (x maxx) x = maxx; if (y > maxy) y = maxy; qObj.mask.style.backgroundPosition = -x + "px " + -y + "px"; sz = null; delete dz; } this.oim.onmouseout = function() { qObj.mask.style.display = "none"; } this.oim.onmouseover = function() { if (!imgIsSelected) { qObj.mask.style.display = "none"; } else if (document.getElementById(origImage).readyState == "complete") { qObj.mask.style.display = "block"; } else if (document.getElementById(origImage).readyState == "uninitialized") { //alert("image is loading in mouseover……"); while (document.getElementById(origImage).readyState == "complete") { break; } } } } this.render = function() { this.createMask(); this.regEvent(); } this.resize = function(origImage) { this.oim = document.getElementById(origImage); if (this.src == this.oim.src) { return; } if (this.oim.readyState == "uninitialized") { while (this.oim.readyState == "complete") { break; } } if (typeof (this.oim.pbi) != "undefined") return this.oim.pbi; this.oim.style.cursor = "crosshair"; this.ow = this.oim.width; this.oh = this.oim.height; this.detaX = (typeof (dx) == "undefined") ? 30 : dx; this.detaY = (typeof (dy) == "undefined") ? 0 : dy; var rect = this.getPosition(this.oim); this.ol = rect.left + this.detaX + this.ow - (qsoft.isIE ? 2 : 0); this.ot = rect.top + this.detaY - (qsoft.isIE ? 2 : 0); this.src = this.oim.src; var rsize = this.getImageSize(this.oim); this.w = rsize.width; this.h = rsize.height; this.maskX = (typeof (mx) == "undefined") ? this.ow : mx; this.maskY = (typeof (my) == "undefined") ? this.oh : my; if (this.maskX this.w ? this.w : this.maskX; this.maskY = this.maskY > this.h ? this.h : this.maskY; this.mask.style.width = this.maskX + "px"; this.mask.style.height = this.maskY + "px"; this.mask.style.left = this.ol + "px"; this.mask.style.top = this.ot + "px"; this.mask.style.backgroundImage = "url(" + this.src + ")"; this.mask.style.backgroundRepeat = "no-repeat"; rect = null; delete rect; } } qsoft.PopBigImage.create = function(origImage, dx, dy, mx, my, bflag) { var q = new qsoft.PopBigImage(origImage, dx, dy, mx, my); q.render(); if (bflag) q.mask.style.display = "block"; picMaxObject = q; return q; } 还有一个内存泄漏问题,就是每次选择一条记录时,内存会增加5M!使用JQueryZoom的,客户会因为机子慢骂人的。。。还是慎用吧!作者也来想想怎么改善吧,反正qsoft.PopBigImage.v0.35.js的作者爽了,这里已经给你解决了,还有,很赞你这个JS,内存泄漏不是你这个JS惹的祸,是我们使用时用的不恰当造成的!请看那个注释:。。。。//这个很神。。。。
改进的版本,命名为qsoft.PopBigImage.v1.1.js吧,毕竟改了不少的说。。。。。
牛顿说站在巨人的肩膀上,看的更远!
这里站在
[email protected]的肩膀上,学会了很多,3Q