手机端图片放大缩小旋转
2020-01-13 本文已影响0人
TianTongBo
效果图
image.png
(function() {
'use strict';
var definePinchZoom = function($) {
var PinchZoom = function(el, options) {
this.el = $(el);
this.zoomFactor = 1;
this.lastScale = 1;
this.offset = {
x: 0,
y: 0
};
this.options = $.extend({}, this.defaults, options);
this.setupMarkup();
this.bindEvents();
this.update();
this.enable();
},
sum = function(a, b) {
return a + b;
},
isCloseTo = function(value, expected) {
return value > expected - 0.01 && value < expected + 0.01;
};
PinchZoom.prototype = {
defaults: {
tapZoomFactor: 2,
zoomOutFactor: 1.3,
animationDuration: 300,
maxZoom: 4,
minZoom: 0.5,
lockDragAxis: false,
use2d: true,
zoomStartEventName: 'pz_zoomstart',
zoomEndEventName: 'pz_zoomend',
dragStartEventName: 'pz_dragstart',
dragEndEventName: 'pz_dragend',
doubleTapEventName: 'pz_doubletap'
},
handleDragStart: function(event) {
this.el.trigger(this.options.dragStartEventName);
this.stopAnimation();
this.lastDragPosition = false;
this.hasInteraction = true;
this.handleDrag(event);
},
handleDrag: function(event) {
if (this.zoomFactor > 1.0) {
var touch = this.getTouches(event)[0];
this.drag(touch, this.lastDragPosition);
this.offset = this.sanitizeOffset(this.offset);
this.lastDragPosition = touch;
}
},
handleDragEnd: function() {
this.el.trigger(this.options.dragEndEventName);
this.end();
},
handleZoomStart: function(event) {
this.el.trigger(this.options.zoomStartEventName);
this.stopAnimation();
this.lastScale = 1;
this.nthZoom = 0;
this.lastZoomCenter = false;
this.hasInteraction = true;
},
handleZoom: function(event, newScale) {
var touchCenter = this.getTouchCenter(this.getTouches(event)),
scale = newScale / this.lastScale;
this.lastScale = newScale;
this.nthZoom += 1;
if (this.nthZoom > 3) {
this.scale(scale, touchCenter);
this.drag(touchCenter, this.lastZoomCenter);
}
this.lastZoomCenter = touchCenter;
},
handleZoomEnd: function() {
this.el.trigger(this.options.zoomEndEventName);
this.end();
},
handleDoubleTap: function(event) {
var center = this.getTouches(event)[0],
zoomFactor = this.zoomFactor > 1 ? 1 : this.options.tapZoomFactor,
startZoomFactor = this.zoomFactor,
updateProgress = (function(progress) {
this.scaleTo(startZoomFactor + progress * (zoomFactor - startZoomFactor), center);
}).bind(this);
if (this.hasInteraction) {
return;
}
if (startZoomFactor > zoomFactor) {
center = this.getCurrentZoomCenter();
}
this.animate(this.options.animationDuration, updateProgress, this.swing);
this.el.trigger(this.options.doubleTapEventName);
},
sanitizeOffset: function(offset) {
var maxX = (this.zoomFactor - 1) * this.getContainerX(),
maxY = (this.zoomFactor - 1) * this.getContainerY(),
maxOffsetX = Math.max(maxX, 0),
maxOffsetY = Math.max(maxY, 0),
minOffsetX = Math.min(maxX, 0),
minOffsetY = Math.min(maxY, 0);
return {
x: Math.min(Math.max(offset.x, minOffsetX), maxOffsetX),
y: Math.min(Math.max(offset.y, minOffsetY), maxOffsetY)
};
},
scaleTo: function(zoomFactor, center) {
this.scale(zoomFactor / this.zoomFactor, center);
},
scale: function(scale, center) {
scale = this.scaleZoomFactor(scale);
this.addOffset({
x: (scale - 1) * (center.x + this.offset.x),
y: (scale - 1) * (center.y + this.offset.y)
});
},
scaleZoomFactor: function(scale) {
var originalZoomFactor = this.zoomFactor;
this.zoomFactor *= scale;
this.zoomFactor = Math.min(this.options.maxZoom, Math.max(this.zoomFactor, this.options.minZoom));
return this.zoomFactor / originalZoomFactor;
},
drag: function(center, lastCenter) {
if (lastCenter) {
if (this.options.lockDragAxis) {
if (Math.abs(center.x - lastCenter.x) > Math.abs(center.y - lastCenter.y)) {
this.addOffset({
x: -(center.x - lastCenter.x),
y: 0
});
} else {
this.addOffset({
y: -(center.y - lastCenter.y),
x: 0
});
}
} else {
this.addOffset({
y: -(center.y - lastCenter.y),
x: -(center.x - lastCenter.x)
});
}
}
},
getTouchCenter: function(touches) {
return this.getVectorAvg(touches);
},
getVectorAvg: function(vectors) {
return {
x: vectors.map(function(v) {
return v.x;
}).reduce(sum) / vectors.length,
y: vectors.map(function(v) {
return v.y;
}).reduce(sum) / vectors.length
};
},
addOffset: function(offset) {
this.offset = {
x: this.offset.x + offset.x,
y: this.offset.y + offset.y
};
},
sanitize: function() {
if (this.zoomFactor < this.options.zoomOutFactor) {
this.zoomOutAnimation();
} else if (this.isInsaneOffset(this.offset)) {
this.sanitizeOffsetAnimation();
}
},
isInsaneOffset: function(offset) {
var sanitizedOffset = this.sanitizeOffset(offset);
return sanitizedOffset.x !== offset.x || sanitizedOffset.y !== offset.y;
},
sanitizeOffsetAnimation: function() {
var targetOffset = this.sanitizeOffset(this.offset),
startOffset = {
x: this.offset.x,
y: this.offset.y
},
updateProgress = (function(progress) {
this.offset.x = startOffset.x + progress * (targetOffset.x - startOffset.x);
this.offset.y = startOffset.y + progress * (targetOffset.y - startOffset.y);
this.update();
}).bind(this);
this.animate(this.options.animationDuration, updateProgress, this.swing);
},
zoomOutAnimation: function() {
var startZoomFactor = this.zoomFactor,
zoomFactor = 1,
center = this.getCurrentZoomCenter(),
updateProgress = (function(progress) {
this.scaleTo(startZoomFactor + progress * (zoomFactor - startZoomFactor), center);
}).bind(this);
this.animate(this.options.animationDuration, updateProgress, this.swing);
},
updateAspectRatio: function() {
this.setContainerY(this.getContainerX() / this.getAspectRatio());
},
getInitialZoomFactor: function() {
return this.container[0].offsetWidth / this.el[0].offsetWidth;
},
getAspectRatio: function() {
return this.el[0].offsetWidth / this.el[0].offsetHeight;
},
getCurrentZoomCenter: function() {
var length = this.container[0].offsetWidth * this.zoomFactor,
offsetLeft = this.offset.x,
offsetRight = length - offsetLeft - this.container[0].offsetWidth,
widthOffsetRatio = offsetLeft / offsetRight,
centerX = widthOffsetRatio * this.container[0].offsetWidth / (widthOffsetRatio + 1),
height = this.container[0].offsetHeight * this.zoomFactor,
offsetTop = this.offset.y,
offsetBottom = height - offsetTop - this.container[0].offsetHeight,
heightOffsetRatio = offsetTop / offsetBottom,
centerY = heightOffsetRatio * this.container[0].offsetHeight / (heightOffsetRatio + 1);
if (offsetRight === 0) {
centerX = this.container[0].offsetWidth;
}
if (offsetBottom === 0) {
centerY = this.container[0].offsetHeight;
}
return {
x: centerX,
y: centerY
};
},
canDrag: function() {
return !isCloseTo(this.zoomFactor, 1);
},
getTouches: function(event) {
var position = this.container.offset();
return Array.prototype.slice.call(event.touches).map(function(touch) {
return {
x: touch.pageX - position.left,
y: touch.pageY - position.top
};
});
},
animate: function(duration, framefn, timefn, callback) {
var startTime = new Date().getTime(),
renderFrame = (function() {
if (!this.inAnimation) {
return;
}
var frameTime = new Date().getTime() - startTime,
progress = frameTime / duration;
if (frameTime >= duration) {
framefn(1);
if (callback) {
callback();
}
this.update();
this.stopAnimation();
this.update();
} else {
if (timefn) {
progress = timefn(progress);
}
framefn(progress);
this.update();
requestAnimationFrame(renderFrame);
}
}).bind(this);
this.inAnimation = true;
requestAnimationFrame(renderFrame);
},
stopAnimation: function() {
this.inAnimation = false;
},
swing: function(p) {
return -Math.cos(p * Math.PI) / 2 + 0.5;
},
getContainerX: function() {
return this.container[0].offsetWidth;
},
getContainerY: function() {
return this.container[0].offsetHeight;
},
setContainerY: function(y) {
return this.container.height(y);
},
setupMarkup: function() {
this.container = $('<div class="pinch-zoom-container"></div>');
this.el.before(this.container);
this.container.append(this.el);
this.container.css({
'overflow': 'hidden',
'position': 'relative',
});
this.el.css({
'-webkit-transform-origin': '0% 0%',
'-moz-transform-origin': '0% 0%',
'-ms-transform-origin': '0% 0%',
'-o-transform-origin': '0% 0%',
'transform-origin': '0% 0%',
'position': 'absolute'
});
},
end: function() {
this.hasInteraction = false;
this.sanitize();
this.update();
if(this.zoomFactor>1.0){
this.el.parent().parent().css({
"background":"rgba(0,0,0,.3)"
});
}else if(this.zoomFactor<=1.0) {
this.el.parent().parent().css({
"background":"#ffffff"
});
}
},
bindEvents: function() {
detectGestures(this.container.get(0), this);
$(window).on('resize', this.update.bind(this));
$(this.el).find('img').on('load', this.update.bind(this));
},
update: function() {
if (this.updatePlaned) {
return;
}
this.updatePlaned = true;
setTimeout((function() {
this.updatePlaned = false;
this.updateAspectRatio();
var zoomFactor = this.getInitialZoomFactor() * this.zoomFactor,
offsetX = -this.offset.x / zoomFactor,
offsetY = -this.offset.y / zoomFactor,
transform3d = 'scale3d(' + zoomFactor + ', ' + zoomFactor + ',1) ' + 'translate3d(' + offsetX + 'px,' + offsetY + 'px,0px)',
transform2d = 'scale(' + zoomFactor + ', ' + zoomFactor + ') ' + 'translate(' + offsetX + 'px,' + offsetY + 'px)',
removeClone = (function() {
if (this.clone) {
this.clone.remove();
delete this.clone;
}
}).bind(this);
if (!this.options.use2d || this.hasInteraction || this.inAnimation) {
this.is3d = true;
removeClone();
this.el.css({
'-webkit-transform': transform3d,
'-o-transform': transform2d,
'-ms-transform': transform2d,
'-moz-transform': transform2d,
'transform': transform3d
});
} else {
if (this.is3d) {
this.clone = this.el.clone();
this.clone.css('pointer-events', 'none');
this.clone.appendTo(this.container);
setTimeout(removeClone, 200);
}
this.el.css({
'-webkit-transform': transform2d,
'-o-transform': transform2d,
'-ms-transform': transform2d,
'-moz-transform': transform2d,
'transform': transform2d
});
this.is3d = false;
}
}).bind(this), 0);
},
enable: function() {
this.enabled = true;
},
disable: function() {
this.enabled = false;
}
};
var detectGestures = function(el, target) {
var interaction = null,
fingers = 0,
lastTouchStart = null,
startTouches = null,
setInteraction = function(newInteraction, event) {
if (interaction !== newInteraction) {
if (interaction && !newInteraction) {
switch (interaction) {
case "zoom":
target.handleZoomEnd(event);
break;
case 'drag':
target.handleDragEnd(event);
break;
}
}
switch (newInteraction) {
case 'zoom':
target.handleZoomStart(event);
break;
case 'drag':
target.handleDragStart(event);
break;
}
}
interaction = newInteraction;
},
updateInteraction = function(event) {
if (fingers === 2) {
setInteraction('zoom');
} else if (fingers === 1 && target.canDrag()) {
setInteraction('drag', event);
} else {
setInteraction(null, event);
}
},
targetTouches = function(touches) {
return Array.prototype.slice.call(touches).map(function(touch) {
return {
x: touch.pageX,
y: touch.pageY
};
});
},
getDistance = function(a, b) {
var x, y;
x = a.x - b.x;
y = a.y - b.y;
return Math.sqrt(x * x + y * y);
},
calculateScale = function(startTouches, endTouches) {
var startDistance = getDistance(startTouches[0], startTouches[1]),
endDistance = getDistance(endTouches[0], endTouches[1]);
return endDistance / startDistance;
},
cancelEvent = function(event) {
event.stopPropagation();
event.preventDefault();
},
detectDoubleTap = function(event) {
var time = (new Date()).getTime();
if (fingers > 1) {
lastTouchStart = null;
}
if (time - lastTouchStart < 300) {
cancelEvent(event);
target.handleDoubleTap(event);
switch (interaction) {
case "zoom":
target.handleZoomEnd(event);
break;
case 'drag':
target.handleDragEnd(event);
break;
}
}
if (fingers === 1) {
lastTouchStart = time;
}
},
firstMove = true;
el.addEventListener('touchstart', function(event) {
if (target.enabled) {
firstMove = true;
fingers = event.touches.length;
detectDoubleTap(event);
}
});
el.addEventListener('touchmove', function(event) {
if (target.enabled) {
if (firstMove) {
updateInteraction(event);
if (interaction) {
cancelEvent(event);
}
startTouches = targetTouches(event.touches);
} else {
switch (interaction) {
case 'zoom':
target.handleZoom(event, calculateScale(startTouches, targetTouches(event.touches)));
break;
case 'drag':
target.handleDrag(event);
break;
}
if (interaction) {
cancelEvent(event);
target.update();
}
}
firstMove = false;
}
});
el.addEventListener('touchend', function(event) {
if (target.enabled) {
fingers = event.touches.length;
updateInteraction(event);
}
});
};
return PinchZoom;
};
if (typeof define !== 'undefined' && define.amd) {
define(['jquery'], function($) {
return definePinchZoom($);
});
} else {
window.RTP = window.RTP || {};
window.RTP.PinchZoom = definePinchZoom(window.$);
}
}).call(this);
var bsFlag=0;
imgFD($('.uploadImg'))
function imgFD(eleImg) {
var html=`<div id="move_part" class="big_img_box" >
<div class="btns btnsT" id="btnsT"><span class="close iconfont icon-cuohao"></span><span class="xuanzhuan iconfont icon-xuanzhuan" id ="xzID"></span></div>
<div class="btns btnsR hide" id="btnsR"><span class="close iconfont icon-cuohao"></span><span class="xuanzhuan iconfont icon-xuanzhuan" id ="xzID1"></span></div>
<div class="btns btnsB hide" id="btnsB"><span class="close iconfont icon-cuohao"></span><span class="xuanzhuan iconfont icon-xuanzhuan" id ="xzID2"></span></div>
<div class="btns btnsL hide" id="btnsL"><span class="close iconfont icon-cuohao"></span><span class="xuanzhuan iconfont icon-xuanzhuan" id ="xzID3"></span></div>
<img id="showImg" draggable="false" src="" alt="">
</div>`
$("body").append(html);
$(".big_img_box").css({position: "fixed",left: "0.3rem",top: "1rem",right: '0.3rem',background: "#fff",padding: "15px",display:"none","z-index": 1000,});
$(".big_img_box img").css({width: "100%",height: "100%", transform: "none",});
$(".btnsT").css({position: "absolute",right: 0,left:0,top: "-0.2rem",margin:"0 auto",display:"flex","justify-content":"center","align-items": "center","z-index": 2});
$(".btnsR").css({position: "absolute",right: "-1rem",bottom:0,top:0 ,margin:"auto 0",display:"flex","justify-content":"center","align-items": "center",transform : 'rotate('+90%360+'deg)',"z-index": 2});
$(".btnsB").css({position: "absolute",right: 0,left:0,bottom: "-0.2rem",margin:"0 auto",display:"flex","justify-content":"center","align-items": "center",transform : 'rotate('+180%360+'deg)',"z-index": 2});
$(".btnsL").css({position: "absolute",left:"-1rem",bottom:0,top: 0,margin:"auto 0",display:"flex","justify-content":"center","align-items": "center",transform : 'rotate('+-90%360+'deg)',"z-index": 2});
$(".close").css({color: "#fff",background: "rgba(0,0,0,.3)","font-size": "0.3rem",display:"inline-block","justify-content":"center","align-items": "center",cursor: "pointer",width: "0.7rem",height: "0.7rem","border-radius": "50%","line-height":"0.7rem" ,"text-align":"center" });
$(".xuanzhuan").css({marginLeft:".8rem",color: "#fff",background: "rgba(0,0,0,.3)","font-size": "0.3rem",display:"inline-block","justify-content":"center","align-items": "center",cursor: "pointer",width: "0.7rem",height: "0.7rem","border-radius": "50%","line-height":"0.7rem" ,"text-align":"center" });
var timer = null;
eleImg.on("click", function(e) {
// $('body').css({'position':'fixed','overflow':'hidden'})
bsFlag=1
var img = $(this);
clearInterval(timer);
var target = e.srcElement ? e.srcElement : e.target;
// var src=e.srcElement.src;
var src = target.src;
var realWidth=0;//真实的宽度
var realHeight=0;//真实的高度
var setWidth=0;//重新设置图片的宽度
var setHeight=0;//重新设置图片的高度
// if(src.slice(-6).indexOf('.') == -1) {
// return;
// }
$('.big_img_box img')[0].src = src;
$("<img/>").attr("src", $(img).attr("src")).load(function () {
realWidth = this.width;
realHeight = this.height;
var imgNew = $("<img/>");
//如果真实的宽度大于规定的宽度就按照相应的规则处理
if(realWidth>=document.documentElement.clientWidth/1.2){
$(imgNew).css({"width":document.documentElement.clientWidth/1.2+"px","height": document.documentElement.clientWidth/1.2*realHeight/realWidth+"px"});
}
else{//如果小于浏览器的宽度按照原尺寸显示
$(imgNew).css("width",realWidth+'px').css("height",realHeight+'px');
}
setWidth = $(imgNew).width();
setHeight = $(imgNew).height();
console.log(setWidth,setHeight)
if(setHeight>=document.documentElement.clientHeight/1.5){
setWidth =document.documentElement.clientHeight/1.5*setWidth/setHeight;
setHeight=document.documentElement.clientHeight/1.5;
}
console.log(setWidth,setHeight)
var width = setWidth/20;
var height =setHeight/20;
var h0 = 0;
var y0 = 0;
timer = setInterval(function() {
if(parseInt(h0) >=parseInt(setHeight)|| parseInt(y0) >= parseInt(setWidth)) {
clearInterval(timer);
}
h0 += height;
y0 += width;
console.log(y0,h0)
$('.big_img_box').css({
height: h0 + 'px',
width: y0 + 'px'
})
$(".pinch-zoom-container").css({
height: h0-30 + 'px',
width: y0 -30+ 'px'
})
$('.big_img_box').show();
}, 20);
})
})
$('.close').click(function(e) {
clearInterval(timer);
$('.big_img_box').hide();
e.stopPropagation();
$('body').css({'position':'','overflow-y':'scroll'})
document.getElementById('move_part').style.transform = 'rotate(0deg)';
$(".btns").addClass("hide").eq(0).removeClass("hide");
$('.big_img_box').css({"width":0,"height":0})
return false;
})
//图片旋转
$("#xzID").click(function () {
$('#move_part').css({"transform":'rotate('+90+'deg)'});
$(".btns").addClass("hide").eq(3).removeClass("hide");
$("#xzID3").click(function () {
$('#move_part').css({"transform":'rotate('+180+'deg)'});
$(".btns").addClass("hide").eq(2).removeClass("hide");
// $('.big_img_box img').each(function () {
// new RTP.PinchZoom($(this), {});
// });
$("#xzID2").click(function () {
$('#move_part').css({"transform":'rotate('+270+'deg)'});
$(".btns").addClass("hide").eq(1).removeClass("hide");
// $('.big_img_box img').each(function () {
// new RTP.PinchZoom($(this), {});
// });
$("#xzID1").click(function () {
$('#move_part').css({"transform":'rotate('+360+'deg)'});
$(".btns").addClass("hide").eq(0).removeClass("hide");
// $('.big_img_box img').each(function () {
// new RTP.PinchZoom($(this), {});
// });
})
})
})
bsFlag=1;
})
var isComputer ="{php echo is_mobile()}";
console.log(isComputer)
var div1 = document.getElementById("move_part");
//限制最大宽高,不让滑块出去
var maxW = document.body.clientWidth - div1.offsetWidth;
var maxH = document.body.clientHeight - div1.offsetHeight;
if(isComputer==1){
//手指触摸开始,记录div的初始位置
div1.addEventListener('touchstart', function(e) {
var ev = e || window.event;
var touch = ev.targetTouches[0];
oL = touch.clientX - div1.offsetLeft;
oT = touch.clientY - div1.offsetTop;
});
//触摸中的,位置记录
div1.addEventListener('touchmove', function(e) {
var ev = e || window.event;
ev.stopPropagation()
ev.preventDefault()
var touch = ev.targetTouches[0];
var oLeft = touch.clientX - oL;
var oTop = touch.clientY - oT;
var touchesLen = ev.touches.length ;
if(touchesLen==2){
return;
}
if(oLeft < -150) {
oLeft = -150;
} else if(oLeft > maxW-document.documentElement.clientWidth / 1.2+150) {
oLeft = maxW-document.documentElement.clientWidth / 1.2+150;
}
if(oTop < -110) {
oTop = -110;
} else if(oTop >maxH-document.documentElement.clientHeight/3+70) {
oTop = maxH-document.documentElement.clientHeight/3+70;
}
div1.style.left = oLeft + 'px';
div1.style.top = oTop + 'px';
});
}else if(isComputer==0){
//鼠标按下,记录div的初始位置
div1.onmousedown=function(e){
var ev = e || window.event;
oL = ev.clientX - div1.offsetLeft;
oT = ev.clientY - div1.offsetTop;
if(typeof div1.setCapture !== 'undefined'){
div1.setCapture();
}
//鼠标按住元素拖动,位置记录
document.onmousemove=function(e){
var ev = e || window.event;
ev.stopPropagation()
ev.preventDefault()
var oLeft = ev.clientX - oL;
var oTop = ev.clientY - oT;
if(oLeft < -150) {
oLeft = -150;
} else if(oLeft > maxW-document.documentElement.clientWidth / 1.2+150) {
oLeft = maxW-document.documentElement.clientWidth / 1.2+150;
}
if(oTop < -110) {
oTop = -110;
} else if(oTop >maxH-document.documentElement.clientHeight/3+70) {
oTop = maxH-document.documentElement.clientHeight/3+70;
}
div1.style.left = oLeft + 'px';
div1.style.top = oTop + 'px';
}
document.onmouseup = function(event){
this.onmousemove = null;
this.onmouseup = null;
//修复低版本ie bug
if(typeof div1.releaseCapture!='undefined'){
div1.releaseCapture();
}
}
}
}
//触摸结束时的处理
//图片放大处理
$('.big_img_box img').each(function () {
new RTP.PinchZoom($(this), {});
});
}