js实现移动端图片预览:手势缩放,手势拖动,双击放大...

js实现移动端图⽚预览:⼿势缩放,⼿势拖动,双击放⼤...查看⽰例效果:
⼀、功能介绍
  图⽚预览主要有以下⼏个功能点组成:
监听图⽚点击事件,进⼊图⽚预览模式
⾃定义⼿势事件, (双指缩放,滑动,双击。。。)
监听图⽚⼿势事件,通过 transform-matrix 实现图⽚的各种变换;
⼆、实现⽅法
1、图⽚预览模式
图⽚预览即点击图⽚在页⾯中插⼊⼀个⿊⾊全屏背景框并将图⽚居中显⽰。封装时,为了只对指定图⽚添加功能,可通过监听指定类名或添加某种属性的img标签监听;另外需在对背景框绑定点击事件,退出预览模式。⼀下是⼀个简单⽰例代码:
//点击图⽚进⼊预览
var $Dom = document.querySelector(".preview");
$lick = function() {
var temp = this.src;
var objE = ateElement("div");
objE.innerHTML = '<div class="bgM" >' +
'<img src="'+temp+'"  id="img_scan" class="img-custom-img2"/>' +
'</div>';
document.body.appendChild(objE.children[0]);
//退出图⽚预览事件
var $bg = document.querySelector(".bgM");
$bg.onclick = function() {
var dm = document.querySelector(".bgM");
veChild(dm);
}促销品管理
//阻⽌事件冒泡
var $img = document.querySelector(".img-custom-img2");
$lick = function(event) {
event.stopPropagation();
大家小事
}
}
复制代码
css样式参考
.
bgM{
width: 100%;
height: 100%;
position: absolute;
top: 0;left: 0;right: 0;bottom: 0;
z-index: 1000;
background-color: rgba(0,0,0,0.85);
overflow: hidden;
}
.bgM img{
width: 100%;
max-height:100%;
position: absolute;
top: 0;left: 0;right: 0;bottom: 0;
z-index: 1001;
margin: auto;
}
复制代码
2、⾃定义⼿势事件
当触发touch事件的时候,会⽣成⼀个TouchEvent对象,我们可通过其属性e.touches.length来判断是否多点触控,通过
触点坐标,通过e.target获取dom节点;
这⾥为了⽅便,直接监听document事件然后对⽬标元素触发事件,实际也可以直接对img监听事件,然后分别处理;
(1)⼿势事件
监听touchstart事件,若e.touches.length>=2,为双指事件,获取触点坐标(触点坐标-⽬标元素.offsetLeft/Top)计算两个点中点添加到事件属性中,改变相关状态,触发gesturestart事件;
pctools5.0
监听touchmove事件,若e.touches.length>=2,获当前取触点坐标和gesturestart坐标,计算出缩放⽐例及⾓度,触发
gesturechange事件;
监听touchend事件,根据前⾯事件记录的状态触发结束gestureend事件;
(2)滑动事件
监听touchstart事件,若e.touches.length<2,为单指事件,获取触点坐标(触点坐标-⽬标元素.offsetLeft/Top)添加到事件属性中,记录事件状态;
监听touchmove事件,若e.touches.length<2,获当前取触点坐标和上⼀步坐标,计算出移动距离添加到事件属性中,触发
swipeMove事件;
(3)双击事件
监听touchstart事件,若e.touches.length<2,为单指事件,获取触点坐标(触点坐标-⽬标元素.offsetLeft/Top)添加到事件属性中,获取当前时间挫记录到相关变量中,计算本次时间戳与上次事件时间戳之差,若时间差范围在指定范围(0~250)则触发doubleTouch事件;
(4)单击事件
监听touchstart事件,使⽤延时器450ms触发单击事件,若在450ms⽆其他事件则触发单击事件
参考代码:
var isTouch = false;
var isDoubleTouch = false; //是否为多触点
var start = []; //存放触点坐标
var now, delta; //当前时间,两次触发事件时间差
var timer = null; //计时器,触发单击事件
var startPosition, movePosition, endPosition; //滑动起点,移动,结束点坐标
//事件声明华大影院
//事件声明
var gesturestart = new CustomEvent('gesturestart');
var gesturechange = new CustomEvent('gesturechange');
var gestureend = new CustomEvent('gestureend');
var swipeMove = new CustomEvent('swipeMove');
var doubleTouch = new CustomEvent("doubleTouch");
var oneTouch = new CustomEvent("oneTouch");
//监听touchstart事件
document.addEventListener('touchstart', function(e) {
if (e.touches.length >= 2) { //判断是否有两个点在屏幕上
isDoubleTouch = true;
start = e.touches; //得到第⼀组两个点
立体交叉桥var screenMinPoint = getMidpoint(start[0], start[1]); //获取两个触点中⼼坐标
gesturestart.midPoint = [screenMinPoint[0] - e.target.offsetLeft, screenMinPoint[1] - e.target.offsetTop]; //获取中⼼点坐标相对⽬标元素坐标            e.target.dispatchEvent(gesturestart);
} else {
delta = w() - now; //计算两次点击时间差
now = w();
startPosition = [e.touches[0].pageX, e.touches[0].pageY];
if (delta > 0 && delta <= 250) { //双击事件
clearTimeout(timer);
doubleTouch.position = [e.touches[0].pageX - e.target.offsetLeft, e.touches[0].pageY - e.target.offsetTop];
e.target.dispatchEvent(doubleTouch);
} else { //滑动事件
timer = setTimeout(function(){
e.target.dispatchEvent(oneTouch);//单击事件
},450)
}
isTouch = true;
腐蚀疲劳
}
}, false);
//监听touchmove事件
document.addEventListener('touchmove', function(e) {
clearTimeout(timer);
if (e.touches.length >= 2 && isDoubleTouch) { //⼿势事件
var now = e.touches; //得到第⼆组两个点
var scale = getDistance(now[0], now[1]) / getDistance(start[0], start[1]); //得到缩放⽐例
var rotation = getAngle(now[0], now[1]) - getAngle(start[0], start[1]); //得到旋转⾓度差
gesturechange.scale = Fixed(2);
e.target.dispatchEvent(gesturechange);
} else if (isTouch) {
movePosition = [e.touches[0].pageX, e.touches[0].pageY];
endPosition = movePosition;
movePosition = [movePosition[0] - startPosition[0], movePosition[1] - startPosition[1]];
startPosition = [e.touches[0].pageX, e.touches[0].pageY];
swipeMove.distance =[movePosition[0].toFixed(2) , movePosition[1].toFixed(2)];
e.target.dispatchEvent(swipeMove);
}
}, false);
//监听touchend事件
document.addEventListener('touchend', function(e) {
if (isDoubleTouch) {
isDoubleTouch = false;
gestureend.position = endPosition;
e.target.dispatchEvent(gestureend);
};
}, false);
/*
* 两点的距离
*/
function getDistance(p1, p2) {
var x = p2.pageX - p1.pageX,
var x = p2.pageX - p1.pageX,
y = p2.pageY - p1.pageY;
return Math.sqrt((x * x) + (y * y));
};
/*
* 两点的夹⾓
*/
function getAngle(p1, p2) {
var x = p1.pageX - p2.pageX,
y = p1.pageY - p2.pageY;
return Math.atan2(y, x) * 180 / Math.PI;
};
/*
* 获取中点
*/
function getMidpoint(p1, p2) {
var x = (p1.pageX + p2.pageX) / 2,
y = (p1.pageY + p2.pageY) / 2;
return [x, y];
}
复制代码
三、图⽚的变换
对于图⽚的每次操作都需在上⼀次操作的基础上进⾏叠加,如果直接使⽤width,top,left或scale,translate等css样式需要每次都记录当前图⽚状态的全部参数,⽽且计算较多,这⾥考虑使⽤transform-matrix实现图⽚的基本变换,这样只需创建⼀个数组作为变换矩阵,每次操作直接在当前变换矩阵上修改相关参数即可实现图像的变换:
transform-matrix :可配置[a,b,c,d,e,f]6个参数,如下图所⽰,x和y是初始的坐标,x’ 和y’则是通过矩阵变换后得到新的坐标。
变换矩阵,对原先的坐标施加变换,就能得到新的坐标了。依据矩阵变换规则即可得到: x’=ax+cy+e y’=bx+dy+f。
变换x⽅向y⽅向
缩放a d
移动e f
(1) 获取⽬标元素及相关参数,绑定事件
var $imgs = document.querySelector("#img_scan");
var clientWidth = document.body.clientWidth; //窗⼝宽
var clientHeight = document.body.clientHeight; //窗⼝⾼
var imgWidth = ComputedStyle($imgs).width); //图⽚宽
var imgHeight = ComputedStyle($imgs).height); //图⽚⾼
$imgs.addEventListener('gesturestart', gesturef, false);
$imgs.addEventListener('gesturechange', gesturef, false);
$imgs.addEventListener('gestureend', gesturef, false);
$imgs.addEventListener('swipeMove', gesturef, false);
$imgs.addEventListener('doubleTouch', gesturef, false);
$imgs.addEventListener('oneTouch', gesturef, false);
var tMatrix = [1, 0, 0, 1, 0, 0]; //x缩放,⽆,⽆,y缩放,x平移,y平移
var originLast, maxSwipeLeft, maxSwipeRight, maxSwipeTop, maxSwipeBottom; //上下左右可拖动距离
复制代码
(2)监听 gesturestart 设置变换中⼼
case "gesturestart":
var x = event.midPoint[0];
var y = event.midPoint[1];
originLast = event.midPoint;
$ansformOrigin = x + "px " + y + "px";
break;
复制代码
(2)监听 gesturechange 进⾏缩放变换,这⾥设置了缩放范围为0.5 ~ 3;
case "gesturechange":
var sc = parseFloat(event.scale);
tMatrix[0] = tMatrix[0] + sc - 1 > 0.5 && tMatrix[0] + sc - 1 < 3 ? tMatrix[0] + sc - 1 : tMatrix[0];
tMatrix[3] = tMatrix[3] + sc - 1 > 0.5 && tMatrix[3] + sc - 1 < 3 ? tMatrix[3] + sc - 1 : tMatrix[3];
var temp = tMatrix.join(",");
$ansform = "matrix(" + temp + ")";
break;
复制代码
(3)监听 gestureend 获取移动边界范围边界
case "gestureend":
maxMove();
break;
复制代码
可移动边界范围的计算:
对于图⽚中的任意点可拖动范围都是相同的,那么以缩放中⼼点来计算,如下图所⽰,对于图⽚中的缩放中⼼点p,有缩放后距离边距的距离,可移动的范围均为 缩放后增加或减少的距离 - (缩放中⼼点距离图⽚边缘的距离),即 | 缩放⽐例 - 1 | * p点距离边缘的距离;
代码如下:
function maxMove(){
//最⼤可拖动范围
var sca = tMatrix[0];
maxSwipeLeft = Math.abs(sca - 1) * originLast[0];
maxSwipeRight = Math.abs(sca - 1) * (imgWidth - originLast[0]);
maxSwipeTop = Math.abs(sca - 1) * originLast[1];
maxSwipeBottom = Math.abs(sca - 1) * (imgHeight - originLast[1]);
}
复制代码
(4)监听 swipeMove 拖动图⽚,需考虑是否在可拖动范围

本文发布于:2024-09-21 12:41:08,感谢您对本站的认可!

本文链接:https://www.17tex.com/xueshu/124859.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:事件   坐标   触点
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议