写在最前面:Demo的源起来自于http://js.fgm.cc/learn/,但是实现部分都是经过自己思考和优化的,有时会借助别人的图片,然而“窃喜”。如无特殊说明,demo都是经过ie6、ie7等低版本浏览器测试通过的。表要笑话我有“自虐”倾向,各中是有情节和情结的。力图做得专业再专业一点点。^_^
实现的功能:根据鼠标移入小图区域,显示大图。这种功能应用很常见于各种购物网站,在商品展示中,单击小图,展示详情大图。
Demo地址: http://yuyingguo.sinaapp.com/jsStudy/鼠标移入仿购物网站图片查看细节.html
有图有真相:
实现思路:思路很明确,就是根据鼠标单击事件,获取到事件源的,将相应的大图片展示出来。所以问题可以分为两个部分,找到事件源是一步,根据事件源得到大图信息(确切的说就是大图路径)是第二步。在以下代码中,对于找大图路径做了”手脚“,人为设置小图名为small_**.jpg,相应大图为big_**.jpg。
为了demo的美观性,在css上也是用心处理过的:主要的样式#gallery和li。以下对其分析。
gallery的宽高都是计算过的,根据你图片的大小,预留间隙,建议你在写代码前画张草图吧。gallery设置为absolute定位,是因为我要把它垂直水平居中显示。定位到left:50%和top:50%,这是将图片的左上角定位到了正中间,但是要知道图片是有宽高的,我们的目的应该是使图片的中心出于显示区的正中间,所以就有了margin-left:-106px和margin-top:-132px,即把图片向左和向上偏移宽高的一半。图片中心和是显示中心重合,实现垂直水平居中。
#gallery { background: white; width: 212px; height: 264px; position: absolute; left: 50%; top: 50%; margin-left: -106px; margin-top: -132px; border: 5px solid white; } li { float: left; margin: 0px 0px 0px 2px; }
这里岔开一点题外话,阿里UED崖鹰老师面试我的时候,问我是更擅长js一点还是css一点,我说两个都可以。然后问了我js问题和css的相关问题。不得不说崖鹰老师的问题都是偏向于细节方面,是一种更向完美优化解决问题的方向发展的。而一面的小新老师问的问题,侧重你对实践的考验,对整体的把握,对解决问题的思路的把握,还有对你整个人的态度的考核,比如说“你平时真的有去思考吗?”,“往简历上砸的东西真的是你实打实掌握的吗?”。而清羽老师给我的感觉就是“你平时思考的方式源自你的态度,然后决定了你的高度”。真的谢谢阿里,让我走完了所有的实习面试流程,尽管结果让我感觉一方面是自己的实力还欠一点打磨还有一方面就是和阿里的缘分还不够吧。和HR莫利老师的聊天过程也让我受益颇多,当时回答仓促,之后细细回想,很多问题都是让你对自身的思考、自身价值观的思考、对自己职规的思考、对你所选择的行业的思考。
回归正传,之前岔开话题是因为我想表述崖鹰老师给我css方面所带来的启示,然后不小心泄露了感情,说多了>_<。写css应该是一种“艺术”,我个人觉得这种艺术无关于技巧,而是—种态度——相信任何一个用心的csser都可以做到,让你手写的每一条css规则都是有理由存在并且是不可替代(就是说,要在你现在的水平上做到最好),这就是追求极致的态度。
js优化部分是很明显的,使用了事件代理(对于事件代理的详细信息可以参看我的另外一篇js文章: http://www.cnblogs.com/Iwillknow/p/3693149.html),即没有给<li>分别注册事件监听,而是给父元素<ul id="gallery">注册事件。以下代码是为了兼容FF和ie。
var event = e||window.event; var eventSrc = event.target||event.srcElement;
代码中你会看到if(typeof eventSrc.id != "undefined") { //你知道这句话的重要性吗的字样。因为本人在这里掉进了一个坑。事件代理是用了事件冒泡的处理机制,事件绑定到更高层的DOM。在此处,因为DOM之间的嵌套,我将onmouseover绑定到<ul>上,一个严重的后果就是当我鼠标移过的时候,其实是会触发两次事件的,一件是移过<li>时触发,冒泡到<ul>;另外当鼠标移出移过的时候,在<ul>区域触发<ul>上的事件,因为<ul>本身是没有定义src属性的,所以在读取eventSrc.src时出现undefined错误。当然这个错误并没有直接抛出来,因为本身去读这个属性是不会出错的,异常是从调用replace函数抛出的,因为replace是对字符串奏效,所以就出现method undefined的错误。
后话:其实事件代理优化js的手段大家都是知道的,不过不去实践一下还真不知道会有很多细节问题。自勉自勉~
完整代码如下:
<!doctype html> <html> <head> <style> * { margin: 0px; padding: 0px; } ul { list-style-type: none; } body { background: black; } #gallery { background: white; 212px; height: 264px; position: absolute; left: 50%; top: 50%; margin-left: -106px; margin-top: -132px; border: 5px solid white; } li { float: left; margin: 0px 0px 0px 2px; } #gallery li.first { position: relative; } #loading { position: absolute; left: 0px; top: 0px; background: url("img/loading.gif"); display: none; } </style> <script> window.onload = function() { var targetObj = document.getElementById("gallery"); var firstObj = document.getElementById("first"); var loadingFlag = document.getElementById("loading"); var count = 0; targetObj.onmouseover = function(e) { var event = e||window.event; var eventSrc = event.target||event.srcElement; if(typeof eventSrc.id != "undefined") { //你知道这句话的重要性吗 //****** //console.log("eventSrc.src " + eventSrc.src); //****** var imgSrc = null; imgSrc = eventSrc.src; //****** //console.log("imgSrc " + imgSrc); //****** var newFirstImg = new Image(); newFirstImg.src = imgSrc.replace(/small/,"big"); loadingFlag.style.display = "block"; firstObj.children[0].src = newFirstImg.src; //****** //console.log("newFirstImg.src " + newFirstImg.src); //****** newFirstImg.complete?loadingFlag.style.display = "none":(firstObj.children[0].onload = function()
{loadingFlag.style.display = "none"}); } }; }; </script> </head> <body> <ul id="gallery"> <li id="first"><img src="img/big_1.jpg"/><div id="loading"></div></li> <li><img src="img/small_1.jpg"/></li> <li><img src="img/small_2.jpg"/></li> <li><img src="img/small_3.jpg"/></li> <li><img src="img/small_4.jpg"/></li> <li><img src="img/small_5.jpg"/></li> <li><img src="img/small_6.jpg"/></li> <li><img src="img/small_7.jpg"/></li> <li><img src="img/small_8.jpg"/></li> <li><img src="img/small_9.jpg"/></li> <li><img src="img/small_10.jpg"/></li> <li><img src="img/small_11.jpg"/></li> </ul> </body> </html>