mirror of
				https://github.com/superseriousbusiness/gotosocial.git
				synced 2025-10-31 02:12:24 -05:00 
			
		
		
		
	
		
			
	
	
		
			120 lines
		
	
	
	
		
			3.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			120 lines
		
	
	
	
		
			3.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | /* | ||
|  | 	GoToSocial | ||
|  | 	Copyright (C) GoToSocial Authors admin@gotosocial.org | ||
|  | 	SPDX-License-Identifier: AGPL-3.0-or-later | ||
|  | 
 | ||
|  | 	This program is free software: you can redistribute it and/or modify | ||
|  | 	it under the terms of the GNU Affero General Public License as published by | ||
|  | 	the Free Software Foundation, either version 3 of the License, or | ||
|  | 	(at your option) any later version. | ||
|  | 
 | ||
|  | 	This program is distributed in the hope that it will be useful, | ||
|  | 	but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
|  | 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||
|  | 	GNU Affero General Public License for more details. | ||
|  | 
 | ||
|  | 	You should have received a copy of the GNU Affero General Public License | ||
|  | 	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||
|  | */ | ||
|  | 
 | ||
|  | /* | ||
|  | 	Code in this file adapted from: | ||
|  | 	https://github.com/vovayatsyuk/photoswipe-object-position (MIT License).
 | ||
|  | */ | ||
|  | 
 | ||
|  | function getCroppedBoundsOffset(position, imageSize, thumbSize, zoomLevel) { | ||
|  | 	const float = parseFloat(position);  | ||
|  | 	return position.indexOf('%') > 0 | ||
|  | 		? (thumbSize - imageSize * zoomLevel) * float / 100 | ||
|  | 		: float; | ||
|  | } | ||
|  |   | ||
|  | function getCroppedZoomPan(position, min, max) { | ||
|  | 	const float = parseFloat(position); | ||
|  | 	return position.indexOf('%') > 0 ? min + (max - min) * float / 100 : float; | ||
|  | } | ||
|  | 
 | ||
|  | function getThumbnail(el) { | ||
|  | 	return el.querySelector('img'); | ||
|  | } | ||
|  | 
 | ||
|  | function getObjectPosition(el) { | ||
|  | 	return getComputedStyle(el).getPropertyValue('object-position').split(' '); | ||
|  | } | ||
|  | 
 | ||
|  | export default class ObjectPosition { | ||
|  | 	constructor(lightbox) { | ||
|  | 		/** | ||
|  | 		* Make pan adjustments if large image doesn't fit the viewport. | ||
|  | 		* | ||
|  | 		* Examples: | ||
|  | 		* 1. When thumb object-position is 50% 0 (top part is initially visible) | ||
|  | 		*    make sure you'll see the top part of the large image as well. | ||
|  | 		* 2. When thumb object-position is 50% 100% (bottom part is initially visible) | ||
|  | 		*    make sure you'll see the bottom part of the large image as well. | ||
|  | 		*/ | ||
|  | 		lightbox.on('initialZoomPan', (event) => { | ||
|  | 			const slide = event.slide; | ||
|  | 			if (!slide.data.element) { | ||
|  | 				// No thumbnail
 | ||
|  | 				// image set.
 | ||
|  | 				return; | ||
|  | 			} | ||
|  | 			 | ||
|  | 			const thumbnailImg = getThumbnail(slide.data.element); | ||
|  | 			if (!thumbnailImg) { | ||
|  | 				// No thumbnail
 | ||
|  | 				// image set.
 | ||
|  | 				return; | ||
|  | 			} | ||
|  | 
 | ||
|  | 			const [positionX, positionY] = getObjectPosition(thumbnailImg); | ||
|  | 
 | ||
|  | 			if (positionX !== '50%' && slide.pan.x < 0) { | ||
|  | 				slide.pan.x = getCroppedZoomPan(positionX, slide.bounds.min.x, slide.bounds.max.x); | ||
|  | 			} | ||
|  |   | ||
|  | 			if (positionY !== '50%' && slide.pan.y < 0) { | ||
|  | 				slide.pan.y = getCroppedZoomPan(positionY, slide.bounds.min.y, slide.bounds.max.y); | ||
|  | 			} | ||
|  | 		}); | ||
|  | 
 | ||
|  | 		/** | ||
|  | 		* Fix opening animation when thumb object-position is not 50% 50%. | ||
|  | 		* https://github.com/dimsemenov/PhotoSwipe/pull/1868
 | ||
|  | 		*/ | ||
|  | 		lightbox.addFilter('thumbBounds', (thumbBounds, itemData) => { | ||
|  | 			if (!itemData.element) { | ||
|  | 				// No thumbnail
 | ||
|  | 				// image set.
 | ||
|  | 				return; | ||
|  | 			} | ||
|  | 			 | ||
|  | 			const thumbnailImg = getThumbnail(itemData.element); | ||
|  | 			if (!thumbnailImg) { | ||
|  | 				// No thumbnail
 | ||
|  | 				// image set.
 | ||
|  | 				return; | ||
|  | 			} | ||
|  | 
 | ||
|  | 			const thumbAreaRect = thumbnailImg.getBoundingClientRect(); | ||
|  | 			const fillZoomLevel = thumbBounds.w / itemData.width; | ||
|  | 			const [positionX, positionY] = getObjectPosition(thumbnailImg); | ||
|  | 
 | ||
|  | 			if (positionX !== '50%') { | ||
|  | 				const offsetX = getCroppedBoundsOffset(positionX, itemData.width, thumbAreaRect.width, fillZoomLevel); | ||
|  | 				thumbBounds.x = thumbAreaRect.left + offsetX; | ||
|  | 				thumbBounds.innerRect.x = offsetX; | ||
|  | 			} | ||
|  | 
 | ||
|  | 			if (positionY !== '50%') { | ||
|  | 				const offsetY = getCroppedBoundsOffset(positionY, itemData.height, thumbAreaRect.height, fillZoomLevel); | ||
|  | 				thumbBounds.y = thumbAreaRect.top + offsetY; | ||
|  | 				thumbBounds.innerRect.y = offsetY; | ||
|  | 			} | ||
|  | 
 | ||
|  | 			return thumbBounds; | ||
|  | 		}); | ||
|  | 	} | ||
|  | } |