diff --git a/src/place_building_blocks/place_photo_gallery/place_photo_gallery.ts b/src/place_building_blocks/place_photo_gallery/place_photo_gallery.ts index 2605c47..3b995ce 100644 --- a/src/place_building_blocks/place_photo_gallery/place_photo_gallery.ts +++ b/src/place_building_blocks/place_photo_gallery/place_photo_gallery.ts @@ -42,6 +42,16 @@ interface TileSize { heightPx: number; } +/** + * Returns the desired photo size in pixels based on CSS pixels and max size, + * accounting for diff between physical and CSS pixels on current device; see: + * https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio. + */ +function getPhotoSize(cssPx: number, max: number) { + const devicePx = Math.ceil(cssPx * window.devicePixelRatio); + return devicePx ? Math.min(devicePx, max) : max; +} + /** * Formats a `google.maps.places.Photo` object for display based on tile size. * @@ -60,23 +70,19 @@ interface TileSize { */ function formatPhoto(photo: Photo, tileSize: TileSize): FormattedPhoto { const photoSizeRatio = photo.widthPx / photo.heightPx; + const windowSizeRatio = window.innerWidth / window.innerHeight; const tileSizeRatio = tileSize.widthPx / tileSize.heightPx; - // Account for diff between physical and CSS pixels on current device; see: - // https://developer.mozilla.org/en-US/docs/Web/API/Window/devicePixelRatio. + const lightboxPhotoOptions = photoSizeRatio > windowSizeRatio ? + {maxHeight: getPhotoSize(window.innerHeight, MAX_PHOTO_SIZE_PX)} : + {maxWidth: getPhotoSize(window.innerWidth, MAX_PHOTO_SIZE_PX)}; const tilePhotoOptions = photoSizeRatio > tileSizeRatio ? - {maxHeight: Math.ceil(tileSize.heightPx * window.devicePixelRatio)} : - {maxWidth: Math.ceil(tileSize.widthPx * window.devicePixelRatio)}; + {maxHeight: getPhotoSize(tileSize.heightPx, MAX_TILE_PHOTO_SIZE_PX)} : + {maxWidth: getPhotoSize(tileSize.widthPx, MAX_TILE_PHOTO_SIZE_PX)}; return { - uri: photo.getURI({ - maxHeight: MAX_PHOTO_SIZE_PX, - maxWidth: MAX_PHOTO_SIZE_PX, - }), - tileUri: photo.getURI({ - maxHeight: tilePhotoOptions.maxHeight || MAX_TILE_PHOTO_SIZE_PX, - maxWidth: tilePhotoOptions.maxWidth || MAX_TILE_PHOTO_SIZE_PX, - }), + uri: photo.getURI(lightboxPhotoOptions), + tileUri: photo.getURI(tilePhotoOptions), attributions: photo.authorAttributions, }; } diff --git a/src/place_building_blocks/place_photo_gallery/place_photo_gallery_test.ts b/src/place_building_blocks/place_photo_gallery/place_photo_gallery_test.ts index b2ab15a..0cdc78a 100644 --- a/src/place_building_blocks/place_photo_gallery/place_photo_gallery_test.ts +++ b/src/place_building_blocks/place_photo_gallery/place_photo_gallery_test.ts @@ -16,7 +16,6 @@ import type {Place, PlaceResult} from '../../utils/googlemaps_types.js'; import {PlacePhotoGallery} from './place_photo_gallery.js'; - const fakePlace = makeFakePlace({ id: '1234567890', displayName: 'Place Name', @@ -161,10 +160,12 @@ describe('PlacePhotoGallery', () => { const {tiles} = await prepareState({place: fakePlace}); expect(tiles.length).toBe(3); - expect(getUri0Spy).toHaveBeenCalledWith({maxHeight: 4800, maxWidth: 4800}); - expect(getUri0Spy).toHaveBeenCalledWith({maxHeight: 134, maxWidth: 1200}); - expect(getUri1Spy).toHaveBeenCalledWith({maxHeight: 1200, maxWidth: 142}); - expect(getUri2Spy).toHaveBeenCalledWith({maxHeight: 1200, maxWidth: 142}); + expect(getUri0Spy).toHaveBeenCalledWith({maxHeight: window.innerHeight}); + expect(getUri0Spy).toHaveBeenCalledWith({maxHeight: 134}); + expect(getUri1Spy).toHaveBeenCalledWith({maxWidth: window.innerWidth}); + expect(getUri1Spy).toHaveBeenCalledWith({maxWidth: 142}); + expect(getUri2Spy).toHaveBeenCalledWith({maxWidth: window.innerWidth}); + expect(getUri2Spy).toHaveBeenCalledWith({maxWidth: 142}); expect(getComputedStyle(tiles[0]).backgroundImage) .toBe('url("https://lh3.googleusercontent.com/places/A")'); expect(getComputedStyle(tiles[1]).backgroundImage) @@ -184,10 +185,12 @@ describe('PlacePhotoGallery', () => { const {tiles} = await prepareState({place: fakePlaceResult}); expect(tiles.length).toBe(3); - expect(getUrl0Spy).toHaveBeenCalledWith({maxHeight: 4800, maxWidth: 4800}); - expect(getUrl0Spy).toHaveBeenCalledWith({maxHeight: 134, maxWidth: 1200}); - expect(getUrl1Spy).toHaveBeenCalledWith({maxHeight: 1200, maxWidth: 142}); - expect(getUrl2Spy).toHaveBeenCalledWith({maxHeight: 1200, maxWidth: 142}); + expect(getUrl0Spy).toHaveBeenCalledWith({maxHeight: window.innerHeight}); + expect(getUrl0Spy).toHaveBeenCalledWith({maxHeight: 134}); + expect(getUrl1Spy).toHaveBeenCalledWith({maxWidth: window.innerWidth}); + expect(getUrl1Spy).toHaveBeenCalledWith({maxWidth: 142}); + expect(getUrl2Spy).toHaveBeenCalledWith({maxWidth: window.innerWidth}); + expect(getUrl2Spy).toHaveBeenCalledWith({maxWidth: 142}); expect(getComputedStyle(tiles[0]).backgroundImage) .toBe('url("https://lh3.googleusercontent.com/places/A")'); expect(getComputedStyle(tiles[1]).backgroundImage)