@@ -189,9 +189,6 @@ class ReactImageLightbox extends Component {
189189
190190 // Change zoom level
191191 changeZoom ( zoomLevel , clientX , clientY ) {
192- const windowWidth = getWindowWidth ( ) ;
193- const windowHeight = getWindowHeight ( ) ;
194-
195192 // Constrain zoom level to the set bounds
196193 const nextZoomLevel = Math . max ( MIN_ZOOM_LEVEL , Math . min ( MAX_ZOOM_LEVEL , zoomLevel ) ) ;
197194
@@ -207,21 +204,31 @@ class ReactImageLightbox extends Component {
207204 } ) ;
208205 }
209206
207+ const imageBaseSize = this . getBestImageForType ( 'mainSrc' ) ;
208+ if ( imageBaseSize === null ) {
209+ return ;
210+ }
211+
210212 const currentZoomMultiplier = this . getZoomMultiplier ( ) ;
211213 const nextZoomMultiplier = this . getZoomMultiplier ( nextZoomLevel ) ;
212214
213- // Default to the center of the screen to zoom when no mouse position specified
214- const percentXInCurrentBox = ( typeof clientX !== 'undefined' ? clientX : windowWidth / 2 ) / windowWidth ;
215- const percentYInCurrentBox = ( typeof clientY !== 'undefined' ? clientY : windowHeight / 2 ) / windowHeight ;
215+ // Default to the center of the image to zoom when no mouse position specified
216+ const boxRect = this . getLightboxRect ( ) ;
217+ const percentXInCurrentBox = typeof clientX !== 'undefined' ?
218+ ( ( clientX - boxRect . left - ( ( boxRect . width - imageBaseSize . width ) / 2 ) ) / imageBaseSize . width ) :
219+ 0.5 ;
220+ const percentYInCurrentBox = typeof clientY !== 'undefined' ?
221+ ( ( clientY - boxRect . top - ( ( boxRect . height - imageBaseSize . height ) / 2 ) ) / imageBaseSize . height ) :
222+ 0.5 ;
216223
217- const currentBoxWidth = windowWidth / currentZoomMultiplier ;
218- const currentBoxHeight = windowHeight / currentZoomMultiplier ;
224+ const currentImageWidth = imageBaseSize . width * currentZoomMultiplier ;
225+ const currentImageHeight = imageBaseSize . height * currentZoomMultiplier ;
219226
220- const nextBoxWidth = windowWidth / nextZoomMultiplier ;
221- const nextBoxHeight = windowHeight / nextZoomMultiplier ;
227+ const nextImageWidth = imageBaseSize . width * nextZoomMultiplier ;
228+ const nextImageHeight = imageBaseSize . height * nextZoomMultiplier ;
222229
223- const deltaX = ( nextBoxWidth - currentBoxWidth ) * ( percentXInCurrentBox - 0.5 ) ;
224- const deltaY = ( nextBoxHeight - currentBoxHeight ) * ( percentYInCurrentBox - 0.5 ) ;
230+ const deltaX = ( currentImageWidth - nextImageWidth ) * ( percentXInCurrentBox - 0.5 ) ;
231+ const deltaY = ( currentImageHeight - nextImageHeight ) * ( percentYInCurrentBox - 0.5 ) ;
225232
226233 let nextOffsetX = this . state . offsetX - deltaX ;
227234 let nextOffsetY = this . state . offsetY - deltaY ;
@@ -287,10 +294,9 @@ class ReactImageLightbox extends Component {
287294
288295 // Get sizing for when an image is larger than the window
289296 getFitSizes ( width , height , stretch ) {
290- const windowHeight = getWindowHeight ( ) ;
291- const windowWidth = getWindowWidth ( ) ;
292- let maxHeight = windowHeight - ( this . props . imagePadding * 2 ) ;
293- let maxWidth = windowWidth - ( this . props . imagePadding * 2 ) ;
297+ const boxSize = this . getLightboxRect ( ) ;
298+ let maxHeight = boxSize . height - ( this . props . imagePadding * 2 ) ;
299+ let maxWidth = boxSize . width - ( this . props . imagePadding * 2 ) ;
294300
295301 if ( ! stretch ) {
296302 maxHeight = Math . min ( maxHeight , height ) ;
@@ -300,16 +306,17 @@ class ReactImageLightbox extends Component {
300306 const maxRatio = maxWidth / maxHeight ;
301307 const srcRatio = width / height ;
302308
303- const fitSizes = { } ;
304309 if ( maxRatio > srcRatio ) { // height is the constraining dimension of the photo
305- fitSizes . width = width * maxHeight / height ;
306- fitSizes . height = maxHeight ;
307- } else {
308- fitSizes . width = maxWidth ;
309- fitSizes . height = height * maxWidth / width ;
310+ return {
311+ width : width * maxHeight / height ,
312+ height : maxHeight ,
313+ } ;
310314 }
311315
312- return fitSizes ;
316+ return {
317+ width : maxWidth ,
318+ height : height * maxWidth / width ,
319+ } ;
313320 }
314321
315322 getMaxOffsets ( zoomLevel = this . state . zoomLevel ) {
@@ -318,24 +325,23 @@ class ReactImageLightbox extends Component {
318325 return { maxX : 0 , minX : 0 , maxY : 0 , minY : 0 } ;
319326 }
320327
321- const windowWidth = getWindowWidth ( ) ;
322- const windowHeight = getWindowHeight ( ) ;
328+ const boxSize = this . getLightboxRect ( ) ;
323329 const zoomMultiplier = this . getZoomMultiplier ( zoomLevel ) ;
324330
325331 let maxX = 0 ;
326- if ( currentImageInfo . width - ( windowWidth / zoomMultiplier ) < 0 ) {
332+ if ( ( zoomMultiplier * currentImageInfo . width ) - boxSize . width < 0 ) {
327333 // if there is still blank space in the X dimension, don't limit except to the opposite edge
328- maxX = ( ( windowWidth / zoomMultiplier ) - currentImageInfo . width ) / 2 ;
334+ maxX = ( boxSize . width - ( zoomMultiplier * currentImageInfo . width ) ) / 2 ;
329335 } else {
330- maxX = ( currentImageInfo . width - ( windowWidth / zoomMultiplier ) ) / 2 ;
336+ maxX = ( ( zoomMultiplier * currentImageInfo . width ) - boxSize . width ) / 2 ;
331337 }
332338
333339 let maxY = 0 ;
334- if ( currentImageInfo . height - ( windowHeight / zoomMultiplier ) < 0 ) {
340+ if ( ( zoomMultiplier * currentImageInfo . height ) - boxSize . height < 0 ) {
335341 // if there is still blank space in the Y dimension, don't limit except to the opposite edge
336- maxY = ( ( windowHeight / zoomMultiplier ) - currentImageInfo . height ) / 2 ;
342+ maxY = ( boxSize . height - ( zoomMultiplier * currentImageInfo . height ) ) / 2 ;
337343 } else {
338- maxY = ( currentImageInfo . height - ( windowHeight / zoomMultiplier ) ) / 2 ;
344+ maxY = ( ( zoomMultiplier * currentImageInfo . height ) - boxSize . height ) / 2 ;
339345 }
340346
341347 return {
@@ -346,16 +352,6 @@ class ReactImageLightbox extends Component {
346352 } ;
347353 }
348354
349- getOffsetXFromWindowCenter ( x ) {
350- const windowWidth = getWindowWidth ( ) ;
351- return ( windowWidth / 2 ) - x ;
352- }
353-
354- getOffsetYFromWindowCenter ( y ) {
355- const windowHeight = getWindowHeight ( ) ;
356- return ( windowHeight / 2 ) - y ;
357- }
358-
359355 // Get image src types
360356 getSrcTypes ( ) {
361357 return [
@@ -386,12 +382,34 @@ class ReactImageLightbox extends Component {
386382 ] ;
387383 }
388384
389- // Get sizing when the image is scaled
385+ /**
386+ * Get sizing when the image is scaled
387+ */
390388 getZoomMultiplier ( zoomLevel = this . state . zoomLevel ) {
391389 return Math . pow ( ZOOM_RATIO , zoomLevel ) ;
392390 }
393391
394- // Handle user keyboard actions
392+ /**
393+ * Get the size of the lightbox in pixels
394+ */
395+ getLightboxRect ( ) {
396+ if ( this . outerEl ) {
397+ return this . outerEl . getBoundingClientRect ( ) ;
398+ }
399+
400+ return {
401+ width : getWindowWidth ( ) ,
402+ height : getWindowHeight ( ) ,
403+ top : 0 ,
404+ right : 0 ,
405+ bottom : 0 ,
406+ left : 0 ,
407+ } ;
408+ }
409+
410+ /**
411+ * Handle user keyboard actions
412+ */
395413 handleKeyInput ( event ) {
396414 event . stopPropagation ( ) ;
397415
@@ -451,7 +469,9 @@ class ReactImageLightbox extends Component {
451469 }
452470 }
453471
454- // Handle a mouse wheel event over the lightbox container
472+ /**
473+ * Handle a mouse wheel event over the lightbox container
474+ */
455475 handleOuterMousewheel ( event ) {
456476 // Prevent scrolling of the background
457477 event . preventDefault ( ) ;
@@ -522,7 +542,9 @@ class ReactImageLightbox extends Component {
522542 }
523543 }
524544
525- // Handle a double click on the current image
545+ /**
546+ * Handle a double click on the current image
547+ */
526548 handleImageDoubleClick ( event ) {
527549 if ( this . state . zoomLevel > MIN_ZOOM_LEVEL ) {
528550 // A double click when zoomed in zooms all the way out
@@ -541,7 +563,9 @@ class ReactImageLightbox extends Component {
541563 }
542564 }
543565
544- // Handle a mouse click ending in the lightbox container
566+ /**
567+ * Handle a mouse click ending in the lightbox container
568+ */
545569 handleMouseUp ( ) {
546570 if ( ! this . isDragging ) {
547571 return ;
@@ -604,10 +628,8 @@ class ReactImageLightbox extends Component {
604628 return ;
605629 }
606630
607- const zoomMultiplier = this . getZoomMultiplier ( ) ;
608-
609- const newOffsetX = ( ( this . dragStartX - clientX ) / zoomMultiplier ) + this . dragStartOffsetX ;
610- const newOffsetY = ( ( this . dragStartY - clientY ) / zoomMultiplier ) + this . dragStartOffsetY ;
631+ const newOffsetX = ( this . dragStartX - clientX ) + this . dragStartOffsetX ;
632+ const newOffsetY = ( this . dragStartY - clientY ) + this . dragStartOffsetY ;
611633 if ( this . state . offsetX !== newOffsetX || this . state . offsetY !== newOffsetY ) {
612634 this . setState ( {
613635 offsetX : newOffsetX ,
@@ -782,16 +804,39 @@ class ReactImageLightbox extends Component {
782804 this . requestMove ( 'prev' , event ) ;
783805 }
784806
807+ // Request to transition to the previous image
808+ getTransform ( { x = null , y = null , zoom = null } ) {
809+ const isOldIE = _ieVersion < 10 ;
810+ const transforms = [ ] ;
811+ if ( x !== null || y !== null ) {
812+ transforms . push ( isOldIE ?
813+ `translate(${ x || 0 } px,${ y || 0 } px)` :
814+ `translate3d(${ x || 0 } px,${ y || 0 } px,0)`
815+ ) ;
816+ }
817+
818+ if ( zoom !== null ) {
819+ transforms . push ( isOldIE ?
820+ `scale(${ zoom } )` :
821+ `scale3d(${ zoom } ,${ zoom } ,1)`
822+ ) ;
823+ }
824+
825+ return {
826+ [ isOldIE ? 'msTransform' : 'transform' ] :
827+ transforms . length === 0 ? 'none' : transforms . join ( ' ' ) ,
828+ } ;
829+ }
830+
785831 render ( ) {
832+ const boxSize = this . getLightboxRect ( ) ;
786833 let transitionStyle = { } ;
787834
788835 // Transition settings for sliding animations
789836 if ( ! this . props . animationDisabled && this . isAnimating ( ) ) {
790837 transitionStyle = {
791838 ...transitionStyle ,
792- transition : [ 'transform' , 'left' , 'top' , 'right' , 'bottom' ]
793- . map ( x => `${ x } ${ this . props . animationDuration } ms` )
794- . join ( ', ' ) ,
839+ transition : `transform ${ this . props . animationDuration } ms` ,
795840 } ;
796841 }
797842
@@ -891,26 +936,28 @@ class ReactImageLightbox extends Component {
891936 } ;
892937
893938 const zoomMultiplier = this . getZoomMultiplier ( ) ;
894- const zoomStyle = _ieVersion < 10 ?
895- { msTransform : `scale(${ zoomMultiplier } )` } :
896- { transform : `scale3d(${ zoomMultiplier } , ${ zoomMultiplier } , 1)` } ;
897-
898939 // Next Image (displayed on the right)
899- addImage ( 'nextSrc' , `image-next ril-image-next ${ styles . imageNext } ` ) ;
940+ addImage (
941+ 'nextSrc' ,
942+ `image-next ril-image-next ${ styles . imageNext } ` ,
943+ this . getTransform ( { x : boxSize . width } )
944+ ) ;
900945 // Main Image
901946 addImage (
902947 'mainSrc' ,
903948 'image-current ril-image-current' ,
904- {
905- ...zoomStyle ,
906- left : - 1 * zoomMultiplier * this . state . offsetX ,
907- right : zoomMultiplier * this . state . offsetX ,
908- top : - 1 * zoomMultiplier * this . state . offsetY ,
909- bottom : zoomMultiplier * this . state . offsetY ,
910- }
949+ this . getTransform ( {
950+ x : - 1 * this . state . offsetX ,
951+ y : - 1 * this . state . offsetY ,
952+ zoom : zoomMultiplier ,
953+ } )
911954 ) ;
912955 // Previous Image (displayed on the left)
913- addImage ( 'prevSrc' , `image-prev ril-image-prev ${ styles . imagePrev } ` ) ;
956+ addImage (
957+ 'prevSrc' ,
958+ `image-prev ril-image-prev ${ styles . imagePrev } ` ,
959+ this . getTransform ( { x : - 1 * boxSize . width } )
960+ ) ;
914961
915962 const noop = ( ) => { } ;
916963
@@ -945,13 +992,14 @@ class ReactImageLightbox extends Component {
945992 backgroundColor : 'transparent' ,
946993 } ,
947994 content : {
948- backgroundColor : 'transparent' ,
949- border : 'none' ,
950- borderRadius : 0 ,
951- top : 0 ,
952- left : 0 ,
953- right : 0 ,
954- bottom : 0 ,
995+ overflow : 'hidden' , // Needed, otherwise keyboard shortcuts scroll the page
996+ border : 'none' ,
997+ borderRadius : 0 ,
998+ padding : 0 ,
999+ top : 0 ,
1000+ left : 0 ,
1001+ right : 0 ,
1002+ bottom : 0 ,
9551003 } ,
9561004 } ;
9571005
@@ -967,7 +1015,7 @@ class ReactImageLightbox extends Component {
9671015 return (
9681016 < Modal
9691017 isOpen
970- onRequestClose = { noop }
1018+ onRequestClose = { this . props . clickOutsideToClose ? this . requestClose : noop }
9711019 style = { modalStyle }
9721020 onAfterOpen = { ( ) => this . outerEl && this . outerEl . focus ( ) } // Focus on the div with key handlers
9731021 >
0 commit comments