类似淘宝京东上的产品图,我们可以放大来看产品的具体细节。那么,在移动设备上,基于Web浏览器的这种效果又是如何实现的呢?
一.使用touchEvent来实现,关于touchEvent的一些基本知识,可以阅读文章——多点触摸网络开发
1.页面代码
<div id="warpper" class="warpper">
<div class="clearfix"></div>
<div id="content" class="content" onclick="change()" >
<img id="testimg" class="testimg" src="http://image.zcool.com.cn/img2/21/50/m_1312514725921.jpg">
</div>
</div>
2.CSS代码
html, body{
margin: 0;
padding: 0;
width:100%;
height:100%;
background:#ddd;
}
.warpper{
position:relative;
width:100%;
height:100%;
margin:auto;
}
.clearfix{
position:relative;
width:100%;
height:100px;
}
.content{
position:relative;
width:450px;
height:338px;
margin:auto;
border:2px solid #92B2CA;
overflow:hidden ;
}
.testimg{
position:absolute;
z-index:1;
width:450px;
height:338px;
top:0px;
left:0px
}
3.JS代码
$(document).ready(function(){ var pagewidth = document.body.clientWidth;//获取页面可用宽度 $(".content").width(pagewidth*0.8);//设置css类为content标签div的宽度 $(".testimg").width(pagewidth*0.8);//设置css类为testimg标签img的宽度 $(".content").height($(".testimg").width()*0.75);//设置css类为content标签div的高度 $(".testimg").height($(".testimg").width()*0.75);//设置css类为testimg标签img的高度 imgInitialWidth = $(".testimg").width();//获取图片testimg的初始宽度 imgInitialHeight = $(".testimg").height();//获取图片testimg的初始高度度 screenWidth = screen.width;//获取屏幕宽度 screenHeight = screen.height;//获取屏幕高度 screenDistance = Math.sqrt(screenWidth*screenWidth+screenHeight*screenHeight);//根据屏幕分辨率获取屏幕对角线长 }); var oneStartX; var oneStartY; var oneEndX; var oneEndY; var twoStartX; var twoStartY; var twoEndX; var twoEndY; var initialDistance; var moveDistance; var screenWidth; var screenHeight; var screenDistance; var radio; var base; var widthNow; var canvas = document.getElementById("body");//触摸有效的区域元素 var imgInitialWidth; var imgInitialHeight; var imgInitialTop; var imgInitialLeft; /*改变图片testimg的大小:当图片大小与初始大小一致时改变其大小,变为原来的2倍;否则恢复初始大小*/ function change(){ widthNow = $(".testimg").width(); if(widthNow==imgInitialWidth){ //改变图片大小为初始值的2倍,并移动图片使其在div中居中显示 $(".testimg").animate({"width":imgInitialWidth*2,"height":imgInitialHeight*2,"top":-imgInitialHeight/2,"left":-imgInitialWidth/2},500); } else{ //图片恢复初始大小 $(".testimg").animate({"width":imgInitialWidth,"height":imgInitialHeight,"top":0,"left":0},500); } } /*开始触摸*/ function touchStart(e) { //获取图片testimg的位置参数 imgInitialTop = +$(".testimg").css("top").split(‘p‘)[0]; imgInitialLeft = +$(".testimg").css("left").split(‘p‘)[0]; var touches = e.targetTouches; //获取位于设置dom元素上的手指动作列表 var i = 0, l = touches.length,touch,touchId; if(l==1){ oneStartX = touches[0].pageX; oneStartY = touches[0].pageY; } //如果该元素上有俩个手指动作,分别获取手指动作所在坐标,并计算手指之间的初始距离 if(l==2){ oneStartX = touches[0].pageX; oneStartY = touches[0].pageY; twoStartX = touches[1].pageX; twoStartY = touches[1].pageY; initialDistance = Math.sqrt((twoStartX-oneStartX)*(twoStartX-oneStartX)+(twoStartY-oneStartY)*(twoStartY-oneStartY)); } widthNow = $(".testimg").width();//获取图片testimg的即时宽度 } /*触摸移动*/ function touchMove(e) { e.preventDefault(); //关闭触摸移动的默认动作 var touches = e.targetTouches; //获取位于设置dom元素上的手指动作列表 var i = 0, l = touches.length,touch,touchId; //如果设置dom元素上的只有一个手指动作,则该动作用于移动图片位置,并且只有在图片大小与初始大小不一致时生效 if(l==1){ if(widthNow!=imgInitialWidth){ var x = touches[0].pageX - oneStartX; var y = touches[0].pageY - oneStartY; var changeX = imgInitialLeft+x; var changeY = imgInitialTop+y; var imgWidthChange = $(".testimg").width()-imgInitialWidth; var imgHeightChange = $(".testimg").height()-imgInitialHeight; if(changeX>0){ changeX = 0; }else{ if(changeX*(-1)>imgWidthChange){ changeX = -imgWidthChange; } } if(changeY>0){ changeY = 0; }else{ if(changeY*(-1)>imgHeightChange){ changeY = -imgHeightChange; } } $(".testimg").css({"top":changeY,"left":changeX}); } base=1; } //如果设置dom元素上的有2个手指动作,则该动作用于确定移动后俩手指坐标 if(l==2){ oneEndX = touches[0].pageX; oneEndY = touches[0].pageY; twoEndX = touches[1].pageX; twoEndY = touches[1].pageY; base=2; } } /*触摸结束*/ function touchEnd(e) { //当设置dom元素上的有2个手指动作时,变换图片大小 if(base===2){ /* *当移动后的俩手指距离大于触摸开始时的距离,及伸展触摸时,根据手指坐标取得的变换参数来确定图片的变换大小; *当移动后的俩手指距离小于触摸开始时的距离,及收缩触摸时,图片恢复初始大小; */ moveDistance = Math.sqrt((twoEndX-oneEndX)*(twoEndX-oneEndX)+(twoEndY-oneEndY)*(twoEndY-oneEndY));//移动后俩手指之间的距离 radio = (moveDistance-initialDistance)*40/screenDistance;//根据滑动距离和页面大小确定的变换参数,可以调整倍数来达到合适效果 if(moveDistance>initialDistance){ $(".testimg").animate({"width":imgInitialWidth*radio,"height":imgInitialHeight*radio,"top":-imgInitialHeight*(radio-1)/2,"left":-imgInitialWidth*(radio-1)/2},500); }else{ $(".testimg").animate({"width":imgInitialWidth,"height":imgInitialHeight,"top":0,"left":0},500); } } } canvas.addEventListener("touchstart", touchStart, false);//监听触摸启动事件 canvas.addEventListener("touchmove", touchMove, false);//监听滑动事件 canvas.addEventListener("touchend", touchEnd, false);//监听触摸结束事件 //阻止body上的触摸默认事件,如翻页、滚动和缩放(有效性有待考证) document.body.addEventListener(‘touchmove‘, function(event) { event.preventDefault(); }, false);
整体思路为——事件双点触摸滑动改变图片大小:根据触摸双点前后距离差决定图片放大还是复原,根据俩个点触摸滑动的平均距离决定放大比例,并对应改变图片的top和left,及坐标,保证图片居中显示。事件单点触摸滑动移动图片位置:根据touch的坐标变化来改变图片的top和left,并设置极限值确保图片不会移出。需要注意的是只有 e.targetTouches才能获取到多个手指的坐标,不知道是什么原因。
二.使用js插件来模拟手势效果达到要求,可参考移动web开发,12个触摸及多点触摸事件常用Js插件,具体使用这里不讨论。
总结:
1.js插件功能强大,但是每一个的使用方法都有所不同,想要学会,要下一番功夫,并且定制功能在细节上有其局限性,无法满足某些需要;
2.自己写touch事件,会遇到很多问题,效果也不一定能尽人意,但是能学到更多的知识,而且如果真正理解透彻了,可以写自己的插件!