图片放大缩小的zoom.js

  1 +function ($) { "use strict";
  2 
  3   /**
  4    * The zoom service
  5    */
  6   function ZoomService () {
  7     this._activeZoom            =
  8     this._initialScrollPosition =
  9     this._initialTouchPosition  =
 10     this._touchMoveListener     = null
 11 
 12     this._$document = $(document)
 13     this._$window   = $(window)
 14     this._$body     = $(document.body)
 15 
 16     this._boundClick = $.proxy(this._clickHandler, this)
 17   }
 18 
 19   ZoomService.prototype.listen = function () {
 20     this._$body.on('click', '[data-action="zoom"]', $.proxy(this._zoom, this))
 21   }
 22 
 23   ZoomService.prototype._zoom = function (e) {
 24 
 25     var target = e.target
 26 
 27     if (!target || target.tagName != 'IMG') return
 28 
 29     if (this._$body.hasClass('zoom-overlay-open')) return
 30 
 31     if (e.metaKey || e.ctrlKey) {
 32       return window.open((e.target.getAttribute('data-original') || e.target.src), '_blank')
 33     }
 34 
 35     // if (target.width >= ($(window).width() - Zoom.OFFSET)) return
 36 
 37     this._activeZoomClose(true)
 38 
 39     this._activeZoom = new Zoom(target)
 40     this._activeZoom.zoomImage()
 41 
 42     // todo(fat): probably worth throttling this
 43     this._$window.on('scroll.zoom', $.proxy(this._scrollHandler, this))
 44 
 45     this._$document.on('keyup.zoom', $.proxy(this._keyHandler, this))
 46     this._$document.on('touchstart.zoom', $.proxy(this._touchStart, this))
 47 
 48     // we use a capturing phase here to prevent unintended js events
 49     // sadly no useCapture in jquery api (http://bugs.jquery.com/ticket/14953)
 50     if (document.addEventListener) {
 51       document.addEventListener('click', this._boundClick, true)
 52     } else {
 53       document.attachEvent('onclick', this._boundClick, true)
 54     }
 55 
 56     if ('bubbles' in e) {
 57       if (e.bubbles) e.stopPropagation()
 58     } else {
 59       // Internet Explorer before version 9
 60       e.cancelBubble = true
 61     }
 62   }
 63 
 64   ZoomService.prototype._activeZoomClose = function (forceDispose) {
 65     if (!this._activeZoom) return
 66 
 67     if (forceDispose) {
 68       this._activeZoom.dispose()
 69     } else {
 70       this._activeZoom.close()
 71     }
 72 
 73     this._$window.off('.zoom')
 74     this._$document.off('.zoom')
 75 
 76     document.removeEventListener('click', this._boundClick, true)
 77 
 78     this._activeZoom = null
 79   }
 80 
 81   ZoomService.prototype._scrollHandler = function (e) {
 82     if (this._initialScrollPosition === null) this._initialScrollPosition = $(window).scrollTop()
 83     var deltaY = this._initialScrollPosition - $(window).scrollTop()
 84     if (Math.abs(deltaY) >= 40) this._activeZoomClose()
 85   }
 86 
 87   ZoomService.prototype._keyHandler = function (e) {
 88     if (e.keyCode == 27) this._activeZoomClose()
 89   }
 90 
 91   ZoomService.prototype._clickHandler = function (e) {
 92     if (e.preventDefault) e.preventDefault()
 93     else event.returnValue = false
 94 
 95     if ('bubbles' in e) {
 96       if (e.bubbles) e.stopPropagation()
 97     } else {
 98       // Internet Explorer before version 9
 99       e.cancelBubble = true
100     }
101 
102     this._activeZoomClose()
103   }
104 
105   ZoomService.prototype._touchStart = function (e) {
106     this._initialTouchPosition = e.touches[0].pageY
107     $(e.target).on('touchmove.zoom', $.proxy(this._touchMove, this))
108   }
109 
110   ZoomService.prototype._touchMove = function (e) {
111     if (Math.abs(e.touches[0].pageY - this._initialTouchPosition) > 10) {
112       this._activeZoomClose()
113       $(e.target).off('touchmove.zoom')
114     }
115   }
116 
117 
118   /**
119    * The zoom object
120    */
121   function Zoom (img) {
122     this._fullHeight      =
123     this._fullWidth       =
124     this._overlay         =
125     this._targetImageWrap = null
126 
127     this._targetImage = img
128 
129     this._$body = $(document.body)
130   }
131 
132   Zoom.OFFSET = 40
133   Zoom._MAX_WIDTH = 2560
134   Zoom._MAX_HEIGHT = 4096
135 
136   Zoom.prototype.zoomImage = function () {
137     var img = document.createElement('img')
138     img.onload = $.proxy(function () {
139       this._fullHeight = Number(img.height)
140       this._fullWidth = Number(img.width)
141       this._zoomOriginal()
142     }, this)
143     img.src = this._targetImage.src
144   }
145 
146   Zoom.prototype._zoomOriginal = function () {
147     this._targetImageWrap           = document.createElement('div')
148     this._targetImageWrap.className = 'zoom-img-wrap'
149 
150     this._targetImage.parentNode.insertBefore(this._targetImageWrap, this._targetImage)
151     this._targetImageWrap.appendChild(this._targetImage)
152 
153     $(this._targetImage)
154       .addClass('zoom-img')
155       .attr('data-action', 'zoom-out')
156 
157     this._overlay           = document.createElement('div')
158     this._overlay.className = 'zoom-overlay'
159 
160     document.body.appendChild(this._overlay)
161 
162     this._calculateZoom()
163     this._triggerAnimation()
164   }
165 
166   Zoom.prototype._calculateZoom = function () {
167     this._targetImage.offsetWidth // repaint before animating
168 
169     var originalFullImageWidth  = this._fullWidth
170     var originalFullImageHeight = this._fullHeight
171 
172     var scrollTop = $(window).scrollTop()
173 
174     var maxScaleFactor = originalFullImageWidth / this._targetImage.width
175 
176     var viewportHeight = ($(window).height() - Zoom.OFFSET)
177     var viewportWidth  = ($(window).width() - Zoom.OFFSET)
178 
179     var imageAspectRatio    = originalFullImageWidth / originalFullImageHeight
180     var viewportAspectRatio = viewportWidth / viewportHeight
181 
182     if (originalFullImageWidth < viewportWidth && originalFullImageHeight < viewportHeight) {
183       this._imgScaleFactor = maxScaleFactor
184 
185     } else if (imageAspectRatio < viewportAspectRatio) {
186       this._imgScaleFactor = (viewportHeight / originalFullImageHeight) * maxScaleFactor
187 
188     } else {
189       this._imgScaleFactor = (viewportWidth / originalFullImageWidth) * maxScaleFactor
190     }
191   }
192 
193   Zoom.prototype._triggerAnimation = function () {
194     console.log('放大的时候触发')
195     this._targetImage.offsetWidth // repaint before animating
196 
197     var imageOffset = $(this._targetImage).offset()
198     var scrollTop   = $(window).scrollTop()
199 
200     var viewportY = scrollTop + ($(window).height() / 2)
201     var viewportX = ($(window).width() / 2)
202 
203     var imageCenterY = imageOffset.top + (this._targetImage.height / 2)
204     var imageCenterX = imageOffset.left + (this._targetImage.width / 2)
205 
206     this._translateY = viewportY - imageCenterY
207     this._translateX = viewportX - imageCenterX
208 
209     var targetTransform = 'scale(' + this._imgScaleFactor + ')'
210     var imageWrapTransform = 'translate(' + this._translateX + 'px, ' + this._translateY + 'px)'
211 
212     if ($.support.transition) {
213       imageWrapTransform += ' translateZ(0)'
214     }
215 
216     $(this._targetImage)
217       .css({
218         '-webkit-transform': targetTransform,
219             '-ms-transform': targetTransform,
220                 'transform': targetTransform
221       })
222 
223     $(this._targetImageWrap)
224       .css({
225         '-webkit-transform': imageWrapTransform,
226             '-ms-transform': imageWrapTransform,
227                 'transform': imageWrapTransform
228       })
229 
230     this._$body.addClass('zoom-overlay-open')
231   }
232 
233   Zoom.prototype.close = function () {
234     console.log('缩回的时候出发1');
235     this._$body
236       .removeClass('zoom-overlay-open')
237       .addClass('zoom-overlay-transitioning')
238 
239     // we use setStyle here so that the correct vender prefix for transform is used
240     $(this._targetImage)
241       .css({
242         '-webkit-transform': '',
243             '-ms-transform': '',
244                 'transform': ''
245       })
246 
247     $(this._targetImageWrap)
248       .css({
249         '-webkit-transform': '',
250             '-ms-transform': '',
251                 'transform': ''
252       })
253 
254     if (!$.support.transition) {
255       return this.dispose()
256     }
257 
258     $(this._targetImage)
259       .one($.support.transition.end, $.proxy(this.dispose, this))
260       .emulateTransitionEnd(300)
261   }
262 
263   Zoom.prototype.dispose = function () {
264     console.log('缩回的时候出发2')
265     if (this._targetImageWrap && this._targetImageWrap.parentNode) {
266       $(this._targetImage)
267         .removeClass('zoom-img')
268         .attr('data-action', 'zoom')
269 
270       this._targetImageWrap.parentNode.replaceChild(this._targetImage, this._targetImageWrap)
271       this._overlay.parentNode.removeChild(this._overlay)
272 
273       this._$body.removeClass('zoom-overlay-transitioning')
274     }
275   }
276 
277   // wait for dom ready (incase script included before body)
278   $(function () {
279     new ZoomService().listen()
280   })
281 
282 }(jQuery)
原文地址:https://www.cnblogs.com/fpcing/p/11270740.html