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)
手机扫一扫
移动阅读更方便
你可能感兴趣的文章