| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212 | 
							- (function() {
 
- 	'use strict';
 
- 	var definePinchZoom = function($) {
 
- 		var PinchZoom = function(el, options, viewerContainer) {
 
- 				this.el = $(el);
 
- 				this.viewerContainer = viewerContainer;
 
- 				this.zoomFactor = 1;
 
- 				this.lastScale = 1;
 
- 				this.offset = {
 
- 					x: 0,
 
- 					y: 0
 
- 				};
 
- 				this.options = $.extend({}, this.defaults, options);
 
- 				this.setupMarkup();
 
- 				this.bindEvents();
 
- 				this.update();
 
- 				// default enable.
 
- 				this.enable();
 
- 				this.height = 0;
 
- 				this.load = false;
 
- 				this.direction = null;
 
- 				this.clientY = null;
 
- 				this.lastclientY = null;
 
- 			},
 
- 			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.2,
 
- 				animationDuration: 300,
 
- 				maxZoom: 4,
 
- 				minZoom: 0.8,
 
- 				lockDragAxis: false,
 
- 				use2d: true,
 
- 				zoomStartEventName: 'pz_zoomstart',
 
- 				zoomEndEventName: 'pz_zoomend',
 
- 				dragStartEventName: 'pz_dragstart',
 
- 				dragEndEventName: 'pz_dragend',
 
- 				doubleTapEventName: 'pz_doubletap'
 
- 			},
 
- 			/**
 
- 			 * Event handler for 'dragstart'
 
- 			 * @param event
 
- 			 */
 
- 			handleDragStart: function(event) {
 
- 				this.el.trigger(this.options.dragStartEventName);
 
- 				this.stopAnimation();
 
- 				this.lastDragPosition = false;
 
- 				this.hasInteraction = true;
 
- 				this.handleDrag(event);
 
- 			},
 
- 			/**
 
- 			 * Event handler for 'drag'
 
- 			 * @param event
 
- 			 */
 
- 			handleDrag: function(event) {
 
- 				if (this.zoomFactor > 1.0) {
 
- 					var touch = this.getTouches(event)[0];
 
- 					this.drag(touch, this.lastDragPosition, event);
 
- 					this.offset = this.sanitizeOffset(this.offset);
 
- 					this.lastDragPosition = touch;
 
- 				}
 
- 			},
 
- 			handleDragEnd: function() {
 
- 				this.el.trigger(this.options.dragEndEventName);
 
- 				this.end();
 
- 			},
 
- 			/**
 
- 			 * Event handler for 'zoomstart'
 
- 			 * @param event
 
- 			 */
 
- 			handleZoomStart: function(event) {
 
- 				this.el.trigger(this.options.zoomStartEventName);
 
- 				this.stopAnimation();
 
- 				this.lastScale = 1;
 
- 				this.nthZoom = 0;
 
- 				this.lastZoomCenter = false;
 
- 				this.hasInteraction = true;
 
- 			},
 
- 			/**
 
- 			 * Event handler for 'zoom'
 
- 			 * @param event
 
- 			 */
 
- 			handleZoom: function(event, newScale) {
 
- 				// a relative scale factor is used
 
- 				var touchCenter = this.getTouchCenter(this.getTouches(event)),
 
- 					scale = newScale / this.lastScale;
 
- 				this.lastScale = newScale;
 
- 				// the first touch events are thrown away since they are not precise
 
- 				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();
 
- 			},
 
- 			/**
 
- 			 * Event handler for 'doubletap'
 
- 			 * @param event
 
- 			 */
 
- 			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);
 
- 			},
 
- 			/**
 
- 			 * Max / min values for the offset
 
- 			 * @param offset
 
- 			 * @return {Object} the sanitized offset
 
- 			 */
 
- 			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);
 
- 				var x = Math.min(Math.max(offset.x, minOffsetX), maxOffsetX),
 
- 					y = Math.min(Math.max(offset.y, minOffsetY), maxOffsetY);
 
- 				return {
 
- 					x: x,
 
- 					y: y
 
- 				};
 
- 			},
 
- 			/**
 
- 			 * Scale to a specific zoom factor (not relative)
 
- 			 * @param zoomFactor
 
- 			 * @param center
 
- 			 */
 
- 			scaleTo: function(zoomFactor, center) {
 
- 				this.scale(zoomFactor / this.zoomFactor, center);
 
- 			},
 
- 			/**
 
- 			 * Scales the element from specified center
 
- 			 * @param scale
 
- 			 * @param 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)
 
- 				});
 
- 			},
 
- 			/**
 
- 			 * Scales the zoom factor relative to current state
 
- 			 * @param scale
 
- 			 * @return the actual scale (can differ because of max min zoom factor)
 
- 			 */
 
- 			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;
 
- 			},
 
- 			/**
 
- 			 * Drags the element
 
- 			 * @param center
 
- 			 * @param lastCenter
 
- 			 */
 
- 			drag: function(center, lastCenter, event) {
 
- 				if (lastCenter) {
 
- 					if (this.options.lockDragAxis) {
 
- 						// lock scroll to position that was changed the most
 
- 						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 {
 
- 						if (center.y - lastCenter.y < 0) {
 
- 							this.direction = "down";
 
- 						} else if (center.y - lastCenter.y > 10) {
 
- 							this.direction = "up";
 
- 						}
 
- 						this.addOffset({
 
- 							y: -(center.y - lastCenter.y),
 
- 							x: -(center.x - lastCenter.x)
 
- 						});
 
- 					}
 
- 				}
 
- 			},
 
- 			/**
 
- 			 * Calculates the touch center of multiple touches
 
- 			 * @param touches
 
- 			 * @return {Object}
 
- 			 */
 
- 			getTouchCenter: function(touches) {
 
- 				return this.getVectorAvg(touches);
 
- 			},
 
- 			/**
 
- 			 * Calculates the average of multiple vectors (x, y values)
 
- 			 */
 
- 			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
 
- 				};
 
- 			},
 
- 			/**
 
- 			 * Adds an offset
 
- 			 * @param offset the offset to add
 
- 			 * @return return true when the offset change was accepted
 
- 			 */
 
- 			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();
 
- 				}
 
- 			},
 
- 			/**
 
- 			 * Checks if the offset is ok with the current zoom factor
 
- 			 * @param offset
 
- 			 * @return {Boolean}
 
- 			 */
 
- 			isInsaneOffset: function(offset) {
 
- 				var sanitizedOffset = this.sanitizeOffset(offset);
 
- 				return sanitizedOffset.x !== offset.x ||
 
- 					sanitizedOffset.y !== offset.y;
 
- 			},
 
- 			/**
 
- 			 * Creates an animation moving to a sane offset
 
- 			 */
 
- 			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
 
- 				);
 
- 			},
 
- 			/**
 
- 			 * Zooms back to the original position,
 
- 			 * (no offset and zoom factor 1)
 
- 			 */
 
- 			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
 
- 				);
 
- 			},
 
- 			/**
 
- 			 * Updates the aspect ratio
 
- 			 */
 
- 			updateAspectRatio: function() {
 
- 				this.setContainerY(this.getContainerX() / this.getAspectRatio());
 
- 			},
 
- 			/**
 
- 			 * Calculates the initial zoom factor (for the element to fit into the container)
 
- 			 * @return the initial zoom factor
 
- 			 */
 
- 			getInitialZoomFactor: function() {
 
- 				// use .offsetWidth instead of width()
 
- 				// because jQuery-width() return the original width but Zepto-width() will calculate width with transform.
 
- 				// the same as .height()
 
- 				if (this.container[0] && this.el[0]) {
 
- 					return this.container[0].offsetWidth / this.el[0].offsetWidth;
 
- 				} else {
 
- 					return 0
 
- 				}
 
- 			},
 
- 			/**
 
- 			 * Calculates the aspect ratio of the element
 
- 			 * @return the aspect ratio
 
- 			 */
 
- 			getAspectRatio: function() {
 
- 				if (this.el[0]) {
 
- 					var offsetHeight = this.el[0].offsetHeight;
 
- 					return this.container[0].offsetWidth / offsetHeight;
 
- 				} else {
 
- 					return 0
 
- 				}
 
- 			},
 
- 			/**
 
- 			 * Calculates the virtual zoom center for the current offset and zoom factor
 
- 			 * (used for reverse zoom)
 
- 			 * @return {Object} the current zoom center
 
- 			 */
 
- 			getCurrentZoomCenter: function() {
 
- 				// uses following formula to calculate the zoom center x value
 
- 				// offset_left / offset_right = zoomcenter_x / (container_x - zoomcenter_x)
 
- 				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),
 
- 					// the same for the zoomcenter y
 
- 					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);
 
- 				// prevents division by zero
 
- 				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);
 
- 			},
 
- 			/**
 
- 			 * Returns the touches of an event relative to the container offset
 
- 			 * @param event
 
- 			 * @return array touches
 
- 			 */
 
- 			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
 
- 					};
 
- 				});
 
- 			},
 
- 			/**
 
- 			 * Animation loop
 
- 			 * does not support simultaneous animations
 
- 			 * @param duration
 
- 			 * @param framefn
 
- 			 * @param timefn
 
- 			 * @param callback
 
- 			 */
 
- 			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);
 
- 			},
 
- 			/**
 
- 			 * Stops the animation
 
- 			 */
 
- 			stopAnimation: function() {
 
- 				this.inAnimation = false;
 
- 			},
 
- 			/**
 
- 			 * Swing timing function for animations
 
- 			 * @param p
 
- 			 * @return {Number}
 
- 			 */
 
- 			swing: function(p) {
 
- 				return -Math.cos(p * Math.PI) / 2 + 0.5;
 
- 			},
 
- 			getContainerX: function() {
 
- 				if (this.el[0]) {
 
- 					return this.el[0].offsetWidth;
 
- 				} else {
 
- 					return 0;
 
- 				}
 
- 			},
 
- 			getContainerY: function() {
 
- 				return this.el[0].offsetHeight;
 
- 			},
 
- 			setContainerY: function(y) {
 
- 				y = y.toFixed(2);
 
- 				return this.container.height(y);
 
- 			},
 
- 			/**
 
- 			 * Creates the expected html structure
 
- 			 */
 
- 			setupMarkup: function() {
 
- 				this.container = $('<div class="pinch-zoom-container"></div>');
 
- 				this.el.before(this.container);
 
- 				this.container.append(this.el);
 
- 				this.container.css({
 
- 					'position': 'relative',
 
- 					//                  'width':'auto',
 
- 					//                  'height':'auto'
 
- 				});
 
- 				// Zepto doesn't recognize `webkitTransform..` style
 
- 				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': 'relative'
 
- 				});
 
- 			},
 
- 			end: function() {
 
- 				this.hasInteraction = false;
 
- 				this.sanitize();
 
- 				this.update();
 
- 			},
 
- 			/**
 
- 			 * Binds all required event listeners
 
- 			 */
 
- 			bindEvents: function() {
 
- 				detectGestures(this.container.eq(0), this, this.viewerContainer);
 
- 				// Zepto and jQuery both know about `on`
 
- 				$(window).on('resize', this.update.bind(this));
 
- 				$(this.el).find('img').on('load', this.update.bind(this));
 
- 			},
 
- 			/**
 
- 			 * Updates the css values according to the current zoom factor and offset
 
- 			 */
 
- 			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).toFixed(3),
 
- 						offsetY = (-this.offset.y / zoomFactor).toFixed(3);
 
- 					this.lastclientY = offsetY;
 
- 					var 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);
 
- 					// Scale 3d and translate3d are faster (at least on ios)
 
- 					// but they also reduce the quality.
 
- 					// PinchZoom uses the 3d transformations during interactions
 
- 					// after interactions it falls back to 2d transformations
 
- 					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 {
 
- 						// When changing from 3d to 2d transform webkit has some glitches.
 
- 						// To avoid this, a copy of the 3d transformed element is displayed in the
 
- 						// foreground while the element is converted from 3d to 2d transform
 
- 						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;
 
- 					}
 
- 					this.done && this.done.call(this, zoomFactor)
 
- 				}).bind(this), 0);
 
- 			},
 
- 			/**
 
- 			 * Enables event handling for gestures
 
- 			 */
 
- 			enable: function() {
 
- 				this.enabled = true;
 
- 			},
 
- 			/**
 
- 			 * Disables event handling for gestures
 
- 			 */
 
- 			disable: function() {
 
- 				this.enabled = false;
 
- 			},
 
- 			//销毁还原
 
- 			destroy: function() {
 
- 				var dom = this.el.clone();
 
- 				var p = this.container.parent();
 
- 				this.container.remove();
 
- 				dom.removeAttr('style');
 
- 				p.append(dom);
 
- 			}
 
- 		};
 
- 		var detectGestures = function(el, target, viewerContainer) {
 
- 			var interaction = null,
 
- 				fingers = 0,
 
- 				lastTouchStart = null,
 
- 				startTouches = null,
 
- 				lastTouchY = null,
 
- 				clientY = null,
 
- 				lastclientY = 0,
 
- 				lastTop = 0,
 
- 				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();
 
- 					var pageY = event.changedTouches[0].pageY;
 
- 					var top = parentNode.scrollTop || 0;
 
- 					if (fingers > 1) {
 
- 						lastTouchStart = null;
 
- 						lastTouchY = null;
 
- 						cancelEvent(event);
 
- 					}
 
- 					if (time - lastTouchStart < 300 && Math.abs(pageY - lastTouchY) < 10 && Math.abs(lastTop - top) < 10) {
 
- 						cancelEvent(event);
 
- 						target.handleDoubleTap(event);
 
- 						switch (interaction) {
 
- 							case "zoom":
 
- 								target.handleZoomEnd(event);
 
- 								break;
 
- 							case 'drag':
 
- 								target.handleDragEnd(event);
 
- 								break;
 
- 						}
 
- 					}
 
- 					if (fingers === 1) {
 
- 						lastTouchStart = time;
 
- 						lastTouchY = pageY;
 
- 						lastTop = top;
 
- 					}
 
- 				},
 
- 				firstMove = true;
 
- 			if (viewerContainer) {
 
- 				var parentNode = viewerContainer[0];
 
- 			}
 
- 			if (parentNode) {
 
- 				parentNode.addEventListener('touchstart', function(event) {
 
- 					if (target.enabled) {
 
- 						firstMove = true;
 
- 						fingers = event.touches.length;
 
- 						detectDoubleTap(event);
 
- 						clientY = event.changedTouches[0].clientY;
 
- 						if (fingers > 1) {
 
- 							cancelEvent(event);
 
- 						}
 
- 					}
 
- 				});
 
- 				parentNode.addEventListener('touchmove', function(event) {
 
- 					if (target.enabled) {
 
- 						lastclientY = event.changedTouches[0].clientY;
 
- 						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(lastclientY);
 
- 							}
 
- 						}
 
- 						if (fingers > 1) {
 
- 							cancelEvent(event);
 
- 						}
 
- 						firstMove = false;
 
- 					}
 
- 				});
 
- 				parentNode.addEventListener('touchend', function(event) {
 
- 					if (target.enabled) {
 
- 						fingers = event.touches.length;
 
- 						if (fingers > 1) {
 
- 							cancelEvent(event);
 
- 						}
 
- 						updateInteraction(event);
 
- 					}
 
- 				});
 
- 			}
 
- 		};
 
- 		return PinchZoom;
 
- 	};
 
- 	var PinchZoom = definePinchZoom($);
 
- 	var Pdfh5 = function(dom, options) {
 
- 		this.container = $(dom);
 
- 		this.currentNum = 1; //当前页数从1开始
 
- 		this.thePDF = null;
 
- 		this.pdfRender = null;
 
- 		this.totalNum = null;
 
- 		this.pdfLoaded = false;
 
- 		this.pages = null;
 
- 		this.initTime = 0;
 
- 		this.startTime = 0;
 
- 		this.endTime = 0;
 
- 		this.renderTime = 0;
 
- 		this.timer = null;
 
- 		this.loadWidth = 1;
 
- 		this.docWidth = document.documentElement.clientWidth;
 
- 		this.eventType = {};
 
- 		this.init(options);
 
- 	};
 
- 	Pdfh5.prototype = {
 
- 		init: function(options) {
 
- 			var self = this;
 
- 			if (self.pdfLoaded) {
 
- 				return;
 
- 			}
 
- 			this.initTime = new Date().getTime();
 
- 			setTimeout(function() {
 
- 				self.eventType["start"] && self.eventType["start"].call(self, self.initTime);
 
- 				self.start && self.start(self.initTime)
 
- 			}, 0)
 
- 			options = options ? options : {};
 
- 			options.pdfurl = options.pdfurl ? options.pdfurl : null;
 
- 			options.data = options.data ? options.data : null;
 
- 			if (options.scrollEnable == 'undefined' || options.scrollEnable == undefined) {
 
- 				options.scrollEnable = true
 
- 			}
 
- 			if (options.scrollEnable == 'true' || options.scrollEnable == true) {
 
- 				options.scrollEnable = true
 
- 			}
 
- 			if (options.scrollEnable == 'null' || options.scrollEnable == null) {
 
- 				options.scrollEnable = true
 
- 			}
 
- 			if (options.scrollEnable == 'false') {
 
- 				options.scrollEnable = false
 
- 			}
 
- 			var html = '<div class="loadingBar">' +
 
- 				'<div class="progress">' +
 
- 				' <div class="glimmer">' +
 
- 				'</div>' +
 
- 				' </div>' +
 
- 				'</div>' +
 
- 				'<div class="pageNum">' +
 
- 				'<div class="pageNum-bg"></div>' +
 
- 				' <div class="pageNum-num">' +
 
- 				' <span class="pageNow">1</span>/' +
 
- 				'<span class="pageTotal">1</span>' +
 
- 				'</div>' +
 
- 				' </div>' +
 
- 				'<div class="backTop">' +
 
- 				'</div>' +
 
- 				'<div class="loadEffect"></div>';
 
- 			if (!this.container.find('.pageNum')[0]) {
 
- 				this.container.append(html);
 
- 			}
 
- 			var viewer = document.createElement("div");
 
- 			viewer.className = 'pdfViewer';
 
- 			var viewerContainer = document.createElement("div");
 
- 			viewerContainer.className = 'viewerContainer';
 
- 			viewerContainer.appendChild(viewer);
 
- 			this.container.append(viewerContainer);
 
- 			this.viewer = $(viewer);
 
- 			this.viewerContainer = $(viewerContainer);
 
- 			this.pageNum = this.container.find('.pageNum');
 
- 			this.pageNow = this.pageNum.find('.pageNow');
 
- 			this.pageTotal = this.pageNum.find('.pageTotal');
 
- 			this.loadingBar = this.container.find('.loadingBar');
 
- 			this.progress = this.loadingBar.find('.progress');
 
- 			this.backTop = this.container.find('.backTop');
 
- 			this.loading = this.container.find('.loadEffect');
 
- 			var height = document.documentElement.clientHeight * (1 / 3);
 
- 			if (!options.scrollEnable) {
 
- 				this.viewerContainer.css({
 
- 					"overflow": "hidden"
 
- 				})
 
- 			} else {
 
- 				this.viewerContainer.css({
 
- 					"overflow": "auto"
 
- 				})
 
- 			}
 
- 			viewerContainer.addEventListener('scroll', function() {
 
- 				var scrollTop = viewerContainer.scrollTop;
 
- 				if (scrollTop >= 150) {
 
- 					if (self.backTop) {
 
- 						self.backTop.show();
 
- 					}
 
- 				} else {
 
- 					if (self.backTop) {
 
- 						self.backTop.fadeOut(200);
 
- 					}
 
- 				}
 
- 				if (self.viewerContainer) {
 
- 					self.pages = self.viewerContainer.find('.page');
 
- 				}
 
- 				clearTimeout(self.timer);
 
- 				if (self.pageNum) {
 
- 					self.pageNum.show();
 
- 				}
 
- 				if (self.pages) {
 
- 					self.pages.each(function(index, obj) {
 
- 						var top = obj.getBoundingClientRect().top;
 
- 						var bottom = obj.getBoundingClientRect().bottom;
 
- 						if (top <= height && bottom > height) {
 
- 							if (self.pageNum) {
 
- 								self.pageNow.text(index + 1)
 
- 							}
 
- 						}
 
- 					})
 
- 				}
 
- 				self.timer = setTimeout(function() {
 
- 					if (self.pageNum) {
 
- 						self.pageNum.fadeOut(200);
 
- 					}
 
- 				}, 1500)
 
- 				self.eventType["scroll"] && self.eventType["scroll"].call(self, scrollTop);
 
- 				self.scroll && self.scroll(scrollTop);
 
- 			})
 
- 			this.backTop.on('click tap', function() {
 
- 				var mart = self.viewer.css('transform');
 
- 				var arr = mart.replace(/[a-z\(\)\s]/g, '').split(',');
 
- 				var s1 = arr[0];
 
- 				var s2 = arr[3];
 
- 				var x = arr[4] / 2;
 
- 				var left = self.viewer[0].getBoundingClientRect().left;
 
- 				if (left <= -self.docWidth * 2) {
 
- 					x = -self.docWidth / 2
 
- 				}
 
- 				self.viewer.css({
 
- 					transform: 'scale(' + s1 + ', ' + s2 + ') translate(' + x + 'px, 0px)'
 
- 				})
 
- 				if (self.PinchZoom) {
 
- 					self.PinchZoom.offset.y = 0;
 
- 					self.PinchZoom.lastclientY = 0;
 
- 				}
 
- 				self.viewerContainer.animate({
 
- 					scrollTop: 0
 
- 				}, 300)
 
- 				self.eventType["backTop"] && self.eventType["backTop"].call(self);
 
- 			})
 
- 			//获取url带的参数地址
 
- 			function GetQueryString(name) {
 
- 				var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
 
- 				var r = window.location.search.substr(1).match(reg);
 
- 				if (r != null) return decodeURIComponent(r[2]);
 
- 				return "";
 
- 			}
 
- 			var pdfurl = GetQueryString("file");
 
- 			if (pdfurl) {
 
- 				getDoc(pdfurl)
 
- 			} else if (options.pdfurl) {
 
- 				getDoc(options.pdfurl)
 
- 			} else {
 
- 				setTimeout(function() {
 
- 					var time = new Date().getTime();
 
- 					self.endTime = time - self.initTime;
 
- 					self.eventType["complete"] && self.eventType["complete"].call(self, "error", "文件路径错误", self.endTime);
 
- 					self.eventType["error"] && self.eventType["error"].call(self, "error", "文件路径错误", self.endTime);
 
- 					self.complete && self.complete("error", "文件路径错误", self.endTime)
 
- 					self.error && self.error("error", "文件路径错误", self.endTime)
 
- 				}, 0)
 
- 			}
 
- 			function getDoc(array) {
 
- 				if (self.pdfLoaded) {
 
- 					return;
 
- 				}
 
- 				pdfjsLib.getDocument(array).then(function(pdf) {
 
- 					if (self.pdfLoaded) {
 
- 						return;
 
- 					}
 
- 					self.thePDF = pdf;
 
- 					self.totalNum = pdf.numPages;
 
- 					self.thePDF.getPage(1).then(handlePages);
 
- 					self.pageTotal.text(self.totalNum)
 
- 					var time = new Date().getTime();
 
- 					self.startTime = time - self.initTime;
 
- 					self.eventType["renderStart"] && self.eventType["renderStart"].call(self, self.startTime);
 
- 					self.renderStart && self.renderStart(self.startTime)
 
- 				}).catch(function(err) {
 
- 					var time = new Date().getTime();
 
- 					self.endTime = time - self.initTime;
 
- 					self.eventType["complete"] && self.eventType["complete"].call(self, "error", err.responseText, self.endTime);
 
- 					self.eventType["error"] && self.eventType["error"].call(self, "error", err.responseText, self.endTime);
 
- 					self.complete && self.complete("error", err.responseText, self.endTime)
 
- 					self.error && self.error("error", err.responseText, self.endTime)
 
- 				})
 
- 			}
 
- 			function handlePages(page) {
 
- 				if (self.pdfLoaded) {
 
- 					return;
 
- 				}
 
- 				if (!options || !options.scale) {
 
- 					if (self.totalNum === 1) {
 
- 						options.scale = 1.8
 
- 					} else {
 
- 						options.scale = 2.5
 
- 						// options.scale = 1.8
 
- 					}
 
- 				}
 
- 				if (options && options.defalutScale) {
 
- 					if (self.totalNum === 1) {
 
- 						options.scale = options.defalutScale
 
- 						// options.scale = 1.8
 
- 					} else {
 
- 						options.scale = 2.5
 
- 						// options.scale = 1.8
 
- 					}
 
- 				}
 
- 				var viewport = page.getViewport(options.scale);
 
- 				var canvas = document.createElement("canvas");
 
- 				var winRatio = ($(window).width() / viewport.width) * 1;
 
- 				var obj = {
 
- 					'Cheight': viewport.height * winRatio,
 
- 					'width': viewport.width,
 
- 					'height': viewport.height,
 
- 					'canvas': canvas,
 
- 					'index': self.currentNum
 
- 				}
 
- 				var context = canvas.getContext('2d');
 
- 				canvas.height = viewport.height;
 
- 				canvas.width = viewport.width;
 
- 				//在canvas上绘制
 
- 				self.pdfRender = page.render({
 
- 					canvasContext: context,
 
- 					viewport: viewport
 
- 				});
 
- 				obj.src = obj.canvas.toDataURL("image/jpeg");
 
- 				self.pdfRender.promise.then(function() {
 
- 					self.render(obj);
 
- 				}).then(function() {
 
- 					//开始下一页到绘制
 
- 					self.currentNum++;
 
- 					if (!self.pdfLoaded && self.thePDF && self.currentNum <= self.totalNum) {
 
- 						self.thePDF.getPage(self.currentNum).then(handlePages);
 
- 					} else {
 
- 						self.pdfLoaded = true;
 
- 						if (self.viewerContainer) {
 
- 							self.pages = self.viewerContainer.find('.page');
 
- 						}
 
- 						self.currentNum = self.totalNum;
 
- 						var time = new Date().getTime();
 
- 						self.endTime = time - self.initTime;
 
- 						if (self.progress) {
 
- 							self.progress.css({
 
- 								width: "100%"
 
- 							})
 
- 						}
 
- 						if (self.loadingBar) {
 
- 							self.loadingBar.fadeOut(200);
 
- 						}
 
- 						self.renderEnd && self.renderEnd(self.endTime)
 
- 						self.eventType["complete"] && self.eventType["complete"].call(self, "success", "PDF解析完毕", self.endTime);
 
- 						self.eventType["success"] && self.eventType["success"].call(self, "success", "PDF解析完毕", self.endTime);
 
- 						self.complete && self.complete("success", "PDF解析完毕", self.endTime)
 
- 						self.success && self.success("success", "PDF解析完毕", self.endTime)
 
- 						self.PinchZoom = new PinchZoom(self.viewer, {}, self.viewerContainer);
 
- 						self.PinchZoom.done = function(scale) {
 
- 							if (scale == 1) {
 
- 								if (self.viewerContainer) {
 
- 									self.viewerContainer.css({
 
- 										'-webkit-overflow-scrolling': 'touch'
 
- 									})
 
- 								}
 
- 							} else {
 
- 								if (self.viewerContainer) {
 
- 									self.viewerContainer.css({
 
- 										'-webkit-overflow-scrolling': 'auto'
 
- 									})
 
- 								}
 
- 							}
 
- 							self.zoomChange && self.zoomChange(scale)
 
- 						}
 
- 					}
 
- 				}).catch(function(err) {
 
- 					console.log(err)
 
- 				})
 
- 			}
 
- 		},
 
- 		render: function(obj) {
 
- 			if (this.pdfLoaded) {
 
- 				return;
 
- 			}
 
- 			var img = new Image();
 
- 			var time = new Date().getTime();
 
- 			var time2 = 0;
 
- 			if (this.renderTime == 0) {
 
- 				time2 = time - this.startTime
 
- 			} else {
 
- 				time2 = time - this.renderTime
 
- 			}
 
- 			obj.src = obj.canvas.toDataURL("image/jpeg");
 
- 			img.src = obj.src;
 
- 			var page = document.createElement("div");
 
- 			page.className = "page page" + obj.index;
 
- 			page.setAttribute('data-index', obj.index);
 
- 			$(page).css({
 
- 				'max-width': obj.width
 
- 			})
 
- 			page.appendChild(img);
 
- 			if (this.viewer) {
 
- 				this.viewer.append(page);
 
- 			}
 
- 			if (this.currentNum == 1) {
 
- 				this.loadWidth = 100 / this.totalNum;
 
- 				if (this.loadingBa) {
 
- 					this.loadingBar.show();
 
- 				}
 
- 				if (this.loading) {
 
- 					this.loading.fadeOut(200);
 
- 				}
 
- 			}
 
- 			if (this.progress) {
 
- 				this.progress.css({
 
- 					width: this.loadWidth * this.currentNum + "%"
 
- 				})
 
- 			}
 
- 			this.eventType["renderPages"] && this.eventType["renderPages"].call(this, page, time - this.initTime, time2);
 
- 			this.renderPages && this.renderPages(page, time - this.initTime, time2)
 
- 			this.renderTime = time;
 
- 		},
 
- 		show: function(callback) {
 
- 			this.container.show();
 
- 			this.eventType["show"] && this.eventType["show"].call(this);
 
- 			callback && callback.call(this)
 
- 		},
 
- 		hide: function(callback) {
 
- 			this.container.hide()
 
- 			this.eventType["hide"] && this.eventType["show"].call(this);
 
- 			callback && callback.call(this)
 
- 		},
 
- 		on: function(type, callback) {
 
- 			this.eventType[type] = callback
 
- 		},
 
- 		scrollEnable: function(flag) {
 
- 			if (!flag) {
 
- 				this.viewerContainer.css({
 
- 					"overflow": "hidden"
 
- 				})
 
- 			} else {
 
- 				this.viewerContainer.css({
 
- 					"overflow": "auto"
 
- 				})
 
- 			}
 
- 			this.eventType["scrollEnable"] && this.eventType["scrollEnable"].call(this);
 
- 		},
 
- 		reset: function(callback) {
 
- 			if (this.PinchZoom) {
 
- 				this.PinchZoom.offset.y = 0;
 
- 				this.PinchZoom.offset.x = 0;
 
- 				this.PinchZoom.lastclientY = 0;
 
- 				this.PinchZoom.zoomFactor = 1;
 
- 				this.PinchZoom.update();
 
- 			}
 
- 			if (this.viewerContainer) {
 
- 				this.viewerContainer.scrollTop(0);
 
- 			}
 
- 			this.eventType["reset"] && this.eventType["reset"].call(this);
 
- 			callback && callback.call(this)
 
- 		},
 
- 		destroy: function(callback) {
 
- 			var self = this;
 
- 			this.reset();
 
- 			if (this.thePDF) {
 
- 				this.thePDF.destroy();
 
- 				this.thePDF = null;
 
- 			}
 
- 			if (this.pdfRender) {
 
- 				this.pdfRender.cancel();
 
- 				this.pdfRender = null;
 
- 			}
 
- 			if (this.viewerContainer) {
 
- 				this.viewerContainer.remove();
 
- 				this.viewerContainer = null;
 
- 			}
 
- 			if (this.container) {
 
- 				this.container.html('');
 
- 				this.container = null;
 
- 			}
 
- 			this.backTop.off('tap');
 
- 			this.backTop.off('click');
 
- 			this.pdfLoaded = true;
 
- 			this.currentNum = 1;
 
- 			this.totalNum = null;
 
- 			this.pages = null;
 
- 			this.initTime = 0;
 
- 			this.startTime = 0;
 
- 			this.endTime = 0;
 
- 			this.renderTime = 0;
 
- 			this.viewer = null;
 
- 			this.pageNum = null;
 
- 			this.pageNow = null;
 
- 			this.pageTotal = null;
 
- 			this.loadingBar = null;
 
- 			this.progress = null;
 
- 			this.loading = null;
 
- 			this.timer = null;
 
- 			this.loadWidth = 1;
 
- 			this.show = null;
 
- 			this.hide = null;
 
- 			callback && callback.call(this)
 
- 			this.eventType["destroy"] && this.eventType["destroy"].call(this)
 
- 		}
 
- 	}
 
- 	if (typeof define !== 'undefined' && define.amd) {
 
- 		define(['jquery'], function($) {
 
- 			return Pdfh5
 
- 		});
 
- 	} else {
 
- 		window.Pdfh5 = Pdfh5
 
- 	}
 
- }).call(this);
 
 
  |