查看示例效果:

一、功能介绍

图片预览主要有以下几个功能点组成:监听图片点击事件,进入图片预览模式

自定义手势事件, (双指缩放,滑动,双击。。。)

监听图片手势事件,通过 transform-matrix 实现图片的各种变换;

二、实现方法

1、图片预览模式

图片预览即点击图片在页面中插入一个黑色全屏背景框并将图片居中显示。封装时,为了只对指定图片添加功能,可通过监听指定类名或添加某种属性的img标签监听;另外需在对背景框绑定点击事件,退出预览模式。一下是一个简单示例代码://点击图片进入预览

var $Dom = document.querySelector(".preview");

$Dom.onclick = function() {

var temp = this.src;

var objE = document.createElement("div");

objE.innerHTML = '

' +

'' +

'

';

document.body.appendChild(objE.children[0]);

//退出图片预览事件

var $bg = document.querySelector(".bgM");

$bg.onclick = function() {

var dm = document.querySelector(".bgM");

document.body.removeChild(dm);

}

//阻止事件冒泡

var $img = document.querySelector(".img-custom-img2");

$img.onclick = 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事件实现自定义双指缩放,单指滑动,双击事件,并通过事件属性传递相关参数,如缩放比例,滑动距离等,详细实现方式参考这篇博客:请参考此博文:https://www.cnblogs.com/pangys/p/9119845.html 这里只大概说明;当触发touch事件的时候,会生成一个TouchEvent对象,我们可通过其属性e.touches.length来判断是否多点触控,通过e.touches[index].pageX,e.touches[index].pageY获取去触点坐标,通过e.target获取dom节点;

这里为了方便,直接监听document事件然后对目标元素触发事件,实际也可以直接对img监听事件,然后分别处理;

(1)手势事件监听touchstart事件,若e.touches.length>=2,为双指事件,获取触点坐标(触点坐标-目标元素.offsetLeft/Top)计算两个点中点 添加到事件属性中,改变相关状态,触发gesturestart事件;

监听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 = Date.now() - now; //计算两次点击时间差

now = Date.now();

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 = scale.toFixed(2);

gesturechange.rotation = rotation.toFixed(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,

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方向缩放ad

移动ef

(1) 获取目标元素及相关参数,绑定事件var $imgs = document.querySelector("#img_scan");

var clientWidth = document.body.clientWidth; //窗口宽

var clientHeight = document.body.clientHeight; //窗口高

var imgWidth = parseInt(window.getComputedStyle($imgs).width); //图片宽

var imgHeight = parseInt(window.getComputedStyle($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;

$imgs.style.transformOrigin = 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(",");

$imgs.style.transform = "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 拖动图片,需考虑是否在可拖动范围if (!maxSwipeLeft || !maxSwipeRight || !maxSwipeTop || !maxSwipeBottom) return;

if (event.distance[0] > 0 && maxSwipeLeft < tMatrix[4]) return;

if (event.distance[0] < 0 && maxSwipeRight < -tMatrix[4]) return;

if (event.distance[1] > 0 && maxSwipeTop < tMatrix[5]) return;

if (event.distance[1] < 0 && maxSwipeBottom < -tMatrix[5]) return;

tMatrix[4] = tMatrix[4] + parseInt(event.distance[0]);

tMatrix[5] = tMatrix[5] + parseInt(event.distance[1]);

var temp = tMatrix.join(",");

$imgs.style.transform = "matrix(" + temp + ")";

break;

复制代码

(5)监听 doubleTouch 实现双击点缩放case "doubleTouch":

originLast = event.position;

$imgs.style.transformOrigin = event.position[0] + "px " + event.position[1] + "px";

tMatrix[0] = 2;

tMatrix[3] = 2;

var temp = tMatrix.join(",");

$imgs.style.transform = "matrix(" + temp + ")";

maxMove();

break;复制代码

(6)监听 oneTouch 实现退出预览

case "oneTouch":

var $bg = document.querySelector(".bgM");

document.body.removeChild($bg);

break;

复制代码

h5 img js 点击图片放大_H5实现移动端图片预览:手势缩放, 手势拖动,双击放大......相关推荐

  1. pdfh5.js 基于pdf.js和jQuery,web/h5/移动端PDF预览手势缩放插件。

    pdfh5.js 基于pdf.js和jQuery,web/h5/移动端PDF预览手势缩放插件. 注意:本地绝对路径地址不能加载,跨域问题用代理或者服务端解决. svg模式渲染存在缺陷,只能渲染普通pd ...

  2. 手机端html5展示pdf,pdf.js移动端展示预览打开pdf-pdfh5.js

    pdf.js移动端展示预览打开pdf-pdfh5.js 本插件基于pdf.js和jQuery,可手势捏合缩放,支持懒加载(即分段加载). 2019.07.18更新:增加npm install pdfh ...

  3. 解决:PHP 阿里云OSS访问图片地址默认下载而不是在线预览

    修改文件--保存后再上传图片就可以在线预览了 将阿里云图片属性改为"image/jpg" 也可直接替换下方文件,已经是修改后的了,新上传的图片则不会出现不可在线预览了 image/ ...

  4. H5无插件实现实时海康、大华摄像头网页预览

    H5无插件实现实时海康.大华摄像头网页预览 前景概述 功能特点 效果 http接口管理 流列表接口 实现过程 解决的问题 前景概述 最近项目中需要用到"网页实时预览网络摄像头"功能 ...

  5. 安卓开发仿微信图片拖拽_Android仿微信朋友圈图片浏览器(支持图片手势缩放,拖动)...

    [实例简介] Android仿微信朋友圈图片浏览器(支持图片手势缩放,拖动) [实例截图] [核心代码] ImageDemo-2014-02-18 └── ImageDemo-2014-02-18 ├ ...

  6. php主页显示商品预览图代码,jQuery实现鼠标滑过商品小图片上显示对应大图商品页预览功能...

    这次给大家带来jQuery实现鼠标滑过商品小图片上显示对应大图商品页预览功能,jQuery实现鼠标滑过商品小图片上显示对应大图商品页预览功能的注意事项有哪些,下面就是实战案例,一起来看一下. 1 . ...

  7. python与html交互实现图片上传_python 实现上传图片并预览的3种方法(推荐)

    在常见的用户注册页面,需要用户在本地选择一张图片作为头像,并同时预览. 常见的思路有两种:一是将图片上传至服务器的临时文件夹中,并返回该图片的url,然后渲染在html页面:另一种思路是,直接在本地内 ...

  8. h5 img js 点击图片放大_5分钟学会h5生成图片海报!

    生成海报这个功能很实用,之前我们学过小程序生成海报的方法,今天我们来学h5生成海报. 基本原理:其实就是把你html+css写的样式转换成图片下载. 如何实现的 首先我们需要引入下面两个js插件 原理 ...

  9. 移动端查看预览图片放大缩小

    方法一 之前介绍过一款 移动端vue适用的插件大全 https://blog.csdn.net/MtangEr/article/details/85339092 里边有一篇是查看图片放大缩小的 htt ...

最新文章

  1. Linux上调整sshd进程的优先级
  2. Spring容器初始化实现V3 版本
  3. Effective C++学习第一天
  4. RedisTemplate设置过期时间
  5. mysql和python先学哪个_Python数据库操作 初识mysql和mysql基本操作#学习猿地
  6. java表格选中事件_表格中删除选中的操作
  7. 学习之苦也正是学习之甜------知识的本质
  8. 基于Python实现的基金交易系统
  9. 2021年末大盘点。IT行业那些薪资高前景好的岗位,你知道几个?
  10. 神盾局第二季麦克机器人_神盾局特工第四季分集剧情介绍(1-22集)大结局
  11. 基带混用导致信号弱?iPhone网络差的原因及修复,望周知
  12. Openlayers 快速上手教程
  13. 社会生活中的十二条著名法则
  14. BLE协议栈 – SM
  15. CET-4 week8# 细枝末节
  16. winform-htmlEditor窗体超文本编辑器
  17. Python求数组的自然间断点
  18. autojs,按键精灵等辅助,快手极速版代码分享(真实可运行)
  19. 推荐 7 个热门电商 GitHub 项目
  20. String类的intern

热门文章

  1. 转载给ffmpeg入门级:我的第一个调用FFmpeg库的程序出炉
  2. 解决:Command line is too long. In order to reduce its length classpath file can be used.
  3. 分页插件pageHelpler的使用(ssm框架中)服务器端分页
  4. 时间,数字 ,字符串之间的转换
  5. 7.11牛客题(指针)
  6. Oracle的逆向工程generatorConfig
  7. django学习之路
  8. FPGA 状态机设计
  9. 重启php-fpm的方法
  10. 搜索 由浅入深 之一 水题