UNPKG

react-native-image-gallery

Version:

Pure JavaScript image gallery component for iOS and Android

162 lines (140 loc) 4.58 kB
import Rect from './Rect'; export { Rect }; export class Transform { constructor (scale, translateX, translateY, pivot) { this.scale = scale; this.translateX = translateX; this.translateY = translateY; this.pivot = pivot; } } function isValidNumber (number) { if (typeof number === 'number') { if (!isNaN(number)) { return true; } } return false; } function isValidRect (rect) { if (rect instanceof Rect && rect.isValid()) { return true; } return false; } function isValidTransform (transform) { if (transform && isValidNumber(transform.scale) && isValidNumber(transform.translateX) && isValidNumber(transform.translateY)) { return true; } return false; } export function fitCenterRect (contentAspectRatio, containerRect) { let w = containerRect.width(); let h = containerRect.height(); let viewAspectRatio = w / h; if (contentAspectRatio > viewAspectRatio) { h = w / contentAspectRatio; } else { w = h * contentAspectRatio; } return new Rect( containerRect.centerX() - w / 2, containerRect.centerY() - h / 2, containerRect.centerX() + w / 2, containerRect.centerY() + h / 2 ); } /** * The React Native transform system use the center of the view as the pivot when scaling. * The translations are applied before scaling. * @param rect * @param transform * @returns {*} */ export function transformedRect (rect, transform) { if (!isValidRect(rect)) { throw new Error('transformedRect...invalid rect'); } if (!isValidTransform(transform)) { throw new Error('transformedRect...invalid transform'); } let scale = transform.scale; let translateX = transform.translateX; let translateY = transform.translateY; let pivot = transform.pivot; if (pivot === undefined || pivot === null) { let width = rect.width() * scale; let height = rect.height() * scale; let centerX = rect.centerX() + translateX * scale; let centerY = rect.centerY() + translateY * scale; return new Rect( centerX - width / 2, centerY - height / 2, centerX + width / 2, centerY + height / 2 ); } else { let pivotX = pivot.x; let pivotY = pivot.y; if (!isValidNumber(pivotX) || !isValidNumber(pivotY)) { throw new Error('transformedRect...invalid pivot x=' + pivot.x + ', y=' + pivot.y); } // first make the center still let resultRect = transformedRect(rect, { scale, translateX, translateY }); // the pivot moved during scaling, now move it back let dx = (scale - 1) * (pivotX - resultRect.centerX()); let dy = (scale - 1) * (pivotY - resultRect.centerY()); return resultRect.offset(-dx, -dy); } } /** * Calculate the transform from fromRect to toRect * @param fromRect * @param toRect * @returns {Transform} */ export function getTransform (fromRect, toRect) { let scale = toRect.width() / fromRect.width(); let translateX = (toRect.centerX() - fromRect.centerX()) / scale; let translateY = (toRect.centerY() - fromRect.centerY()) / scale; return new Transform(scale, translateX, translateY); } /** * Align edges of the rect with the viewport to avoid unnecessary blank space. NO scaling is performed here. * @param rect * @param viewPortRect * @returns {*|{line, column}|{column, line}|{x}} */ export function alignedRect (rect, viewPortRect) { let dx = 0; let dy = 0; if (rect.width() > viewPortRect.width()) { if (rect.left > viewPortRect.left) { dx = viewPortRect.left - rect.left; } else if (rect.right < viewPortRect.right) { dx = viewPortRect.right - rect.right; } } else { dx = viewPortRect.centerX() - rect.centerX(); } if (rect.height() > viewPortRect.height()) { if (rect.top > viewPortRect.top) { dy = viewPortRect.top - rect.top; } else if (rect.bottom < viewPortRect.bottom) { dy = viewPortRect.bottom - rect.bottom; } } else { dy = viewPortRect.centerY() - rect.centerY(); } return rect.copy().offset(dx, dy); } export function availableTranslateSpace (rect, viewPortRect) { return { left: viewPortRect.left - rect.left, right: rect.right - viewPortRect.right, top: viewPortRect.top - rect.top, bottom: rect.bottom - viewPortRect.bottom }; }