记录一下最近项目中用到的点击图片出现一个遮罩层,同时放大图片显示,移动端可双指缩放图片并单指拖拽图片.再次点击遮罩层透明区域,遮罩层消失
一.实现效果:
页面原图展示:
点击图片后:
二.代码实现:
1.html部分:
下面贴出主要 代码片段
。
<div id="outerdiv" style="position: fixed; top: 0; left: 0; background: rgba(0, 0, 0, 0.7); z-index:2; width:100%;height:100%;display: none;">
<div id="innerdiv" style="position: absolute;">
<img id="bigimg" style="border: 5px solid #fff;" src="" />
</div>
</div>
2.js部分(用到jQuery,所以记得引入哦):
这部分代码判断是移动端还是PC端,返回false为移动端,true为PC端.用它返回的值来区别是否移动端然后执行之后移动端事件.
下面展示一些 代码片段
。
$(function() {
$(".main-newsdate img").click(
function() {
var _this = $(this);//将当前的pimg元素作为_this传入函数
imgShow("#outerdiv", "#innerdiv", "#bigimg", _this);
//移动端手指移动事件,如果不需要移动端手指事件,这一部分内容可以不加,只要上面两行代码以及imgShow()事件
var eleImg = document.querySelector('#innerdiv');
var store = {
scale : 1
};
//定义移动端的初始位置
var position_top, position_left,pageX,pageY;
// 缩放事件的处理
//事件开始
eleImg.addEventListener('touchstart', function(event) {
event.preventDefault();//阻止默认事件,防止底部内容滚动
//在触屏设备下,要判断是单指还是多指操作,可以通过event.touches数组对象的长度判断。
var touches = event.touches;
var events = touches[0];//单指
var events2 = touches[1];//双指
if (touches.length == 1) { //单指操作
pageX = Number(events.pageX);
pageY = Number(events.pageY);
store.moveable = true;
var _obj = $('#innerdiv');
// .css获取的值是字符串
position_left = parseFloat(_obj.css('left')
.split('px'));
position_top = parseFloat(_obj.css('top')
.split('px'));
} else {
// 第一个触摸点的坐标
store.pageX = events.pageX;
store.pageY = events.pageY;
store.moveable = true;
if (events2) {
store.pageX2 = events2.pageX;
store.pageY2 = events2.pageY;
}
store.originScale = store.scale || 1;
}
},{ passive: false }); //passive: false必须加上,否则控制台报错
//开始移动
document.addEventListener('touchmove', function(event) {
event.preventDefault();//阻止默认事件,防止底部滚动
if (!store.moveable) {
return;
}
var touches = event.touches;
var events = touches[0];
var events2 = touches[1];
if (touches.length == 1) {
var pageX2 = Number(events.pageX);
var pageY2 = Number(events.pageY);
//控制图片移动
$('#innerdiv').css({
'top': position_top + pageY2 - pageY + 'px',
"left": position_left + pageX2 - pageX + 'px'
})
} else {
// 双指移动
if (events2) {
// 第2个指头坐标在touchmove时候获取
if (!store.pageX2) {
store.pageX2 = events2.pageX;
}
if (!store.pageY2) {
store.pageY2 = events2.pageY;
}
// 获取坐标之间的距离
var getDistance = function(start, stop) {
//用到三角函数
return Math.hypot(stop.x - start.x,
stop.y - start.y);
};
// 双指缩放比例计算
var zoom = getDistance({
x : events.pageX,
y : events.pageY
}, {
x : events2.pageX,
y : events2.pageY
}) / getDistance({
x : store.pageX,
y : store.pageY
}, {
x : store.pageX2,
y : store.pageY2
});
// 应用在元素上的缩放比例
var newScale = store.originScale * zoom;
// 最大缩放比例限制
if (newScale > 3) {
newScale = 3;
}
// 记住使用的缩放值
store.scale = newScale;
// 图像应用缩放效果
eleImg.style.transform = 'scale('
+ newScale + ')';
}
}
},{ passive: false });
document.addEventListener('touchend', function() {
store.moveable = false;
delete store.pageX2;
delete store.pageY2;
});
document.addEventListener('touchcancel', function() {
store.moveable = false;
delete store.pageX2;
delete store.pageY2;
});
});
//移动端手指页面结束
});
//遮罩层图片位置
function imgShow(outerdiv, innerdiv, bigimg, _this) {
//这是刚才判断是否PC端的函数事件
var flag = IsPC();
console.log(flag);
var src = _this.attr("src");//获取当前点击的pimg元素中的src属性
$(bigimg).attr("src", src);//设置#bigimg元素的src属性
/*获取当前点击图片的真实大小,并显示弹出层及大图*/
$("<img/>").attr("src", src).load(function() {
//注意在使用这种方法获取窗口高度和宽度的时候,
//务必在html页面最上方加上一句<!DOCTYPE html>,否则获取屏幕高度时会出问题
var windowW = $(window).width();//获取当前窗口宽度
var windowH = $(window).height();//获取当前窗口高度
var realWidth = this.width;//获取图片真实宽度
var realHeight = this.height;//获取图片真实高度
var imgWidth, imgHeight;
var scale = 0.8;//缩放尺寸,当图片真实宽度和高度大于窗口宽度和高度时进行缩放
if (realHeight > windowH * scale) {//判断图片高度
imgHeight = windowH * scale;//如大于窗口高度,图片高度进行缩放
imgWidth = imgHeight / realHeight * realWidth;//等比例缩放宽度
if (imgWidth > windowW * scale) {//如宽度扔大于窗口宽度
imgWidth = windowW * scale;//再对宽度进行缩放
}
} else if (realWidth > windowW * scale) {//如图片高度合适,判断图片宽度
imgWidth = windowW * scale;//如大于窗口宽度,图片宽度进行缩放
imgHeight = imgWidth / realWidth * realHeight;//等比例缩放高度
} else {//如果图片真实高度和宽度都符合要求,高宽不变
if (flag == false) {
imgWidth = realWidth;
imgHeight = realHeight;
} else if(realWidth>=1000){ //这里我怕图片太大又做了个判断
imgWidth = realWidth ;
imgHeight = realHeight;
}else{
imgWidth = realWidth *2 ;
imgHeight = realHeight *2;
}
}
$(bigimg).css("width", imgWidth);//以最终的宽度对图片缩放
var w = (windowW - imgWidth) / 2;//计算图片与窗口左边距
var h = (windowH - imgHeight) / 2;//计算图片与窗口上边距
$(innerdiv).css({
"top" : h,
"left" : w
});//设置#innerdiv的top和left属性
$(outerdiv).fadeIn("fast");//淡入显示#outerdiv及.pimg
});
$(outerdiv).click(function() {//再次点击淡出消失弹出层
$(this).fadeOut("fast");
});
};
注意点:
1.阻止默认行为是配合passive使用,否则控制台报错
默认使用passive:true提高滚动性能并减少崩溃,passive即顺从的,是指它顺从浏览器的默认行为。设置该属性的目的主要是为了在阻止事件默认行为导致的卡顿。如果我们阻止了这一默认行为,浏览器是无法预先知道的,必须等待事件监听器执行完成后,才知道要去阻止默认行为。等待监听器的执行是耗时的,,有些甚至耗时很明显,这样就会导致页面卡顿。即便监听器是个空函数,也会产生一定的卡顿,毕竟空函数的执行也会耗时。所以就有了passive属性,如果要阻止默认事件可以设置passive:false.
2…height()方法和.css(“height”)的区别:
返回值不同:.height()方法返回的是数字类型(20); .css(“height”)返回的是字符串类型(20px);
本文移动端手指缩放方法方法主要参考大佬的博文:
https://www.zhangxinxu.com/wordpress/2020/06/mobile-event-touches-zoom-sacle/