console
(function (root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define([], factory);
else if(typeof exports === 'object')
exports["Zoom"] = factory();
else
root["Zoom"] = factory();
})(this,function(){
function Zoom(el,option){
if (!option || !option.width || !option.height) {
throw "dom的尺寸参数错误";
}
option = Object.assign({
minScale:1,
maxScale:3,
top:0,
left:0
}, option);
this.el = el;
this.lastSapce = 0;
this.touchState = 0;
this.lastPoint = null
this.targetPoint = null;
this.minScale = option.minScale || 1;
this.maxScale = option.maxScale || 10;
this.width = option.width ;
this.height = option.height;
this.top = option.top ;
this.left = option.left;
this.scale = 1;
this.originTop = option.top;
this.originLeft = option.left;
this.originW = this.width;
this.originH = this.height;
this.centerX = this.left + this.originW / 2;
this.centerY = this.top + this.originH / 2;
this.el.style.position = 'absolute';
this.init();
return this;
}
Zoom.prototype.getTouches = function (event){
let touches = event.touches;
if (!touches) {
touches = event.originalEvent.touches;
}
return touches;
}
Zoom.prototype.getTouchsDistance = function(t1,t2){
let dx = parseInt(t1.pageX - t2.pageX);
let dy = parseInt(t1.pageY - t2.pageY);
let d = Math.pow((dx *dx + dy * dy), 0.5);
return d.toFixed(5);
}
Zoom.prototype.restView = function(){
this.el.style.width = this.width + 'px';
this.el.style.height = this.height + 'px';
this.el.style.top = this.top + 'px';
this.el.style.left = this.left + 'px';
}
Zoom.prototype.init = function(){
this.el.addEventListener('touchmove',this.touchmoveHandler);
this.el.addEventListener('touchstart',this.touchmoveHandler);
this.el.addEventListener('touchend',this.touchEndHandler);
this.el.addEventListener('touchcancel',this.touchEndHandler);
this.el.addEventListener('touchstart',this.dbclickHandler);
this.el.zoom = this;
}
Zoom.prototype.dbclickHandler = function(event){
event.stopPropagation();
event.preventDefault();
let el = event.currentTarget;
let zoom = el.zoom;
let time = new Date(event.timeStamp).getTime();
let touchs = zoom.getTouches(event);
if (touchs.length == 1) {
if (!el.lastClickTime) {
el.lastClickTime = time;
}else{
if (time - el.lastClickTime < 300) {
el.lastClickTime = 0;
if (zoom.scale != 1) {
zoom.setScale(1);
}else if(zoom.scale == 1){
zoom.setScale(2);
}
}else{
el.lastClickTime = time;
}
}
}
zoom.touchStartTime = new Date().getTime();
return false;
},
Zoom.prototype.drage = function(touch){
if (this.lastPoint == null) {
this.lastPoint = {
x:touch.pageX,
y:touch.pageY,
}
}else{
let dx = parseInt(touch.pageX - this.lastPoint.x);
let dy = parseInt(touch.pageY - this.lastPoint.y);
this.lastPoint.x = touch.pageX;
this.lastPoint.y = touch.pageY;
this.left += dx;
this.top += dy;
this.setTransform(false);
}
}
Zoom.prototype.zoom = function(touchs){
this.lastPoint = null;
let t1 = touchs[0];
let t2 = touchs[1];
let x1 = t1.pageX;
let x2 = t2.pageX;
let y1 = t1.pageY;
let y2 = t2.pageY;
let d = this.getTouchsDistance(t1,t2);
if (this.touchState == 0) {
this.lastSapce = d;
this.touchState = 1;
this.pointX = (x2 + (x1 - x2) / 2 - this.left)/this.scale;
this.pointY = (y2 + (y1 - y2) / 2 - this.top)/this.scale;
}else if(this.touchState == 1){
let scaleChange = ((d / this.lastSapce) - 1) * 2;
let scale = this.scale + scaleChange / 2;
this.setScale(scale,this.pointX,this.pointY);
this.lastSapce = d;
}
}
Zoom.prototype.touchmoveHandler = function(event){
event.stopPropagation();
event.preventDefault();
let el = event.currentTarget;
let zoom = el.zoom;
let touchs = zoom.getTouches(event);
if (touchs.length == 1) {
zoom.drage(touchs[0]);
}else if (touchs.length >= 2) {
zoom.lastPoint = null;
zoom.zoom(touchs);
}
return false;
}
Zoom.prototype.touchEndHandler = function(event){
let zoom = event.currentTarget.zoom;
zoom.touchState = 0;
zoom.lastPoint = null;
zoom.lastSapce = 0;
let minSpace = 20;
let parentWidth = zoom.el.parentElement.offsetWidth;
let parentHight =zoom.el.parentElement.offsetHeight;
let scale = zoom.scale;
if(scale < zoom.minScale){
scale = zoom.minScale;
}
if(scale > zoom.maxScale){
scale = zoom.maxScale;
}
if(scale != zoom.scale){
zoom.preSetScale(scale,zoom.lastPointX,zoom.lastPointY);
}
if((zoom.left + zoom.width) < minSpace){
zoom.left = - zoom.width + minSpace;
}
if(zoom.left >= (parentWidth - minSpace)){
zoom.left = parentWidth - minSpace;
}
if((zoom.top + zoom.height) < minSpace){
zoom.top = - zoom.height + minSpace;
}
if(zoom.top >= (parentHight - minSpace)){
zoom.top = parentHight - minSpace;
}
zoom.setTransform(true);
return;
}
Zoom.prototype.setTransform = function (needAnimation,originX,originY){
let distanceX = this.left - this.originLeft;
let distanceY = this.top - this.originTop;
let scale = this.scale;
originX = originX == undefined ? (this.originTop + 'px') : originX;
originY = originY == undefined ? (this.originLeft + 'px') : originY;
this.el.style.transformOrigin = 'left top';
this.el.style.transform = 'matrix('+scale+',0,0,'+scale+','+distanceX+','+distanceY+')';
if(needAnimation == true){
this.el.style.transition = 'all .3s ease-in-out 0s'
}else{
this.el.style.transition = ''
}
}
Zoom.prototype.destroy = function(){
this.el.removeEventListener('touchmove',this.touchmoveHandler);
this.el.removeEventListener('touchstart',this.touchmoveHandler);
this.el.removeEventListener('touchend',this.touchEndHandler);
this.el.removeEventListener('touchcancel',this.touchEndHandler);
this.el.zoom = null;
}
Zoom.prototype.setScale = function(scale,pointX,pointY){
this.preSetScale(scale,pointX,pointY);
this.setTransform(false);
}
Zoom.prototype.preSetScale = function(scale,pointX,pointY){
if (scale < 0.1) {
scale = 0.1;
}
if (pointX ==undefined) {
this.left = this.centerX - this.originW / 2 - this.originW/2*(scale - 1);
this.top = this.centerY - this.originH / 2 - this.originH/2*(scale - 1);
this.width = scale * this.originW;
this.height = scale * this.originH;
this.scale = scale;
}else{
this.width = scale * this.originW;
this.height = scale * this.originH;
this.left = this.left - pointX * (scale - this.scale);
this.top = this.top - pointY * (scale - this.scale);
this.lastPointX = pointX;
this.lastPointY = pointY;
this.scale = scale;
}
}
return Zoom;
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<title>zoom</title>
<link rel="stylesheet" href="">
<style type="text/css">
html,
body {
height: 100%;
width: 100%;
padding: 0;
margin: 0;
overflow: hidden;
}
.box {
width: 90%;
height: 90%;
margin: 10% 5%;
background: #999;
overflow: hidden;
position:relative;
}
#zoomEl {
position: absolute;
width: 200px;
height: 200px;
left: calc(50% - 100px);
top: calc(50% - 100px);
background-color: red;
background-image: url(./a.png);
background-repeat: round;
display: inline-block;
}
</style>
</head>
<body style="background-color: #ddd;">
<div class="box">
<div id="zoomEl">123123</div>
</div>
<script type="text/javascript">
let zoomEl = document.getElementById('zoomEl');
let zoom = new Zoom(zoomEl, { 'top': zoomEl.offsetTop, 'left': zoomEl.offsetLeft, 'width': 200, 'height': 200 });
zoom.setScale(1)
</script>
</body>
</html>