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);
|