项目中要做图片查看器的需求,需要支持滑动切换上下张、手势缩放、双击放大等功能,用iScroll来实现是比较理想的方案。有以下几点需要注意:
- 页面要禁用缩放。(user-scalable=no)。
- 处于缩放状态时,滑动操作不要切换图片。可以通过图片元素的getBoundingClientRect方法判断。
- 自行给图片元素绑定touch事件,而不用iScroll的onScrollStart(Move、End)。避免在zoom状态切换时zoom状态判断出错。
下面贴出代码:
html
<pre><code>
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0;">
<meta charset="utf-8"/>
<title></title>
<script src="./iScroll.js" type="text/javascript"></script>
<script src="./imageViewer.js" type="text/javascript"></script>
</head>
<body>
<div id="wrapper">
<img id="image" src="" alt="" title="" style="width:100%;height:100%;" />
</div>
</body>
<script type="text/javascript">
var wrapperEl = document.querySelector("#wrapper");
var imageEl = document.querySelector("#image");
new ImageViewer({
wrapperEl:wrapperEl,
imageEl:imageEl,
totalImageCount:8,
getImageSrcByIndex:function(index) {
return "./frl.action" + index + ".jpg";
},
minScrollDistance:30
});
</script>
</html>
</code></pre>
js
<pre><code>
/*
*图片查看器组件
*/
/*图片查看器参数定义
interface IImageViewerOptions{
wrpperEl:HTMLElement; 图片元素的父元素
imageEl:HTMLImageElement; 图片元素DOM对象
totalImageCount:number; 需要展示的图片总数
getImageSrcByIndex:(index:number)=>string; 按索引值获取图片地址
minScrollDistance?:number; 触发切换图片的最小滚动距离
onloadingImage?:()=>void; 加载图片时要执行的操作,比如加些loading效果什么的
onloaded?:()=>void; 图片加载完成时要执行的操作,比如取消loading效果什么的
}*/
</code></pre>
<code>
function ImageViewer(options) {
this.imageEl = options.imageEl;
this.initialize(options);
}
ImageViewer.prototype = {
initialize:function(options) {
this.options = options;
this.currentImageIndex = 0;
this.imageEl.src = this.options.getImageSrcByIndex(this.currentImageIndex);
this.initEvents();
},
initEvents:function() {
var self = this;
if (!this.isSupportTouchEvents()) {
this.initClickEvents();
} else {
this.initTouchEvents();
}
//图片加载成功后设置下当前图片相对视窗的初始信息
this.imageEl.onload = function() {
self.initBoundingRectInfo = this.getBoundingClientRect();
self.options.onloadedImage && self.options.onloadedImage();
}
},
initClickEvents:function() {
var self = this;
this.imageEl.onclick = function(e) {
var eventX = e.pageX;
var boundingRectInfo = this.getBoundingClientRect();
boundingRectInfo.width = boundingRectInfo.width || (boundingRectInfo.right - boundingRectInfo.left);
var isClickedLeft = (eventX - boundingRectInfo.left) < (boundingRectInfo.width /2);
var delta = isClickedLeft ? -1 : 1;
self.loadAdjacentImage(delta);
};
},
initTouchEvents:function() {
var self = this;
this.minScrollDistance = this.options.minScrollDistance || 20;
new iScroll(this.options.wrapperEl,{
zoom: true,
zoomMin: 1,
zoomMax: 4,
doubleTapZoom: 2,
useTransition: true,
checkDOMChanges: false,
hScrollbar: false,
vScrollbar: false
/*onZoomStart: function() {
return false;
},
onScrollStart:function(e) {
self.touchStartX = e.touches[0].pageX;
},
onScrollMove: function(e) {
self.touchMoveX = e.touches[0].pageX;
},
onScrollEnd: function() {
if(self.isImageZoomed()){
return;
}
var moveDistance = self.touchMoveX - self.touchStartX;
if (Math.abs(moveDistance) < self.options.minScrollDistance) {
return;
}
var delta = moveDistance > 0 ? -1 : 1;
self.loadAdjacentImage(delta);
}*/
});
//双击放大,再双击还原后会触发onScrollEnd,此时this.isImageZoomed()为false;会去加载下一张。
//不如自己绑定touch事件。
this.imageEl.ontouchstart = function(e) {
self.touchStartX = e.touches[0].pageX;
};
this.imageEl.ontouchmove = function(e) {
self.isMoving = true;
self.touchMoveX = e.touches[0].pageX;
};
this.imageEl.ontouchend = function() {
if (self.isMoving && !self.isImageZoomed()) {
var moveDistance = self.touchMoveX - self.touchStartX;
if (Math.abs(moveDistance) < self.options.minScrollDistance) {
return;
}
var delta = moveDistance > 0 ? -1 : 1;
self.loadAdjacentImage(delta);
self.isMoving = false;
}
}
},
/*
*加载相邻的一张图片
*/
loadAdjacentImage:function(delta) {
var targetIndex = this.currentImageIndex + delta;
if (targetIndex < 0 || targetIndex > this.options.totalImageCount) {
return;
}
this.imageEl.src = this.options.getImageSrcByIndex(targetIndex);
this.currentImageIndex += delta;
this.options.onloadingImage && this.options.onloadingImage();
},
/*
*判断图片是否处于缩放状态
*/
isImageZoomed: function() {
var boundingRectInfo = this.imageEl.getBoundingClientRect();
for(var key in boundingRectInfo){
if(['top','bottom','right','left'].indexOf(key) > -1){
if (boundingRectInfo[key] !== this.initBoundingRectInfo[key]) {
return true;
}
}
}
return false;
},
/*
*判断是否是触摸设备
*/
isSupportTouchEvents:function() {
return document.hasOwnProperty("ontouchstart");
}
}
</code>
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。